diff options
832 files changed, 73336 insertions, 11706 deletions
diff --git a/.github/workflows/pull-request-management.yml b/.github/workflows/pull-request-management.yml new file mode 100644 index 000000000..3a855c107 --- /dev/null +++ b/.github/workflows/pull-request-management.yml @@ -0,0 +1,25 @@ +--- +name: Build Pull Request Package + +on: + pull_request: + branches: + - current + - crux + - equuleus + +jobs: + j2lint: + name: Validate j2 files + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + timeout-minutes: 2 + - name: Setup J2Lint + timeout-minutes: 2 + run: | + sudo pip install git+https://github.com/aristanetworks/j2lint.git@341b5d5db86e095b622f09770cb6367a1583620e + - name: Run J2lint + timeout-minutes: 2 + run: | + j2lint $GITHUB_WORKSPACE/data @@ -7,6 +7,8 @@ XDP_DIR := src/xdp LIBS := -lzmq CFLAGS := +J2LINT := $(shell command -v j2lint 2> /dev/null) + config_xml_src = $(wildcard interface-definitions/*.xml.in) config_xml_obj = $(config_xml_src:.xml.in=.xml) op_xml_src = $(wildcard op-mode-definitions/*.xml.in) @@ -29,9 +31,12 @@ interface_definitions: $(config_xml_obj) # XXX: delete top level node.def's that now live in other packages # IPSec VPN EAP-RADIUS does not support source-address rm -rf $(TMPL_DIR)/vpn/ipsec/remote-access/radius/source-address - # T3568: firewall is yet not migrated to XML and Python - this is only a dummy - rm -rf $(TMPL_DIR)/firewall/node.def - rm -rf $(TMPL_DIR)/nfirewall + + # T4284 neq QoS implementation is not yet live + find $(TMPL_DIR)/interfaces -name redirect -type d -exec rm -rf {} \; + rm -rf $(TMPL_DIR)/qos + rm -rf $(TMPL_DIR)/interfaces/input + # XXX: test if there are empty node.def files - this is not allowed as these # could mask help strings or mandatory priority statements find $(TMPL_DIR) -name node.def -type f -empty -exec false {} + || sh -c 'echo "There are empty node.def files! Check your interface definitions." && exit 1' @@ -55,9 +60,10 @@ op_mode_definitions: $(op_xml_obj) rm -f $(OP_TMPL_DIR)/show/node.def rm -f $(OP_TMPL_DIR)/show/system/node.def - # XXX: ping must be able to recursivly call itself as the + # XXX: ping and traceroute must be able to recursivly call itself as the # options are provided from the script itself ln -s ../node.tag $(OP_TMPL_DIR)/ping/node.tag/node.tag/ + ln -s ../node.tag $(OP_TMPL_DIR)/traceroute/node.tag/node.tag/ # XXX: test if there are empty node.def files - this is not allowed as these # could mask help strings or mandatory priority statements @@ -72,7 +78,18 @@ vyxdp: $(MAKE) -C $(XDP_DIR) .PHONY: all -all: clean interface_definitions op_mode_definitions vyshim +all: clean interface_definitions op_mode_definitions check test j2lint vyshim + +.PHONY: check +.ONESHELL: +check: + @echo "Checking which CLI scripts are not enabled to work with vyos-configd..." + @for file in `ls src/conf_mode -I__pycache__` + do + if ! grep -q $$file data/configd-include.json; then + echo "* $$file" + fi + done .PHONY: clean clean: @@ -87,6 +104,13 @@ test: set -e; python3 -m compileall -q -x '/vmware-tools/scripts/, /ppp/' . PYTHONPATH=python/ python3 -m "nose" --with-xunit src --with-coverage --cover-erase --cover-xml --cover-package src/conf_mode,src/op_mode,src/completion,src/helpers,src/validators,src/tests --verbose +.PHONY: j2lint +j2lint: +ifndef J2LINT + $(error "j2lint binary not found, consider installing: pip install git+https://github.com/aristanetworks/j2lint.git@341b5d5db86") +endif + $(J2LINT) data/ + .PHONY: sonar sonar: sonar-scanner -X -Dsonar.login=${SONAR_TOKEN} diff --git a/data/configd-include.json b/data/configd-include.json index 6893aaa86..5a4912e30 100644 --- a/data/configd-include.json +++ b/data/configd-include.json @@ -1,11 +1,18 @@ [ +"arp.py", "bcast_relay.py", +"container.py", "conntrack.py", "conntrack_sync.py", "dhcp_relay.py", +"dhcp_server.py", "dhcpv6_relay.py", +"dhcpv6_server.py", "dns_forwarding.py", "dynamic_dns.py", +"firewall.py", +"flow_accounting_conf.py", +"high-availability.py", "host_name.py", "https.py", "igmp_proxy.py", @@ -22,6 +29,7 @@ "interfaces-pppoe.py", "interfaces-pseudo-ethernet.py", "interfaces-tunnel.py", +"interfaces-vti.py", "interfaces-vxlan.py", "interfaces-wireguard.py", "interfaces-wireless.py", @@ -29,6 +37,7 @@ "lldp.py", "nat.py", "nat66.py", +"netns.py", "ntp.py", "pki.py", "policy.py", @@ -44,20 +53,27 @@ "protocols_pim.py", "protocols_rip.py", "protocols_ripng.py", +"protocols_rpki.py", "protocols_static.py", "protocols_static_multicast.py", +"qos.py", "salt-minion.py", "service_console-server.py", "service_ids_fastnetmon.py", "service_ipoe-server.py", "service_mdns-repeater.py", +"service_monitoring_telegraf.py", "service_pppoe-server.py", "service_router-advert.py", +"service_upnp.py", "ssh.py", "system-ip.py", "system-ipv6.py", "system-login-banner.py", +"system-logs.py", "system-option.py", +"system-proxy.py", +"system_sysctl.py", "system-syslog.py", "system-timezone.py", "system_console.py", @@ -68,6 +84,5 @@ "vpn_pptp.py", "vpn_sstp.py", "vrf.py", -"vrf_vni.py", -"vrrp.py" +"vrf_vni.py" ] diff --git a/data/templates/accel-ppp/chap-secrets.config_dict.tmpl b/data/templates/accel-ppp/chap-secrets.config_dict.j2 index da64b64d5..51e66d57c 100644 --- a/data/templates/accel-ppp/chap-secrets.config_dict.tmpl +++ b/data/templates/accel-ppp/chap-secrets.config_dict.j2 @@ -1,12 +1,10 @@ # username server password acceptable local IP addresses shaper -{% if authentication is defined and authentication.local_users is defined and authentication.local_users.username is defined %} -{% for user, user_config in authentication.local_users.username.items() %} -{% if user_config.disabled is not defined %} -{% if user_config.rate_limit is defined %} +{% if authentication.local_users.username is vyos_defined %} +{% for user, user_config in authentication.local_users.username.items() if user_config.disabled is not vyos_defined %} +{% if user_config.rate_limit is vyos_defined %} {{ "%-12s" | format(user) }} * {{ "%-16s" | format(user_config.password) }} {{ "%-16s" | format(user_config.static_ip) }} {{ user_config.rate_limit.download }}/{{ user_config.rate_limit.upload }} -{% else %} +{% else %} {{ "%-12s" | format(user) }} * {{ "%-16s" | format(user_config.password) }} {{ "%-16s" | format(user_config.static_ip) }} -{% endif %} -{% endif %} -{% endfor %} +{% endif %} +{% endfor %} {% endif %} diff --git a/data/templates/accel-ppp/chap-secrets.ipoe.tmpl b/data/templates/accel-ppp/chap-secrets.ipoe.j2 index 1df878fcf..a1430ec22 100644 --- a/data/templates/accel-ppp/chap-secrets.ipoe.tmpl +++ b/data/templates/accel-ppp/chap-secrets.ipoe.j2 @@ -1,18 +1,18 @@ # username server password acceptable local IP addresses shaper {% for interface in auth_interfaces %} -{% for mac in interface.mac %} -{% if mac.rate_upload and mac.rate_download %} -{% if mac.vlan_id %} +{% for mac in interface.mac %} +{% if mac.rate_upload and mac.rate_download %} +{% if mac.vlan_id %} {{ interface.name }}.{{ mac.vlan_id }} * {{ mac.address | lower }} * {{ mac.rate_download }}/{{ mac.rate_upload }} -{% else %} +{% else %} {{ interface.name }} * {{ mac.address | lower }} * {{ mac.rate_download }}/{{ mac.rate_upload }} -{% endif %} -{% else %} -{% if mac.vlan_id %} +{% endif %} +{% else %} +{% if mac.vlan_id %} {{ interface.name }}.{{ mac.vlan_id }} * {{ mac.address | lower }} * -{% else %} +{% else %} {{ interface.name }} * {{ mac.address | lower }} * -{% endif %} -{% endif %} -{% endfor %} +{% endif %} +{% endif %} +{% endfor %} {% endfor %} diff --git a/data/templates/accel-ppp/chap-secrets.tmpl b/data/templates/accel-ppp/chap-secrets.j2 index 6cace5401..cc3ddc28f 100644 --- a/data/templates/accel-ppp/chap-secrets.tmpl +++ b/data/templates/accel-ppp/chap-secrets.j2 @@ -1,10 +1,10 @@ # username server password acceptable local IP addresses shaper {% for user in local_users %} -{% if user.state == 'enabled' %} -{% if user.upload and user.download %} +{% if user.state == 'enabled' %} +{% if user.upload and user.download %} {{ "%-12s" | format(user.name) }} * {{ "%-16s" | format(user.password) }} {{ "%-16s" | format(user.ip) }} {{ user.download }}/{{ user.upload }} -{% else %} +{% else %} {{ "%-12s" | format(user.name) }} * {{ "%-16s" | format(user.password) }} {{ "%-16s" | format(user.ip) }} -{% endif %} -{% endif %} +{% endif %} +{% endif %} {% endfor %} diff --git a/data/templates/accel-ppp/config_chap_secrets_radius.j2 b/data/templates/accel-ppp/config_chap_secrets_radius.j2 index 49af3a228..bb820497b 100644 --- a/data/templates/accel-ppp/config_chap_secrets_radius.j2 +++ b/data/templates/accel-ppp/config_chap_secrets_radius.j2 @@ -1,33 +1,33 @@ -{% if authentication.mode is defined and authentication.mode == 'local' %} +{% if authentication.mode is vyos_defined('local') %} [chap-secrets] chap-secrets={{ chap_secrets_file }} -{% elif authentication.mode is defined and authentication.mode == 'radius' %} +{% elif authentication.mode is vyos_defined('radius') %} [radius] verbose=1 -{% for server, options in authentication.radius.server.items() if not options.disable is defined %} +{% for server, options in authentication.radius.server.items() if not options.disable is vyos_defined %} server={{ server }},{{ options.key }},auth-port={{ options.port }},acct-port={{ options.acct_port }},req-limit=0,fail-time={{ options.fail_time }} -{% endfor %} -{% if authentication.radius.acct_interim_jitter is defined and authentication.radius.acct_interim_jitter is not none %} +{% endfor %} +{% if authentication.radius.acct_interim_jitter is vyos_defined %} acct-interim-jitter={{ authentication.radius.acct_interim_jitter }} -{% endif %} +{% endif %} acct-timeout={{ authentication.radius.acct_timeout }} timeout={{ authentication.radius.timeout }} max-try={{ authentication.radius.max_try }} -{% if authentication.radius.nas_identifier is defined and authentication.radius.nas_identifier is not none %} +{% if authentication.radius.nas_identifier is vyos_defined %} nas-identifier={{ authentication.radius.nas_identifier }} -{% endif %} -{% if authentication.radius.nas_ip_address is defined and authentication.radius.nas_ip_address is not none %} +{% endif %} +{% if authentication.radius.nas_ip_address is vyos_defined %} nas-ip-address={{ authentication.radius.nas_ip_address }} -{% endif %} -{% if authentication.radius.source_address is defined and authentication.radius.source_address is not none %} +{% endif %} +{% if authentication.radius.source_address is vyos_defined %} bind={{ authentication.radius.source_address }} -{% endif %} -{% if authentication.radius.dynamic_author.server is defined and authentication.radius.dynamic_author.server is not none %} +{% endif %} +{% if authentication.radius.dynamic_author.server is vyos_defined %} dae-server={{ authentication.radius.dynamic_author.server }}:{{ authentication.radius.dynamic_author.port }},{{ authentication.radius.dynamic_author.key }} -{% endif %} +{% endif %} {% endif %} {# Both chap-secrets and radius block required the gw-ip-address #} -{% if gateway_address is defined and gateway_address is not none %} +{% if gateway_address is vyos_defined %} gw-ip-address={{ gateway_address }} {% endif %} diff --git a/data/templates/accel-ppp/config_ip_pool.j2 b/data/templates/accel-ppp/config_ip_pool.j2 index 3b0f68084..0bef4ad69 100644 --- a/data/templates/accel-ppp/config_ip_pool.j2 +++ b/data/templates/accel-ppp/config_ip_pool.j2 @@ -1,14 +1,14 @@ -{% if client_ip_pool is defined and client_ip_pool is not none %} +{% if client_ip_pool is vyos_defined %} [ip-pool] -{% if gateway_address is defined and gateway_address is not none %} +{% if gateway_address is vyos_defined %} gw-ip-address={{ gateway_address }} -{% endif %} -{% if client_ip_pool.start is defined and client_ip_pool.stop is defined and client_ip_pool.start is not none and client_ip_pool.stop is not none %} +{% endif %} +{% if client_ip_pool.start is vyos_defined and client_ip_pool.stop is vyos_defined %} {{ client_ip_pool.start }}-{{ client_ip_pool.stop.split('.')[3] }} -{% endif %} -{% if client_ip_pool.subnet is defined and client_ip_pool.subnet is not none %} -{% for subnet in client_ip_pool.subnet %} +{% endif %} +{% if client_ip_pool.subnet is vyos_defined %} +{% for subnet in client_ip_pool.subnet %} {{ subnet }} -{% endfor %} -{% endif %} +{% endfor %} +{% endif %} {% endif %} diff --git a/data/templates/accel-ppp/config_ipv6_pool.j2 b/data/templates/accel-ppp/config_ipv6_pool.j2 index f45bf9442..953469577 100644 --- a/data/templates/accel-ppp/config_ipv6_pool.j2 +++ b/data/templates/accel-ppp/config_ipv6_pool.j2 @@ -1,20 +1,20 @@ -{% if client_ipv6_pool is defined and client_ipv6_pool is not none %} +{% if client_ipv6_pool is vyos_defined %} [ipv6-nd] AdvAutonomousFlag=1 -{% if client_ipv6_pool.prefix is defined and client_ipv6_pool.prefix is not none %} +{% if client_ipv6_pool.prefix is vyos_defined %} [ipv6-pool] -{% for prefix, options in client_ipv6_pool.prefix.items() %} +{% for prefix, options in client_ipv6_pool.prefix.items() %} {{ prefix }},{{ options.mask }} -{% endfor %} -{% if client_ipv6_pool.delegate is defined and client_ipv6_pool.delegate is not none %} -{% for prefix, options in client_ipv6_pool.delegate.items() %} +{% endfor %} +{% if client_ipv6_pool.delegate is vyos_defined %} +{% for prefix, options in client_ipv6_pool.delegate.items() %} delegate={{ prefix }},{{ options.delegation_prefix }} -{% endfor %} +{% endfor %} +{% endif %} {% endif %} -{% endif %} -{% if client_ipv6_pool.delegate is defined and client_ipv6_pool.delegate is not none %} +{% if client_ipv6_pool.delegate is vyos_defined %} [ipv6-dhcp] verbose=1 -{% endif %} +{% endif %} {% endif %} diff --git a/data/templates/accel-ppp/config_modules_auth_mode.j2 b/data/templates/accel-ppp/config_modules_auth_mode.j2 index e3d578b38..3fb8a011f 100644 --- a/data/templates/accel-ppp/config_modules_auth_mode.j2 +++ b/data/templates/accel-ppp/config_modules_auth_mode.j2 @@ -1,5 +1,5 @@ -{% if authentication is defined and authentication.mode is defined and authentication.mode == 'local' %} +{% if authentication.mode is vyos_defined('local') %} chap-secrets -{% elif authentication is defined and authentication.mode is defined and authentication.mode == 'radius' %} +{% elif authentication.mode is vyos_defined('radius') %} radius {% endif %} diff --git a/data/templates/accel-ppp/config_modules_auth_protocols.j2 b/data/templates/accel-ppp/config_modules_auth_protocols.j2 index 454d37792..285468406 100644 --- a/data/templates/accel-ppp/config_modules_auth_protocols.j2 +++ b/data/templates/accel-ppp/config_modules_auth_protocols.j2 @@ -1,10 +1,10 @@ {% for protocol in authentication.protocols %} {# this should be fixed in the CLI by a migrator #} -{% if protocol == 'chap' %} +{% if protocol == 'chap' %} auth_chap_md5 -{% elif protocol == 'mschap' %} +{% elif protocol == 'mschap' %} auth_mschap_v1 -{% else %} +{% else %} auth_{{ protocol.replace('-', '_') }} -{% endif %} +{% endif %} {% endfor %} diff --git a/data/templates/accel-ppp/config_modules_ipv6.j2 b/data/templates/accel-ppp/config_modules_ipv6.j2 index 02740ce7c..6174779a5 100644 --- a/data/templates/accel-ppp/config_modules_ipv6.j2 +++ b/data/templates/accel-ppp/config_modules_ipv6.j2 @@ -1,4 +1,4 @@ -{% if ppp_options.ipv6 is defined and ppp_options.ipv6 != 'deny' %} +{% if ppp_options.ipv6 is vyos_defined and ppp_options.ipv6 is not vyos_defined('deny') %} ipv6pool ipv6_nd ipv6_dhcp diff --git a/data/templates/accel-ppp/config_name_server.j2 b/data/templates/accel-ppp/config_name_server.j2 index 2bf064f92..9c745fe62 100644 --- a/data/templates/accel-ppp/config_name_server.j2 +++ b/data/templates/accel-ppp/config_name_server.j2 @@ -1,13 +1,13 @@ -{% if name_server_ipv4 is defined and name_server_ipv4 is not none %} +{% if name_server_ipv4 is vyos_defined %} [dns] -{% for ns in name_server_ipv4 %} +{% for ns in name_server_ipv4 %} dns{{ loop.index }}={{ ns }} -{% endfor %} +{% endfor %} {% endif %} -{% if name_server_ipv6 is defined and name_server_ipv6 is not none %} +{% if name_server_ipv6 is vyos_defined %} [ipv6-dns] -{% for ns in name_server_ipv6 %} +{% for ns in name_server_ipv6 %} {{ ns }} -{% endfor %} +{% endfor %} {% endif %} diff --git a/data/templates/accel-ppp/config_shaper_radius.j2 b/data/templates/accel-ppp/config_shaper_radius.j2 index 8de5f5df3..942cdf132 100644 --- a/data/templates/accel-ppp/config_shaper_radius.j2 +++ b/data/templates/accel-ppp/config_shaper_radius.j2 @@ -1,10 +1,13 @@ -{% if authentication is defined and authentication.mode is defined and authentication.mode == 'radius' %} -{% if authentication is defined and authentication.radius is defined and authentication.radius.rate_limit is defined and authentication.radius.rate_limit.enable is defined %} +{% if authentication.mode is vyos_defined('radius') %} +{% if authentication.radius.rate_limit.enable is vyos_defined %} [shaper] verbose=1 attr={{ authentication.radius.rate_limit.attribute }} -{% if authentication.radius.rate_limit.vendor is defined and authentication.radius.rate_limit.vendor is not none %} +{% if authentication.radius.rate_limit.vendor is vyos_defined %} vendor={{ authentication.radius.rate_limit.vendor }} +{% endif %} +{% if authentication.radius.rate_limit.multiplier is vyos_defined %} +rate-multiplier={{ authentication.radius.rate_limit.multiplier }} +{% endif %} {% endif %} -{% endif %} {% endif %} diff --git a/data/templates/accel-ppp/ipoe.config.j2 b/data/templates/accel-ppp/ipoe.config.j2 new file mode 100644 index 000000000..3c0d47b27 --- /dev/null +++ b/data/templates/accel-ppp/ipoe.config.j2 @@ -0,0 +1,142 @@ +{# j2lint: disable=operator-enclosed-by-spaces #} +### generated by ipoe.py ### +[modules] +log_syslog +ipoe +shaper +ipv6pool +ipv6_nd +ipv6_dhcp +ippool +{% if auth_mode == 'radius' %} +radius +{% elif auth_mode == 'local' %} +chap-secrets +{% endif %} + +[core] +thread-count={{ thread_cnt }} + +[log] +syslog=accel-ipoe,daemon +copy=1 +level=5 + +[ipoe] +verbose=1 +{% for interface in interfaces %} +{% set tmp = 'interface=' %} +{% if interface.vlan_mon %} +{% set tmp = tmp ~ 're:' ~ interface.name ~ '\.\d+' %} +{% else %} +{% set tmp = tmp ~ interface.name %} +{% endif %} +{{ tmp }},shared={{ interface.shared }},mode={{ interface.mode }},ifcfg={{ interface.ifcfg }}{{ ',range=' ~ interface.range if interface.range is defined and interface.range is not none }},start={{ interface.sess_start }},ipv6=1 +{% endfor %} +{% if auth_mode == 'noauth' %} +noauth=1 +{% if client_named_ip_pool %} +{% for pool in client_named_ip_pool %} +{% if pool.subnet is defined %} +ip-pool={{ pool.name }} +{% endif %} +{% if pool.gateway_address is defined %} +gw-ip-address={{ pool.gateway_address }}/{{ pool.subnet.split('/')[1] }} +{% endif %} +{% endfor %} +{% endif %} +{% elif auth_mode == 'local' %} +username=ifname +password=csid +{% endif %} +proxy-arp=1 + +{% for interface in interfaces %} +{% if (interface.shared == '0') and (interface.vlan_mon) %} +vlan-mon={{ interface.name }},{{ interface.vlan_mon | join(',') }} +{% endif %} +{% endfor %} + +{% if dnsv4 %} +[dns] +{% for dns in dnsv4 %} +dns{{ loop.index }}={{ dns }} +{% endfor %} +{% endif %} + +{% if dnsv6 %} +[ipv6-dns] +{% for dns in dnsv6 %} +{{ dns }} +{% endfor %} +{% endif %} + +[ipv6-nd] +verbose=1 + +[ipv6-dhcp] +verbose=1 + +{% if client_named_ip_pool %} +[ip-pool] +{% for pool in client_named_ip_pool %} +{% if pool.subnet is defined %} +{{ pool.subnet }},name={{ pool.name }} +{% endif %} +{% if pool.gateway_address is defined %} +gw-ip-address={{ pool.gateway_address }}/{{ pool.subnet.split('/')[1] }} +{% endif %} +{% endfor %} +{% endif %} + +{% if client_ipv6_pool %} +[ipv6-pool] +{% for p in client_ipv6_pool %} +{{ p.prefix }},{{ p.mask }} +{% endfor %} +{% for p in client_ipv6_delegate_prefix %} +delegate={{ p.prefix }},{{ p.mask }} +{% endfor %} +{% endif %} + +{% if auth_mode == 'local' %} +[chap-secrets] +chap-secrets={{ chap_secrets_file }} +{% elif auth_mode == 'radius' %} +[radius] +verbose=1 +{% for r in radius_server %} +server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }} +{% endfor %} + +{% if radius_acct_inter_jitter %} +acct-interim-jitter={{ radius_acct_inter_jitter }} +{% endif %} + +acct-timeout={{ radius_acct_tmo }} +timeout={{ radius_timeout }} +max-try={{ radius_max_try }} +{% if radius_nas_id %} +nas-identifier={{ radius_nas_id }} +{% endif %} +{% if radius_nas_ip %} +nas-ip-address={{ radius_nas_ip }} +{% endif %} +{% if radius_source_address %} +bind={{ radius_source_address }} +{% endif %} +{% if radius_dynamic_author %} +dae-server={{ radius_dynamic_author.server }}:{{ radius_dynamic_author.port }},{{ radius_dynamic_author.key }} +{% endif %} +{% if radius_shaper_attr %} +[shaper] +verbose=1 +attr={{ radius_shaper_attr }} +{% if radius_shaper_vendor %} +vendor={{ radius_shaper_vendor }} +{% endif %} +{% endif %} +{% endif %} + +[cli] +tcp=127.0.0.1:2002 diff --git a/data/templates/accel-ppp/ipoe.config.tmpl b/data/templates/accel-ppp/ipoe.config.tmpl deleted file mode 100644 index 1cf2ab0be..000000000 --- a/data/templates/accel-ppp/ipoe.config.tmpl +++ /dev/null @@ -1,116 +0,0 @@ -### generated by ipoe.py ### -[modules] -log_syslog -ipoe -shaper -ipv6pool -ipv6_nd -ipv6_dhcp -ippool -{% if auth_mode == 'radius' %} -radius -{% elif auth_mode == 'local' %} -chap-secrets -{% endif %} - -[core] -thread-count={{ thread_cnt }} - -[log] -syslog=accel-ipoe,daemon -copy=1 -level=5 - -[ipoe] -verbose=1 -{% for interface in interfaces %} -{% if interface.vlan_mon %} -interface=re:{{ interface.name }}\.\d+,{% else %}interface={{ interface.name }},{% endif %}shared={{ interface.shared }},mode={{ interface.mode }},ifcfg={{ interface.ifcfg }},range={{ interface.range }},start={{ interface.sess_start }},ipv6=1 -{% endfor %} -{% if auth_mode == 'noauth' %} -noauth=1 -{% elif auth_mode == 'local' %} -username=ifname -password=csid -{% endif %} -proxy-arp=1 - -{% for interface in interfaces %} -{% if (interface.shared == '0') and (interface.vlan_mon) %} -vlan-mon={{ interface.name }},{{ interface.vlan_mon | join(',') }} -{% endif %} -{% endfor %} - -{% if dnsv4 %} -[dns] -{% for dns in dnsv4 %} -dns{{ loop.index }}={{ dns }} -{% endfor %} -{% endif %} - -{% if dnsv6 %} -[ipv6-dns] -{% for dns in dnsv6 %} -{{ dns }} -{% endfor %} -{% endif %} - -[ipv6-nd] -verbose=1 - -[ipv6-dhcp] -verbose=1 - -{% if client_ipv6_pool %} -[ipv6-pool] -{% for p in client_ipv6_pool %} -{{ p.prefix }},{{ p.mask }} -{% endfor %} -{% for p in client_ipv6_delegate_prefix %} -delegate={{ p.prefix }},{{ p.mask }} -{% endfor %} -{% endif %} - -{% if auth_mode == 'local' %} -[chap-secrets] -chap-secrets={{ chap_secrets_file }} -{% elif auth_mode == 'radius' %} -[radius] -verbose=1 -{% for r in radius_server %} -server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }} -{% endfor %} - -{% if radius_acct_inter_jitter %} -acct-interim-jitter={{ radius_acct_inter_jitter }} -{% endif %} - -acct-timeout={{ radius_acct_tmo }} -timeout={{ radius_timeout }} -max-try={{ radius_max_try }} -{% if radius_nas_id %} -nas-identifier={{ radius_nas_id }} -{% endif %} -{% if radius_nas_ip %} -nas-ip-address={{ radius_nas_ip }} -{% endif %} -{% if radius_source_address %} -bind={{ radius_source_address }} -{% endif %} - -{% if radius_dynamic_author %} -dae-server={{ radius_dynamic_author.server }}:{{ radius_dynamic_author.port }},{{ radius_dynamic_author.key }} -{% endif %} - -{% if radius_shaper_attr %} -[shaper] -verbose=1 -attr={{ radius_shaper_attr }} -{% if radius_shaper_vendor %} -vendor={{ radius_shaper_vendor }} -{% endif %} -{% endif %} -{% endif %} - -[cli] -tcp=127.0.0.1:2002 diff --git a/data/templates/accel-ppp/l2tp.config.tmpl b/data/templates/accel-ppp/l2tp.config.j2 index 9fcda76d4..9eeaf7622 100644 --- a/data/templates/accel-ppp/l2tp.config.tmpl +++ b/data/templates/accel-ppp/l2tp.config.j2 @@ -3,9 +3,9 @@ log_syslog l2tp chap-secrets -{% for proto in auth_proto: %} -{{proto}} -{% endfor%} +{% for proto in auth_proto %} +{{ proto }} +{% endfor %} {% if auth_mode == 'radius' %} radius @@ -18,7 +18,7 @@ ipv6_nd ipv6_dhcp [core] -thread-count={{thread_cnt}} +thread-count={{ thread_cnt }} [log] syslog=accel-l2tp,daemon @@ -27,23 +27,23 @@ level=5 {% if dnsv4 %} [dns] -{% for dns in dnsv4 %} +{% for dns in dnsv4 %} dns{{ loop.index }}={{ dns }} -{% endfor %} +{% endfor %} {% endif %} {% if dnsv6 %} [ipv6-dns] -{% for dns in dnsv6 %} +{% for dns in dnsv6 %} {{ dns }} -{% endfor %} +{% endfor %} {% endif %} {% if wins %} [wins] -{% for server in wins %} +{% for server in wins %} wins{{ loop.index }}={{ server }} -{% endfor %} +{% endfor %} {% endif %} [l2tp] @@ -66,14 +66,14 @@ host-name={{ lns_host_name }} {% if client_ip_pool or client_ip_subnets %} [ip-pool] -{% if client_ip_pool %} +{% if client_ip_pool %} {{ client_ip_pool }} -{% endif %} -{% if client_ip_subnets %} -{% for sn in client_ip_subnets %} -{{sn}} -{% endfor %} -{% endif %} +{% endif %} +{% if client_ip_subnets %} +{% for sn in client_ip_subnets %} +{{ sn }} +{% endfor %} +{% endif %} {% endif %} {% if gateway_address %} gw-ip-address={{ gateway_address }} @@ -85,27 +85,24 @@ chap-secrets={{ chap_secrets_file }} {% elif auth_mode == 'radius' %} [radius] verbose=1 -{% for r in radius_server %} +{% for r in radius_server %} server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }} -{% endfor %} - -{% if radius_acct_inter_jitter %} +{% endfor %} +{% if radius_acct_inter_jitter %} acct-interim-jitter={{ radius_acct_inter_jitter }} -{% endif %} - +{% endif %} acct-timeout={{ radius_acct_tmo }} timeout={{ radius_timeout }} max-try={{ radius_max_try }} - -{% if radius_nas_id %} +{% if radius_nas_id %} nas-identifier={{ radius_nas_id }} -{% endif %} -{% if radius_nas_ip %} +{% endif %} +{% if radius_nas_ip %} nas-ip-address={{ radius_nas_ip }} -{% endif %} -{% if radius_source_address %} +{% endif %} +{% if radius_source_address %} bind={{ radius_source_address }} -{% endif %} +{% endif %} {% endif %} {% if gateway_address %} gw-ip-address={{ gateway_address }} @@ -128,12 +125,12 @@ ipv6=allow {% if client_ipv6_pool %} [ipv6-pool] -{% for p in client_ipv6_pool %} +{% for p in client_ipv6_pool %} {{ p.prefix }},{{ p.mask }} -{% endfor %} -{% for p in client_ipv6_delegate_prefix %} +{% endfor %} +{% for p in client_ipv6_delegate_prefix %} delegate={{ p.prefix }},{{ p.mask }} -{% endfor %} +{% endfor %} {% endif %} {% if client_ipv6_delegate_prefix %} @@ -145,9 +142,9 @@ verbose=1 [shaper] verbose=1 attr={{ radius_shaper_attr }} -{% if radius_shaper_vendor %} +{% if radius_shaper_vendor %} vendor={{ radius_shaper_vendor }} -{% endif %} +{% endif %} {% endif %} [cli] diff --git a/data/templates/accel-ppp/pppoe.config.j2 b/data/templates/accel-ppp/pppoe.config.j2 new file mode 100644 index 000000000..0a92e2d54 --- /dev/null +++ b/data/templates/accel-ppp/pppoe.config.j2 @@ -0,0 +1,172 @@ +### generated by accel_pppoe.py ### +[modules] +log_syslog +pppoe +shaper +{# Common authentication backend definitions #} +{% include 'accel-ppp/config_modules_auth_mode.j2' %} +ippool +{# Common IPv6 definitions #} +{% include 'accel-ppp/config_modules_ipv6.j2' %} +{# Common authentication protocols (pap, chap ...) #} +{% include 'accel-ppp/config_modules_auth_protocols.j2' %} + +{% if snmp is vyos_defined %} +net-snmp +{% endif %} +{% if limits is vyos_defined %} +connlimit +{% endif %} +{% if extended_scripts is vyos_defined %} +sigchld +pppd_compat +{% endif %} + +[core] +thread-count={{ thread_count }} + +[log] +syslog=accel-pppoe,daemon +copy=1 +level=5 + +{% if snmp.master_agent is vyos_defined %} +[snmp] +master=1 +{% endif %} + +[client-ip-range] +disable + +{# Common IP pool definitions #} +{% include 'accel-ppp/config_ip_pool.j2' %} + +{# Common IPv6 pool definitions #} +{% include 'accel-ppp/config_ipv6_pool.j2' %} + +{# Common DNS name-server definition #} +{% include 'accel-ppp/config_name_server.j2' %} + +{% if wins_server is vyos_defined %} +[wins] +{% for server in wins_server %} +wins{{ loop.index }}={{ server }} +{% endfor %} +{% endif %} + +{# Common chap-secrets and RADIUS server/option definitions #} +{% include 'accel-ppp/config_chap_secrets_radius.j2' %} + +{% if session_control is vyos_defined and session_control is not vyos_defined('disable') %} +[common] +single-session={{ session_control }} +{% endif %} + +[ppp] +verbose=1 +check-ip=1 +ccp={{ "1" if ppp_options.ccp is vyos_defined else "0" }} +unit-preallocate={{ "1" if authentication.radius.preallocate_vif is vyos_defined else "0" }} +{% if ppp_options.min_mtu is vyos_defined %} +min-mtu={{ ppp_options.min_mtu }} +{% else %} +min-mtu={{ mtu }} +{% endif %} +{% if ppp_options.mru is vyos_defined %} +mru={{ ppp_options.mru }} +{% endif %} +mppe={{ ppp_options.mppe }} +lcp-echo-interval={{ ppp_options.lcp_echo_interval }} +lcp-echo-timeout={{ ppp_options.lcp_echo_timeout }} +lcp-echo-failure={{ ppp_options.lcp_echo_failure }} +{% if ppp_options.ipv4 is vyos_defined %} +ipv4={{ ppp_options.ipv4 }} +{% endif %} +{# IPv6 #} +{% if ppp_options.ipv6 is vyos_defined %} +ipv6={{ ppp_options.ipv6 }} +{% if ppp_options.ipv6_intf_id is vyos_defined %} +ipv6-intf-id={{ ppp_options.ipv6_intf_id }} +{% endif %} +{% if ppp_options.ipv6_peer_intf_id is vyos_defined %} +ipv6-peer-intf-id={{ ppp_options.ipv6_peer_intf_id }} +{% endif %} +ipv6-accept-peer-intf-id={{ "1" if ppp_options.ipv6_accept_peer_intf_id is vyos_defined else "0" }} +{% endif %} +{# MTU #} +mtu={{ mtu }} +{% if ppp_options.interface_cache is vyos_defined %} +unit-cache={{ ppp_options.interface_cache }} +{% endif %} + +[pppoe] +verbose=1 +ac-name={{ access_concentrator }} + +{% if interface is vyos_defined %} +{% for iface, iface_config in interface.items() %} +{% if iface_config.vlan_id is not vyos_defined and iface_config.vlan_range is not vyos_defined %} +interface={{ iface }} +{% endif %} +{% if iface_config.vlan_range is vyos_defined %} +{% for regex in iface_config.regex %} +interface=re:^{{ iface | replace('.', '\\.') }}\.({{ regex }})$ +{% endfor %} +vlan-mon={{ iface }},{{ iface_config.vlan_range | join(',') }} +{% endif %} +{% if iface_config.vlan_id is vyos_defined %} +{% for vlan in iface_config.vlan_id %} +vlan-mon={{ iface }},{{ vlan }} +interface=re:^{{ iface | replace('.', '\\.') }}\.{{ vlan }}$ +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} + +{% if service_name %} +service-name={{ service_name | join(',') }} +{% endif %} + +{% if pado_delay %} +{% set pado_delay_param = namespace(value='0') %} +{% for delay in pado_delay | sort(attribute='0') %} +{% if not loop.last %} +{% set pado_delay_param.value = pado_delay_param.value + ',' + delay + ':' + pado_delay[delay].sessions %} +{% else %} +{% set pado_delay_param.value = pado_delay_param.value + ',-1:' + pado_delay[delay].sessions %} +{% endif %} +{% endfor %} +pado-delay={{ pado_delay_param.value }} +{% endif %} +{% if authentication.radius.called_sid_format is vyos_defined %} +called-sid={{ authentication.radius.called_sid_format }} +{% endif %} + +{% if limits is vyos_defined %} +[connlimit] +{% if limits.connection_limit is vyos_defined %} +limit={{ limits.connection_limit }} +{% endif %} +{% if limits.burst is vyos_defined %} +burst={{ limits.burst }} +{% endif %} +{% if limits.timeout is vyos_defined %} +timeout={{ limits.timeout }} +{% endif %} +{% endif %} + +{# Common RADIUS shaper configuration #} +{% include 'accel-ppp/config_shaper_radius.j2' %} + +{% if extended_scripts is vyos_defined %} +[pppd-compat] +verbose=1 +radattr-prefix=/run/accel-pppd/radattr +{% set script_name = {'on_up': 'ip-up', 'on_down': 'ip-down', 'on_change':'ip-change', 'on_pre_up':'ip-pre-up'} %} +{% for script in extended_scripts %} +{{ script_name[script] }}={{ extended_scripts[script] }} +{% endfor %} +{% endif %} + +[cli] +tcp=127.0.0.1:2001 diff --git a/data/templates/accel-ppp/pppoe.config.tmpl b/data/templates/accel-ppp/pppoe.config.tmpl deleted file mode 100644 index 238e7ee15..000000000 --- a/data/templates/accel-ppp/pppoe.config.tmpl +++ /dev/null @@ -1,174 +0,0 @@ -### generated by accel_pppoe.py ### -[modules] -log_syslog -pppoe -shaper -{# Common authentication backend definitions #} -{% include 'accel-ppp/config_modules_auth_mode.j2' %} -ippool -{# Common IPv6 definitions #} -{% include 'accel-ppp/config_modules_ipv6.j2' %} -{# Common authentication protocols (pap, chap ...) #} -{% include 'accel-ppp/config_modules_auth_protocols.j2' %} - -{% if snmp is defined %} -net-snmp -{% endif %} -{% if limits is defined %} -connlimit -{% endif %} -{% if extended_scripts is defined %} -sigchld -pppd_compat -{% endif %} - -[core] -thread-count={{ thread_count }} - -[log] -syslog=accel-pppoe,daemon -copy=1 -level=5 - -{% if snmp is defined and snmp.master_agent is defined %} -[snmp] -master=1 -{% endif %} - -[client-ip-range] -disable - -{# Common IP pool definitions #} -{% include 'accel-ppp/config_ip_pool.j2' %} - -{# Common IPv6 pool definitions #} -{% include 'accel-ppp/config_ipv6_pool.j2' %} - -{# Common DNS name-server definition #} -{% include 'accel-ppp/config_name_server.j2' %} - -{% if wins_server is defined and wins_server is not none %} -[wins] -{% for server in wins_server %} -wins{{ loop.index }}={{ server }} -{% endfor %} -{% endif %} - -{# Common chap-secrets and RADIUS server/option definitions #} -{% include 'accel-ppp/config_chap_secrets_radius.j2' %} - -{% if session_control is defined and session_control != 'disable' %} -[common] -single-session={{ session_control }} -{% endif %} - -[ppp] -verbose=1 -check-ip=1 -ccp={{ "1" if ppp_options.ccp is defined else "0" }} -unit-preallocate={{ "1" if authentication.radius.preallocate_vif is defined else "0" }} -{% if ppp_options.min_mtu is defined and ppp_options.min_mtu is not none %} -min-mtu={{ ppp_options.min_mtu }} -{% else %} -min-mtu={{ mtu }} -{% endif %} -{% if ppp_options.mru is defined and ppp_options.mru is not none %} -mru={{ ppp_options.mru }} -{% endif %} -mppe={{ ppp_options.mppe }} -lcp-echo-interval={{ ppp_options.lcp_echo_interval }} -lcp-echo-timeout={{ ppp_options.lcp_echo_timeout }} -lcp-echo-failure={{ ppp_options.lcp_echo_failure }} -{% if ppp_options.ipv4 is defined and ppp_options.ipv4 is not none %} -ipv4={{ ppp_options.ipv4 }} -{% endif %} -{# IPv6 #} -{% if ppp_options.ipv6 is defined and ppp_options.ipv6 is not none %} -ipv6={{ ppp_options.ipv6 }} -{% if ppp_options.ipv6_intf_id is defined and ppp_options.ipv6_intf_id is not none %} -ipv6-intf-id={{ ppp_options.ipv6_intf_id }} -{% endif %} -{% if ppp_options.ipv6_peer_intf_id is defined and ppp_options.ipv6_peer_intf_id is not none %} -ipv6-peer-intf-id={{ ppp_options.ipv6_peer_intf_id }} -{% endif %} -ipv6-accept-peer-intf-id={{ "1" if ppp_options.ipv6_accept_peer_intf_id is defined else "0" }} -{% endif %} -{# MTU #} -mtu={{ mtu }} -{% if ppp_options.interface_cache is defined and ppp_options.interface_cache is not none %} -unit-cache={{ ppp_options.interface_cache }} -{% endif %} - -[pppoe] -verbose=1 -ac-name={{ access_concentrator }} - -{% if interface is defined and interface is not none %} -{% for iface, iface_config in interface.items() %} -{% if iface_config.vlan_id is not defined and iface_config.vlan_range is not defined %} -interface={{ iface }} -{% endif %} -{% if iface_config.vlan_id is defined and iface_config.vlan_range is not defined %} -{% for vlan in iface_config.vlan_id %} -interface={{ iface }}.{{ vlan }} -vlan-mon={{ iface }},{{ vlan }} -{% endfor %} -{% endif %} -{% if iface_config.vlan_range is defined and iface_config.vlan_id is not defined %} -vlan-mon={{ iface }},{{ iface_config.vlan_range | join(',') }} -interface=re:{{ iface | replace('.', '\\.') }}\.\d+ -{% endif %} -{% if iface_config.vlan_id is defined and iface_config.vlan_range is defined %} -vlan-mon={{ iface }},{{ iface_config.vlan_id | join(',') }},{{ iface_config.vlan_range | join(',') }} -interface=re:{{ iface | replace('.', '\\.') }}\.\d+ -{% endif %} -{% endfor %} -{% endif %} - -{% if service_name %} -service-name={{ service_name | join(',') }} -{% endif %} - -{% if pado_delay %} -{% set pado_delay_param = namespace(value='0') %} -{% for delay in pado_delay|sort(attribute='0') %} -{% if not loop.last %} -{% set pado_delay_param.value = pado_delay_param.value + ',' + delay + ':' + pado_delay[delay].sessions %} -{% else %} -{% set pado_delay_param.value = pado_delay_param.value + ',-1:' + pado_delay[delay].sessions %} -{% endif %} -{% endfor %} -pado-delay={{ pado_delay_param.value }} -{% endif %} -{% if authentication.radius.called_sid_format is defined and authentication.radius.called_sid_format is not none %} -called-sid={{ authentication.radius.called_sid_format }} -{% endif %} - -{% if limits is defined %} -[connlimit] -{% if limits.connection_limit is defined and limits.connection_limit is not none %} -limit={{ limits.connection_limit }} -{% endif %} -{% if limits.burst is defined and limits.burst %} -burst={{ limits.burst }} -{% endif %} -{% if limits.timeout is defined and limits.timeout is not none %} -timeout={{ limits.timeout }} -{% endif %} -{% endif %} - -{# Common RADIUS shaper configuration #} -{% include 'accel-ppp/config_shaper_radius.j2' %} - -{% if extended_scripts is defined %} -[pppd-compat] -verbose=1 -radattr-prefix=/run/accel-pppd/radattr -{% set script_name = {'on_up': 'ip-up', 'on_down': 'ip-down', 'on_change':'ip-change', 'on_pre_up':'ip-pre-up'} %} -{% for script in extended_scripts %} -{{ script_name[script] }}={{ extended_scripts[script] }} -{% endfor %} -{% endif %} - -[cli] -tcp=127.0.0.1:2001 diff --git a/data/templates/accel-ppp/pptp.config.tmpl b/data/templates/accel-ppp/pptp.config.j2 index 3cfc4a906..cc1a45d6b 100644 --- a/data/templates/accel-ppp/pptp.config.tmpl +++ b/data/templates/accel-ppp/pptp.config.j2 @@ -10,7 +10,7 @@ radius {% endif %} ippool {% for proto in auth_proto %} -{{proto}} +{{ proto }} {% endfor %} [core] @@ -23,16 +23,16 @@ level=5 {% if dnsv4 %} [dns] -{% for dns in dnsv4 %} +{% for dns in dnsv4 %} dns{{ loop.index }}={{ dns }} -{% endfor %} +{% endfor %} {% endif %} {% if wins %} [wins] -{% for server in wins %} +{% for server in wins %} wins{{ loop.index }}={{ server }} -{% endfor %} +{% endfor %} {% endif %} @@ -42,7 +42,7 @@ ifname=pptp%d bind={{ outside_addr }} {% endif %} verbose=1 -ppp-max-mtu={{mtu}} +ppp-max-mtu={{ mtu }} mppe={{ ppp_mppe }} echo-interval=10 echo-failure=3 @@ -66,27 +66,27 @@ chap-secrets={{ chap_secrets_file }} {% elif auth_mode == 'radius' %} [radius] verbose=1 -{% for r in radius_server %} +{% for r in radius_server %} server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }} -{% endfor %} +{% endfor %} -{% if radius_acct_inter_jitter %} +{% if radius_acct_inter_jitter %} acct-interim-jitter={{ radius_acct_inter_jitter }} -{% endif %} +{% endif %} acct-timeout={{ radius_acct_tmo }} timeout={{ radius_timeout }} max-try={{ radius_max_try }} -{% if radius_nas_id %} +{% if radius_nas_id %} nas-identifier={{ radius_nas_id }} -{% endif %} -{% if radius_nas_ip %} +{% endif %} +{% if radius_nas_ip %} nas-ip-address={{ radius_nas_ip }} -{% endif %} -{% if radius_source_address %} +{% endif %} +{% if radius_source_address %} bind={{ radius_source_address }} -{% endif %} +{% endif %} {% endif %} {# Both chap-secrets and radius block required the gw-ip-address #} {% if gw_ip is defined and gw_ip is not none %} diff --git a/data/templates/accel-ppp/sstp.config.tmpl b/data/templates/accel-ppp/sstp.config.j2 index 8fd7d230d..5c6f19306 100644 --- a/data/templates/accel-ppp/sstp.config.tmpl +++ b/data/templates/accel-ppp/sstp.config.j2 @@ -50,7 +50,7 @@ verbose=1 check-ip=1 {# MTU #} mtu={{ mtu }} -ipv6={{ 'allow' if ppp_options.ipv6 == "deny" and client_ipv6_pool is defined else ppp_options.ipv6 }} +ipv6={{ 'allow' if ppp_options.ipv6 is vyos_defined("deny") and client_ipv6_pool is vyos_defined else ppp_options.ipv6 }} ipv4={{ ppp_options.ipv4 }} mppe={{ ppp_options.mppe }} diff --git a/data/templates/bcast-relay/udp-broadcast-relay.j2 b/data/templates/bcast-relay/udp-broadcast-relay.j2 new file mode 100644 index 000000000..75740e04c --- /dev/null +++ b/data/templates/bcast-relay/udp-broadcast-relay.j2 @@ -0,0 +1,5 @@ +### Autogenerated by bcast_relay.py ### + +# UDP broadcast relay configuration for instance {{ id }} +{{ '# ' ~ description if description is vyos_defined }} +DAEMON_ARGS="{{ '-s ' ~ address if address is vyos_defined }} {{ instance }} {{ port }} {{ interface | join(' ') }}" diff --git a/data/templates/bcast-relay/udp-broadcast-relay.tmpl b/data/templates/bcast-relay/udp-broadcast-relay.tmpl deleted file mode 100644 index 73e9acad4..000000000 --- a/data/templates/bcast-relay/udp-broadcast-relay.tmpl +++ /dev/null @@ -1,7 +0,0 @@ -### Autogenerated by bcast_relay.py ### - -# UDP broadcast relay configuration for instance {{ id }} -{% if description %} -# Comment: {{ description }} -{% endif %} -DAEMON_ARGS="{{ '-s ' + address if address is defined }} {{ instance }} {{ port }} {{ interface | join(' ') }}" diff --git a/data/templates/conntrack/nftables-ct.j2 b/data/templates/conntrack/nftables-ct.j2 new file mode 100644 index 000000000..16a03fc6e --- /dev/null +++ b/data/templates/conntrack/nftables-ct.j2 @@ -0,0 +1,48 @@ +#!/usr/sbin/nft -f + +{% set nft_ct_ignore_name = 'VYOS_CT_IGNORE' %} +{% set nft_ct_timeout_name = 'VYOS_CT_TIMEOUT' %} + +# we first flush all chains and render the content from scratch - this makes +# any delta check obsolete +flush chain raw {{ nft_ct_ignore_name }} +flush chain raw {{ nft_ct_timeout_name }} + +table raw { + chain {{ nft_ct_ignore_name }} { +{% if ignore.rule is vyos_defined %} +{% for rule, rule_config in ignore.rule.items() %} + # rule-{{ rule }} {{ '- ' ~ rule_config.description if rule_config.description is vyos_defined }} +{% set nft_command = '' %} +{% if rule_config.inbound_interface is vyos_defined %} +{% set nft_command = nft_command ~ ' iifname ' ~ rule_config.inbound_interface %} +{% endif %} +{% if rule_config.protocol is vyos_defined %} +{% set nft_command = nft_command ~ ' ip protocol ' ~ rule_config.protocol %} +{% endif %} +{% if rule_config.destination.address is vyos_defined %} +{% set nft_command = nft_command ~ ' ip daddr ' ~ rule_config.destination.address %} +{% endif %} +{% if rule_config.destination.port is vyos_defined %} +{% set nft_command = nft_command ~ ' ' ~ rule_config.protocol ~ ' dport { ' ~ rule_config.destination.port ~ ' }' %} +{% endif %} +{% if rule_config.source.address is vyos_defined %} +{% set nft_command = nft_command ~ ' ip saddr ' ~ rule_config.source.address %} +{% endif %} +{% if rule_config.source.port is vyos_defined %} +{% set nft_command = nft_command ~ ' ' ~ rule_config.protocol ~ ' sport { ' ~ rule_config.source.port ~ ' }' %} +{% endif %} + {{ nft_command }} counter notrack comment ignore-{{ rule }} +{% endfor %} +{% endif %} + return + } + chain {{ nft_ct_timeout_name }} { +{% if timeout.custom.rule is vyos_defined %} +{% for rule, rule_config in timeout.custom.rule.items() %} + # rule-{{ rule }} {{ '- ' ~ rule_config.description if rule_config.description is vyos_defined }} +{% endfor %} +{% endif %} + return + } +} diff --git a/data/templates/conntrack/sysctl.conf.tmpl b/data/templates/conntrack/sysctl.conf.j2 index 9e97c3286..075402c04 100644 --- a/data/templates/conntrack/sysctl.conf.tmpl +++ b/data/templates/conntrack/sysctl.conf.j2 @@ -6,7 +6,7 @@ net.netfilter.nf_conntrack_max = {{ table_size }} net.ipv4.tcp_max_syn_backlog = {{ tcp.half_open_connections }} -net.netfilter.nf_conntrack_tcp_loose = {{ '1' if tcp.loose == 'enable' else '0' }} +net.netfilter.nf_conntrack_tcp_loose = {{ '1' if tcp.loose is vyos_defined('enable') else '0' }} net.netfilter.nf_conntrack_tcp_max_retrans = {{ tcp.max_retrans }} net.netfilter.nf_conntrack_icmp_timeout = {{ timeout.icmp }} diff --git a/data/templates/conntrack/vyos_nf_conntrack.conf.tmpl b/data/templates/conntrack/vyos_nf_conntrack.conf.j2 index 111459485..111459485 100644 --- a/data/templates/conntrack/vyos_nf_conntrack.conf.tmpl +++ b/data/templates/conntrack/vyos_nf_conntrack.conf.j2 diff --git a/data/templates/conntrackd/conntrackd.conf.tmpl b/data/templates/conntrackd/conntrackd.conf.j2 index 45b7bff09..66024869d 100644 --- a/data/templates/conntrackd/conntrackd.conf.tmpl +++ b/data/templates/conntrackd/conntrackd.conf.j2 @@ -3,45 +3,45 @@ # Synchronizer settings Sync { Mode FTFW { - DisableExternalCache {{ 'on' if disable_external_cache is defined else 'off' }} + DisableExternalCache {{ 'on' if disable_external_cache is vyos_defined else 'off' }} } {% for iface, iface_config in interface.items() %} -{% if iface_config.peer is defined and iface_config.peer is not none %} +{% if iface_config.peer is vyos_defined %} UDP { -{% if listen_address is defined and listen_address is not none %} +{% if listen_address is vyos_defined %} IPv4_address {{ listen_address }} -{% endif %} +{% endif %} IPv4_Destination_Address {{ iface_config.peer }} - Port {{ iface_config.port if iface_config.port is defined else '3780' }} + Port {{ iface_config.port if iface_config.port is vyos_defined else '3780' }} Interface {{ iface }} SndSocketBuffer {{ sync_queue_size | int *1024 *1024 }} RcvSocketBuffer {{ sync_queue_size | int *1024 *1024 }} Checksum on } -{% else %} +{% else %} Multicast { -{% set ip_address = iface | get_ipv4 %} +{% set ip_address = iface | get_ipv4 %} IPv4_address {{ mcast_group }} - Group {{ iface_config.port if iface_config.port is defined else '3780' }} + Group {{ iface_config.port if iface_config.port is vyos_defined else '3780' }} IPv4_interface {{ ip_address[0] | ip_from_cidr }} Interface {{ iface }} SndSocketBuffer {{ sync_queue_size | int *1024 *1024 }} RcvSocketBuffer {{ sync_queue_size | int *1024 *1024 }} Checksum on } -{% endif %} +{% endif %} {% endfor %} -{% if expect_sync is defined and expect_sync is not none %} +{% if expect_sync is vyos_defined %} Options { -{% if 'all' in expect_sync %} +{% if 'all' in expect_sync %} ExpectationSync on -{% else %} +{% else %} ExpectationSync { -{% for protocol in expect_sync %} +{% for protocol in expect_sync %} {{ protocol }} -{% endfor %} +{% endfor %} } -{% endif %} +{% endif %} } {% endif %} } @@ -83,29 +83,29 @@ General { NetlinkBufferSizeMaxGrowth {{ event_listen_queue_size | int *1024 *1024 }} NetlinkOverrunResync off NetlinkEventsReliable on -{% if ignore_address is defined or accept_protocol is defined %} +{% if ignore_address is vyos_defined or accept_protocol is vyos_defined %} Filter From Userspace { -{% if ignore_address is defined and ignore_address is not none %} +{% if ignore_address is vyos_defined %} Address Ignore { -{% for address in ignore_address if address | is_ipv4 %} +{% for address in ignore_address if address | is_ipv4 %} IPv4_address {{ address }} -{% endfor %} -{% for address in ignore_address if address | is_ipv6 %} +{% endfor %} +{% for address in ignore_address if address | is_ipv6 %} IPv6_address {{ address }} -{% endfor %} +{% endfor %} } -{% endif %} -{% if accept_protocol is defined and accept_protocol is not none %} +{% endif %} +{% if accept_protocol is vyos_defined %} Protocol Accept { -{% for protocol in accept_protocol %} -{% if protocol == 'icmp6' %} +{% for protocol in accept_protocol %} +{% if protocol == 'icmp6' %} IPv6-ICMP -{% else %} +{% else %} {{ protocol | upper }} -{% endif %} -{% endfor %} +{% endif %} +{% endfor %} } -{% endif %} +{% endif %} } {% endif %} } diff --git a/data/templates/conntrackd/conntrackd.op-mode.j2 b/data/templates/conntrackd/conntrackd.op-mode.j2 new file mode 100644 index 000000000..82f7e2859 --- /dev/null +++ b/data/templates/conntrackd/conntrackd.op-mode.j2 @@ -0,0 +1,13 @@ +Source Destination Protocol +{% for parsed in data if parsed.flow.meta is vyos_defined %} +{% for key in parsed.flow.meta %} +{% if key['@direction'] == 'original' %} +{% set saddr = key.layer3.src | bracketize_ipv6 %} +{% set sport = key.layer4.sport %} +{% set daddr = key.layer3.dst | bracketize_ipv6 %} +{% set dport = key.layer4.dport %} +{% set protocol = key.layer4['@protoname'] %} +{{ "%-48s" | format(saddr ~ ':' ~ sport) }} {{ "%-48s" | format(daddr ~ ':' ~ dport) }} {{ protocol }} +{% endif %} +{% endfor %} +{% endfor %} diff --git a/data/templates/conntrackd/conntrackd.op-mode.tmpl b/data/templates/conntrackd/conntrackd.op-mode.tmpl deleted file mode 100644 index 82a4b09ad..000000000 --- a/data/templates/conntrackd/conntrackd.op-mode.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -Source Destination Protocol -{% for parsed in data if parsed.flow is defined and parsed.flow.meta is defined %} -{% for key in parsed.flow.meta %} -{% if key['@direction'] == 'original' %} -{% set saddr = key.layer3.src | bracketize_ipv6 %} -{% set sport = key.layer4.sport %} -{% set daddr = key.layer3.dst | bracketize_ipv6 %} -{% set dport = key.layer4.dport %} -{% set protocol = key.layer4['@protoname'] %} -{{ "%-48s" | format(saddr ~ ':' ~ sport) }} {{ "%-48s" | format(daddr ~ ':' ~ dport) }} {{ protocol }} -{% endif %} -{% endfor %} -{% endfor %} diff --git a/data/templates/conserver/conserver.conf.tmpl b/data/templates/conserver/conserver.conf.j2 index 4e7b5d8d7..1823657d7 100644 --- a/data/templates/conserver/conserver.conf.tmpl +++ b/data/templates/conserver/conserver.conf.j2 @@ -17,7 +17,7 @@ default * { ## {% for key, value in device.items() %} {# Depending on our USB serial console we could require a path adjustment #} -{% set path = '/dev' if key.startswith('ttyS') else '/dev/serial/by-bus' %} +{% set path = '/dev' if key.startswith('ttyS') else '/dev/serial/by-bus' %} console {{ key }} { master localhost; type device; diff --git a/data/templates/conserver/dropbear@.service.tmpl b/data/templates/conserver/dropbear@.service.j2 index e355dab43..e355dab43 100644 --- a/data/templates/conserver/dropbear@.service.tmpl +++ b/data/templates/conserver/dropbear@.service.j2 diff --git a/data/templates/container/registries.conf.j2 b/data/templates/container/registries.conf.j2 new file mode 100644 index 000000000..2e86466a1 --- /dev/null +++ b/data/templates/container/registries.conf.j2 @@ -0,0 +1,27 @@ +### Autogenerated by container.py ### + +# For more information on this configuration file, see containers-registries.conf(5). +# +# NOTE: RISK OF USING UNQUALIFIED IMAGE NAMES +# We recommend always using fully qualified image names including the registry +# server (full dns name), namespace, image name, and tag +# (e.g., registry.redhat.io/ubi8/ubi:latest). Pulling by digest (i.e., +# quay.io/repository/name@digest) further eliminates the ambiguity of tags. +# When using short names, there is always an inherent risk that the image being +# pulled could be spoofed. For example, a user wants to pull an image named +# `foobar` from a registry and expects it to come from myregistry.com. If +# myregistry.com is not first in the search list, an attacker could place a +# different `foobar` image at a registry earlier in the search list. The user +# would accidentally pull and run the attacker's image and code rather than the +# intended content. We recommend only adding registries which are completely +# trusted (i.e., registries which don't allow unknown or anonymous users to +# create accounts with arbitrary names). This will prevent an image from being +# spoofed, squatted or otherwise made insecure. If it is necessary to use one +# of these registries, it should be added at the end of the list. +# +# An array of host[:port] registries to try when pulling an unqualified image, in order. +# unqualified-search-registries = ["example.com"] + +{% if registry is vyos_defined %} +unqualified-search-registries = {{ registry }} +{% endif %} diff --git a/data/templates/container/storage.conf.j2 b/data/templates/container/storage.conf.j2 new file mode 100644 index 000000000..665f9bf95 --- /dev/null +++ b/data/templates/container/storage.conf.j2 @@ -0,0 +1,4 @@ +### Autogenerated by container.py ### +[storage] + driver = "vfs" + graphroot = "/usr/lib/live/mount/persistence/container/storage" diff --git a/data/templates/containers/registry.tmpl b/data/templates/containers/registry.tmpl deleted file mode 100644 index 0347de673..000000000 --- a/data/templates/containers/registry.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -### Autogenerated by /usr/libexec/vyos/conf_mode/containers.py ### - -{% if registry is defined and registry is not none %} -unqualified-search-registries = {{ registry }} -{% endif %} diff --git a/data/templates/containers/storage.tmpl b/data/templates/containers/storage.tmpl deleted file mode 100644 index 3a69b7252..000000000 --- a/data/templates/containers/storage.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -### Autogenerated by /usr/libexec/vyos/conf_mode/containers.py ### - -[storage] - driver = "vfs" - graphroot = "/config/containers/storage" diff --git a/data/templates/dhcp-client/daemon-options.j2 b/data/templates/dhcp-client/daemon-options.j2 new file mode 100644 index 000000000..b21ad08ab --- /dev/null +++ b/data/templates/dhcp-client/daemon-options.j2 @@ -0,0 +1,4 @@ +### Autogenerated by interface.py ### +{% set if_metric = '-e IF_METRIC=' ~ dhcp_options.default_route_distance if dhcp_options.default_route_distance is vyos_defined else '' %} +DHCLIENT_OPTS="-nw -cf /var/lib/dhcp/dhclient_{{ ifname }}.conf -pf /var/lib/dhcp/dhclient_{{ ifname }}.pid -lf /var/lib/dhcp/dhclient_{{ ifname }}.leases {{ if_metric }} {{ ifname }}" + diff --git a/data/templates/dhcp-client/daemon-options.tmpl b/data/templates/dhcp-client/daemon-options.tmpl deleted file mode 100644 index 40629dca1..000000000 --- a/data/templates/dhcp-client/daemon-options.tmpl +++ /dev/null @@ -1,4 +0,0 @@ -### Autogenerated by interface.py ### - -DHCLIENT_OPTS="-nw -cf /var/lib/dhcp/dhclient_{{ifname}}.conf -pf /var/lib/dhcp/dhclient_{{ifname}}.pid -lf /var/lib/dhcp/dhclient_{{ifname}}.leases{{" -e IF_METRIC=" ~ dhcp_options.default_route_distance if dhcp_options.default_route_distance is defined and dhcp_options.default_route_distance is not none}} {{ifname}}" - diff --git a/data/templates/dhcp-client/ipv4.tmpl b/data/templates/dhcp-client/ipv4.j2 index b3e74c22b..cc5ddf09c 100644 --- a/data/templates/dhcp-client/ipv4.tmpl +++ b/data/templates/dhcp-client/ipv4.j2 @@ -7,26 +7,26 @@ initial-interval 2; interface "{{ ifname }}" { send host-name "{{ dhcp_options.host_name }}"; -{% if dhcp_options.client_id is defined and dhcp_options.client_id is not none %} -{% set client_id = dhcp_options.client_id %} +{% if dhcp_options.client_id is vyos_defined %} +{% set client_id = dhcp_options.client_id %} {# Use HEX representation of client-id as it is send in MAC-address style using hex characters. If not HEX, use double quotes ASCII format #} -{% if not dhcp_options.client_id.split(':') | length >= 5 %} -{% set client_id = '"' + dhcp_options.client_id + '"' %} -{% endif %} - send dhcp-client-identifier {{ client_id }}; +{% if not dhcp_options.client_id.split(':') | length >= 5 %} +{% set client_id = '"' + dhcp_options.client_id + '"' %} +{% endif %} + send dhcp-client-identifier {{ client_id }}; {% endif %} -{% if dhcp_options.vendor_class_id is defined and dhcp_options.vendor_class_id is not none %} +{% if dhcp_options.vendor_class_id is vyos_defined %} send vendor-class-identifier "{{ dhcp_options.vendor_class_id }}"; {% endif %} # The request statement causes the client to request that any server responding to the # client send the client its values for the specified options. - request subnet-mask, broadcast-address,{{ " routers," if dhcp_options.no_default_route is not defined }} domain-name-servers, + request subnet-mask, broadcast-address,{{ " routers," if dhcp_options.no_default_route is not vyos_defined }} domain-name-servers, rfc3442-classless-static-routes, domain-name, interface-mtu; # The require statement lists options that must be sent in order for an offer to be # accepted. Offers that do not contain all the listed options will be ignored! require subnet-mask; -{% if dhcp_options.reject is defined and dhcp_options.reject is not none %} +{% if dhcp_options.reject is vyos_defined %} # Block addresses coming from theses dhcp servers if configured. reject {{ dhcp_options.reject | join(', ') }}; {% endif %} diff --git a/data/templates/dhcp-client/ipv6.j2 b/data/templates/dhcp-client/ipv6.j2 new file mode 100644 index 000000000..e136b1789 --- /dev/null +++ b/data/templates/dhcp-client/ipv6.j2 @@ -0,0 +1,60 @@ +### Autogenerated by interface.py ### + +# man https://www.unix.com/man-page/debian/5/dhcp6c.conf/ +interface {{ ifname }} { +{% if dhcpv6_options.duid is vyos_defined %} + send client-id {{ dhcpv6_options.duid }}; +{% endif %} +{% if address is vyos_defined and 'dhcpv6' in address %} + request domain-name-servers; + request domain-name; +{% if dhcpv6_options.parameters_only is vyos_defined %} + information-only; +{% endif %} +{% if dhcpv6_options.temporary is not vyos_defined %} + send ia-na 0; # non-temporary address +{% endif %} +{% if dhcpv6_options.rapid_commit is vyos_defined %} + send rapid-commit; # wait for immediate reply instead of advertisements +{% endif %} +{% endif %} +{% if dhcpv6_options.pd is vyos_defined %} +{% for pd in dhcpv6_options.pd %} + send ia-pd {{ pd }}; # prefix delegation #{{ pd }} +{% endfor %} +{% endif %} +}; + +{% if address is vyos_defined and 'dhcpv6' in address %} +{% if dhcpv6_options.temporary is not vyos_defined %} +id-assoc na 0 { + # Identity association for non temporary address +}; +{% endif %} +{% endif %} + +{% if dhcpv6_options.pd is vyos_defined %} +{% for pd, pd_config in dhcpv6_options.pd.items() %} +id-assoc pd {{ pd }} { +{# length got a default value #} + prefix ::/{{ pd_config.length }} infinity; +{% set sla_len = 64 - pd_config.length | int %} +{% set count = namespace(value=0) %} +{% for interface, interface_config in pd_config.interface.items() if pd_config.interface is vyos_defined %} + prefix-interface {{ interface }} { + sla-len {{ sla_len }}; +{% if interface_config.sla_id is vyos_defined %} + sla-id {{ interface_config.sla_id }}; +{% else %} + sla-id {{ count.value }}; +{% endif %} +{% if interface_config.address is vyos_defined %} + ifid {{ interface_config.address }}; +{% endif %} + }; +{% set count.value = count.value + 1 %} +{% endfor %} +}; +{% endfor %} +{% endif %} + diff --git a/data/templates/dhcp-client/ipv6.tmpl b/data/templates/dhcp-client/ipv6.tmpl deleted file mode 100644 index c292664e9..000000000 --- a/data/templates/dhcp-client/ipv6.tmpl +++ /dev/null @@ -1,60 +0,0 @@ -### Autogenerated by interface.py ### - -# man https://www.unix.com/man-page/debian/5/dhcp6c.conf/ -interface {{ ifname }} { -{% if dhcpv6_options is defined and dhcpv6_options.duid is defined and dhcpv6_options.duid is not none %} - send client-id {{ dhcpv6_options.duid }}; -{% endif %} -{% if address is defined and 'dhcpv6' in address %} - request domain-name-servers; - request domain-name; -{% if dhcpv6_options is defined and dhcpv6_options.parameters_only is defined %} - information-only; -{% endif %} -{% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} - send ia-na 0; # non-temporary address -{% endif %} -{% if dhcpv6_options is defined and dhcpv6_options.rapid_commit is defined %} - send rapid-commit; # wait for immediate reply instead of advertisements -{% endif %} -{% endif %} -{% if dhcpv6_options is defined and dhcpv6_options.pd is defined %} -{% for pd in dhcpv6_options.pd %} - send ia-pd {{ pd }}; # prefix delegation #{{ pd }} -{% endfor %} -{% endif %} -}; - -{% if address is defined and 'dhcpv6' in address %} -{% if dhcpv6_options is not defined or dhcpv6_options.temporary is not defined %} -id-assoc na 0 { - # Identity association for non temporary address -}; -{% endif %} -{% endif %} - -{% if dhcpv6_options is defined and dhcpv6_options.pd is defined %} -{% for pd in dhcpv6_options.pd %} -id-assoc pd {{ pd }} { -{# length got a default value #} - prefix ::/{{ dhcpv6_options.pd[pd].length }} infinity; -{% set sla_len = 64 - dhcpv6_options.pd[pd].length|int %} -{% set count = namespace(value=0) %} -{% for interface in dhcpv6_options.pd[pd].interface if dhcpv6_options.pd[pd].interface is defined %} - prefix-interface {{ interface }} { - sla-len {{ sla_len }}; -{% if dhcpv6_options.pd[pd].interface[interface].sla_id is defined and dhcpv6_options.pd[pd].interface[interface].sla_id is not none %} - sla-id {{ dhcpv6_options.pd[pd].interface[interface].sla_id }}; -{% else %} - sla-id {{ count.value }}; -{% endif %} -{% if dhcpv6_options.pd[pd].interface[interface].address is defined and dhcpv6_options.pd[pd].interface[interface].address is not none %} - ifid {{ dhcpv6_options.pd[pd].interface[interface].address }}; -{% endif %} - }; -{% set count.value = count.value + 1 %} -{% endfor %} -}; -{% endfor %} -{% endif %} - diff --git a/data/templates/dhcp-relay/dhcrelay.conf.tmpl b/data/templates/dhcp-relay/dhcrelay.conf.j2 index a9d17ed9a..11710bd8e 100644 --- a/data/templates/dhcp-relay/dhcrelay.conf.tmpl +++ b/data/templates/dhcp-relay/dhcrelay.conf.j2 @@ -1,6 +1,6 @@ ### Autogenerated by dhcp_relay.py ### -{% set max_size = '-A ' + relay_options.max_size if relay_options.max_size is defined and relay_options.max_size is not none %} +{% set max_size = '-A ' ~ relay_options.max_size if relay_options.max_size is vyos_defined %} {# hop_count and relay_agents_packets is a default option, thus it is always present #} OPTIONS="-c {{ relay_options.hop_count }} -a -m {{ relay_options.relay_agents_packets }} {{ max_size }} -i {{ interface | join(' -i ') }} {{ server | join(' ') }}" diff --git a/data/templates/dhcp-relay/dhcrelay6.conf.j2 b/data/templates/dhcp-relay/dhcrelay6.conf.j2 new file mode 100644 index 000000000..6365346b4 --- /dev/null +++ b/data/templates/dhcp-relay/dhcrelay6.conf.j2 @@ -0,0 +1,21 @@ +### Autogenerated by dhcpv6_relay.py ### + +{# upstream_interface is mandatory so it's always present #} +{% set upstream = namespace(value='') %} +{% for interface, config in upstream_interface.items() %} +{% for address in config.address %} +{% set upstream.value = upstream.value ~ '-u ' ~ address ~ '%' ~ interface ~ ' ' %} +{% endfor %} +{% endfor %} +{# listen_interface is mandatory so it's always present #} +{% set listen = namespace(value='') %} +{% for interface, config in listen_interface.items() %} +{% if config.address is vyos_defined %} +{% set listen.value = listen.value ~ '-l ' ~ config.address ~ '%' ~ interface ~ ' ' %} +{% else %} +{% set listen.value = listen.value ~ '-l ' ~ interface ~ ' ' %} +{% endif %} +{% endfor %} + +OPTIONS="{{ listen.value }} {{ upstream.value }} -c {{ max_hop_count }} {{ '-I' if use_interface_id_option is vyos_defined }}" + diff --git a/data/templates/dhcp-relay/dhcrelay6.conf.tmpl b/data/templates/dhcp-relay/dhcrelay6.conf.tmpl deleted file mode 100644 index 58c216b7c..000000000 --- a/data/templates/dhcp-relay/dhcrelay6.conf.tmpl +++ /dev/null @@ -1,21 +0,0 @@ -### Autogenerated by dhcpv6_relay.py ### - -{# upstream_interface is mandatory so it's always present #} -{% set upstream = namespace(value='') %} -{% for interface, config in upstream_interface.items() %} -{% for address in config.address %} -{% set upstream.value = upstream.value + '-u ' + address + '%' + interface + ' ' %} -{% endfor %} -{% endfor %} -{# listen_interface is mandatory so it's always present #} -{% set listen = namespace(value='') %} -{% for interface, config in listen_interface.items() %} -{% if config.address is defined and config.address is not none %} -{% set listen.value = listen.value + '-l ' + config.address + '%' + interface + ' ' %} -{% else %} -{% set listen.value = listen.value + '-l ' + interface + ' ' %} -{% endif %} -{% endfor %} - -OPTIONS="{{ listen.value }} {{ upstream.value }} -c {{ max_hop_count }} {{ '-I' if use_interface_id_option is defined }}" - diff --git a/data/templates/dhcp-server/dhcpd.conf.j2 b/data/templates/dhcp-server/dhcpd.conf.j2 new file mode 100644 index 000000000..4c2da0aa5 --- /dev/null +++ b/data/templates/dhcp-server/dhcpd.conf.j2 @@ -0,0 +1,246 @@ +### Autogenerated by dhcp_server.py ### + +# For options please consult the following website: +# https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html +# +# log-facility local7; +{% if hostfile_update is vyos_defined %} +on release { + set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name); + set ClientIp = binary-to-ascii(10, 8, ".",leased-address); + execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", ""); +} +on expiry { + set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name); + set ClientIp = binary-to-ascii(10, 8, ".",leased-address); + execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", ""); +} +{% endif %} + +{{ 'use-host-decl-names on;' if host_decl_name is vyos_defined }} +ddns-update-style {{ 'interim' if dynamic_dns_update is vyos_defined else 'none' }}; +option rfc3442-static-route code 121 = array of integer 8; +option windows-static-route code 249 = array of integer 8; +option wpad-url code 252 = text; + +# Vendor specific options - Ubiquiti Networks +option space ubnt; +option ubnt.unifi-controller code 1 = ip-address; +class "ubnt" { + match if substring (option vendor-class-identifier , 0, 4) = "ubnt"; + option vendor-class-identifier "ubnt"; + vendor-option-space ubnt; +} + +{% if global_parameters is vyos_defined %} +# The following {{ global_parameters | length }} line(s) have been added as +# global-parameters in the CLI and have not been validated !!! +{% for parameter in global_parameters %} +{{ parameter }} +{% endfor %} + +{% endif %} +{% if failover is vyos_defined %} +# DHCP failover configuration +failover peer "{{ failover.name }}" { +{% if failover.status == 'primary' %} + primary; + mclt 1800; + split 128; +{% elif failover.status == 'secondary' %} + secondary; +{% endif %} + address {{ failover.source_address }}; + port 647; + peer address {{ failover.remote }}; + peer port 647; + max-response-delay 30; + max-unacked-updates 10; + load balance max seconds 3; +} +{% endif %} +{% if listen_address is vyos_defined %} + +# DHCP server serving relay subnet, we need a connector to the real world +{% for address in listen_address %} +# Connected subnet statement for listen-address {{ address }} +subnet {{ address | network_from_ipv4 }} netmask {{ address | netmask_from_ipv4 }} { } +{% endfor %} +{% endif %} + +# Shared network configration(s) +{% if shared_network_name is vyos_defined %} +{% for network, network_config in shared_network_name.items() if network_config.disable is not vyos_defined %} +shared-network {{ network }} { +{% if network_config.authoritative is vyos_defined %} + authoritative; +{% endif %} +{% if network_config.name_server is vyos_defined %} + option domain-name-servers {{ network_config.name_server | join(', ') }}; +{% endif %} +{% if network_config.domain_name is vyos_defined %} + option domain-name "{{ network_config.domain_name }}"; +{% endif %} +{% if network_config.domain_search is vyos_defined %} + option domain-search "{{ network_config.domain_search | join('", "') }}"; +{% endif %} +{% if network_config.ntp_server is vyos_defined %} + option ntp-servers {{ network_config.ntp_server | join(', ') }}; +{% endif %} +{% if network_config.ping_check is vyos_defined %} + ping-check true; +{% endif %} +{% if network_config.shared_network_parameters is vyos_defined %} + # The following {{ network_config.shared_network_parameters | length }} line(s) + # were added as shared-network-parameters in the CLI and have not been validated +{% for parameter in network_config.shared_network_parameters %} + {{ parameter }} +{% endfor %} +{% endif %} +{% if network_config.subnet is vyos_defined %} +{% for subnet, subnet_config in network_config.subnet.items() %} +{% if subnet_config.description is vyos_defined %} + # {{ subnet_config.description }} +{% endif %} + subnet {{ subnet | address_from_cidr }} netmask {{ subnet | netmask_from_cidr }} { +{% if subnet_config.name_server is vyos_defined %} + option domain-name-servers {{ subnet_config.name_server | join(', ') }}; +{% endif %} +{% if subnet_config.domain_name is vyos_defined %} + option domain-name "{{ subnet_config.domain_name }}"; +{% endif %} +{% if subnet_config.domain_search is vyos_defined %} + option domain-search "{{ subnet_config.domain_search | join('", "') }}"; +{% endif %} +{% if subnet_config.ntp_server is vyos_defined %} + option ntp-servers {{ subnet_config.ntp_server | join(', ') }}; +{% endif %} +{% if subnet_config.pop_server is vyos_defined %} + option pop-server {{ subnet_config.pop_server | join(', ') }}; +{% endif %} +{% if subnet_config.smtp_server is vyos_defined %} + option smtp-server {{ subnet_config.smtp_server | join(', ') }}; +{% endif %} +{% if subnet_config.time_server is vyos_defined %} + option time-servers {{ subnet_config.time_server | join(', ') }}; +{% endif %} +{% if subnet_config.wins_server is vyos_defined %} + option netbios-name-servers {{ subnet_config.wins_server | join(', ') }}; +{% endif %} +{% if subnet_config.static_route is vyos_defined %} +{% set static_default_route = '' %} +{% if subnet_config.default_router is vyos_defined %} +{% set static_default_route = ', ' ~ '0.0.0.0/0' | isc_static_route(subnet_config.default_router) %} +{% endif %} +{% if subnet_config.static_route is vyos_defined %} +{% set rfc3442_routes = [] %} +{% for route, route_options in subnet_config.static_route.items() %} +{% set rfc3442_routes = rfc3442_routes.append(route | isc_static_route(route_options.next_hop)) %} +{% endfor %} + option rfc3442-static-route {{ rfc3442_routes | join(', ') }}{{ static_default_route }}; + option windows-static-route {{ rfc3442_routes | join(', ') }}; +{% endif %} +{% endif %} +{% if subnet_config.ip_forwarding is vyos_defined %} + option ip-forwarding true; +{% endif %} +{% if subnet_config.default_router is vyos_defined %} + option routers {{ subnet_config.default_router }}; +{% endif %} +{% if subnet_config.server_identifier is vyos_defined %} + option dhcp-server-identifier {{ subnet_config.server_identifier }}; +{% endif %} +{% if subnet_config.subnet_parameters is vyos_defined %} + # The following {{ subnet_config.subnet_parameters | length }} line(s) were added as + # subnet-parameters in the CLI and have not been validated!!! +{% for parameter in subnet_config.subnet_parameters %} + {{ parameter }} +{% endfor %} +{% endif %} +{% if subnet_config.tftp_server_name is vyos_defined %} + option tftp-server-name "{{ subnet_config.tftp_server_name }}"; +{% endif %} +{% if subnet_config.bootfile_name is vyos_defined %} + option bootfile-name "{{ subnet_config.bootfile_name }}"; + filename "{{ subnet_config.bootfile_name }}"; +{% endif %} +{% if subnet_config.bootfile_server is vyos_defined %} + next-server {{ subnet_config.bootfile_server }}; +{% endif %} +{% if subnet_config.bootfile_size is vyos_defined %} + option boot-size {{ subnet_config.bootfile_size }}; +{% endif %} +{% if subnet_config.time_offset is vyos_defined %} + option time-offset {{ subnet_config.time_offset }}; +{% endif %} +{% if subnet_config.wpad_url is vyos_defined %} + option wpad-url "{{ subnet_config.wpad_url }}"; +{% endif %} +{% if subnet_config.client_prefix_length is vyos_defined %} + option subnet-mask {{ ('0.0.0.0/' ~ subnet_config.client_prefix_length) | netmask_from_cidr }}; +{% endif %} +{% if subnet_config.lease is vyos_defined %} + default-lease-time {{ subnet_config.lease }}; + max-lease-time {{ subnet_config.lease }}; +{% endif %} +{% if network_config.ping_check is not vyos_defined and subnet_config.ping_check is vyos_defined %} + ping-check true; +{% endif %} +{% if subnet_config.static_mapping is vyos_defined %} +{% for host, host_config in subnet_config.static_mapping.items() if host_config.disable is not vyos_defined %} + host {{ host | replace('_','-') if host_decl_name is vyos_defined else network | replace('_','-') ~ '_' ~ host | replace('_','-') }} { +{% if host_config.ip_address is vyos_defined %} + fixed-address {{ host_config.ip_address }}; +{% endif %} + hardware ethernet {{ host_config.mac_address }}; +{% if host_config.static_mapping_parameters is vyos_defined %} + # The following {{ host_config.static_mapping_parameters | length }} line(s) were added + # as static-mapping-parameters in the CLI and have not been validated +{% for parameter in host_config.static_mapping_parameters %} + {{ parameter }} +{% endfor %} +{% endif %} + } +{% endfor %} +{% endif %} +{% if subnet_config.vendor_option.ubiquiti.unifi_controller is vyos_defined %} + option ubnt.unifi-controller {{ subnet_config.vendor_option.ubiquiti.unifi_controller }}; +{% endif %} +{% if subnet_config.range is vyos_defined %} +{# pool configuration can only be used if there follows a range option #} + pool { +{% endif %} +{% if subnet_config.enable_failover is vyos_defined %} + failover peer "{{ failover.name }}"; + deny dynamic bootp clients; +{% endif %} +{% if subnet_config.range is vyos_defined %} +{% for range, range_options in subnet_config.range.items() %} + range {{ range_options.start }} {{ range_options.stop }}; +{% endfor %} +{% endif %} +{% if subnet_config.range is vyos_defined %} +{# pool configuration can only be used if there follows a range option #} + } +{% endif %} + } +{% endfor %} +{% endif %} + on commit { + set shared-networkname = "{{ network }}"; +{% if hostfile_update is vyos_defined %} + set ClientIp = binary-to-ascii(10, 8, ".", leased-address); + set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)); + set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name, "empty_hostname"); + if not (ClientName = "empty_hostname") { + set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!"); + execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "commit", ClientName, ClientIp, ClientMac, ClientDomain); + } else { + log(concat("Hostname is not defined for client with IP: ", ClientIP, " MAC: ", ClientMac)); + } +{% endif %} + } +} + +{% endfor %} +{% endif %} diff --git a/data/templates/dhcp-server/dhcpd.conf.tmpl b/data/templates/dhcp-server/dhcpd.conf.tmpl deleted file mode 100644 index 233e2cc53..000000000 --- a/data/templates/dhcp-server/dhcpd.conf.tmpl +++ /dev/null @@ -1,231 +0,0 @@ -### Autogenerated by dhcp_server.py ### - -# For options please consult the following website: -# https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html -# -# log-facility local7; -{% if hostfile_update is defined %} -on release { - set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name); - set ClientIp = binary-to-ascii(10, 8, ".",leased-address); - execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", ""); -} -on expiry { - set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name); - set ClientIp = binary-to-ascii(10, 8, ".",leased-address); - execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", ""); -} -{% endif %} - -{{ 'use-host-decl-names on;' if host_decl_name is defined }} -ddns-update-style {{ 'interim' if dynamic_dns_update is defined else 'none' }}; -option rfc3442-static-route code 121 = array of integer 8; -option windows-static-route code 249 = array of integer 8; -option wpad-url code 252 = text; - -{% if global_parameters is defined and global_parameters is not none %} -# The following {{ global_parameters | length }} line(s) have been added as -# global-parameters in the CLI and have not been validated !!! -{% for parameter in global_parameters %} -{{ parameter }} -{% endfor %} - -{% endif %} -{% if failover is defined and failover is not none %} -# DHCP failover configuration -failover peer "{{ failover.name }}" { -{% if failover.status == 'primary' %} - primary; - mclt 1800; - split 128; -{% elif failover.status == 'secondary' %} - secondary; -{% endif %} - address {{ failover.source_address }}; - port 520; - peer address {{ failover.remote }}; - peer port 520; - max-response-delay 30; - max-unacked-updates 10; - load balance max seconds 3; -} -{% endif %} -{% if listen_address is defined and listen_address is not none %} - -# DHCP server serving relay subnet, we need a connector to the real world -{% for address in listen_address %} -# Connected subnet statement for listen-address {{ address }} -subnet {{ address | network_from_ipv4 }} netmask {{ address | netmask_from_ipv4 }} { } -{% endfor %} -{% endif %} - -# Shared network configration(s) -{% if shared_network_name is defined and shared_network_name is not none %} -{% for network, network_config in shared_network_name.items() if network_config.disable is not defined %} -shared-network {{ network | replace('_','-') }} { -{% if network_config.authoritative is defined %} - authoritative; -{% endif %} -{% if network_config.name_server is defined and network_config.name_server is not none %} - option domain-name-servers {{ network_config.name_server | join(', ') }}; -{% endif %} -{% if network_config.domain_name is defined and network_config.domain_name is not none %} - option domain-name "{{ network_config.domain_name }}"; -{% endif %} -{% if network_config.domain_search is defined and network_config.domain_search is not none %} - option domain-search "{{ network_config.domain_search | join('", "') }}"; -{% endif %} -{% if network_config.ntp_server is defined and network_config.ntp_server is not none %} - option ntp-servers {{ network_config.ntp_server | join(', ') }}; -{% endif %} -{% if network_config.ping_check is defined %} - ping-check true; -{% endif %} -{% if network_config.shared_network_parameters is defined and network_config.shared_network_parameters is not none %} - # The following {{ network_config.shared_network_parameters | length }} line(s) - # were added as shared-network-parameters in the CLI and have not been validated -{% for parameter in network_config.shared_network_parameters %} - {{ parameter }} -{% endfor %} -{% endif %} -{% if network_config.subnet is defined and network_config.subnet is not none %} -{% for subnet, subnet_config in network_config.subnet.items() %} -{% if subnet_config.description is defined and subnet_config.description is not none %} - # {{ subnet_config.description }} -{% endif %} - subnet {{ subnet | address_from_cidr }} netmask {{ subnet | netmask_from_cidr }} { -{% if subnet_config.name_server is defined and subnet_config.name_server is not none %} - option domain-name-servers {{ subnet_config.name_server | join(', ') }}; -{% endif %} -{% if subnet_config.domain_name is defined and subnet_config.domain_name is not none %} - option domain-name "{{ subnet_config.domain_name }}"; -{% endif %} -{% if subnet_config.domain_search is defined and subnet_config.domain_search is not none %} - option domain-search "{{ subnet_config.domain_search | join('", "') }}"; -{% endif %} -{% if subnet_config.ntp_server is defined and subnet_config.ntp_server is not none %} - option ntp-servers {{ subnet_config.ntp_server | join(', ') }}; -{% endif %} -{% if subnet_config.pop_server is defined and subnet_config.pop_server is not none %} - option pop-server {{ subnet_config.pop_server | join(', ') }}; -{% endif %} -{% if subnet_config.smtp_server is defined and subnet_config.smtp_server is not none %} - option smtp-server {{ subnet_config.smtp_server | join(', ') }}; -{% endif %} -{% if subnet_config.time_server is defined and subnet_config.time_server is not none %} - option time-servers {{ subnet_config.time_server | join(', ') }}; -{% endif %} -{% if subnet_config.wins_server is defined and subnet_config.wins_server is not none %} - option netbios-name-servers {{ subnet_config.wins_server | join(', ') }}; -{% endif %} -{% if subnet_config.static_route is defined and subnet_config.static_route is not none %} -{% set static_default_route = '' %} -{% if subnet_config.default_router and subnet_config.default_router is not none %} -{% set static_default_route = ', ' + '0.0.0.0/0' | isc_static_route(subnet_config.default_router) %} -{% endif %} -{% if subnet_config.static_route is defined and subnet_config.static_route is not none %} -{% set rfc3442_routes = [] %} -{% for route, route_options in subnet_config.static_route.items() %} -{% set rfc3442_routes = rfc3442_routes.append(route | isc_static_route(route_options.next_hop)) %} -{% endfor %} - option rfc3442-static-route {{ rfc3442_routes | join(', ') }}{{ static_default_route }}; - option windows-static-route {{ rfc3442_routes | join(', ') }}; -{% endif %} -{% endif %} -{% if subnet_config.ip_forwarding is defined %} - option ip-forwarding true; -{% endif %} -{% if subnet_config.default_router and subnet_config.default_router is not none %} - option routers {{ subnet_config.default_router }}; -{% endif %} -{% if subnet_config.server_identifier is defined and subnet_config.server_identifier is not none %} - option dhcp-server-identifier {{ subnet_config.server_identifier }}; -{% endif %} -{% if subnet_config.subnet_parameters is defined and subnet_config.subnet_parameters is not none %} - # The following {{ subnet_config.subnet_parameters | length }} line(s) were added as - # subnet-parameters in the CLI and have not been validated!!! -{% for parameter in subnet_config.subnet_parameters %} - {{ parameter }} -{% endfor %} -{% endif %} -{% if subnet_config.tftp_server_name is defined and subnet_config.tftp_server_name is not none %} - option tftp-server-name "{{ subnet_config.tftp_server_name }}"; -{% endif %} -{% if subnet_config.bootfile_name is defined and subnet_config.bootfile_name is not none %} - option bootfile-name "{{ subnet_config.bootfile_name }}"; - filename "{{ subnet_config.bootfile_name }}"; -{% endif %} -{% if subnet_config.bootfile_server is defined and subnet_config.bootfile_server is not none %} - next-server {{ subnet_config.bootfile_server }}; -{% endif %} -{% if subnet_config.time_offset is defined and subnet_config.time_offset is not none %} - option time-offset {{ subnet_config.time_offset }}; -{% endif %} -{% if subnet_config.wpad_url is defined and subnet_config.wpad_url is not none %} - option wpad-url "{{ subnet_config.wpad_url }}"; -{% endif %} -{% if subnet_config.client_prefix_length is defined and subnet_config.client_prefix_length is not none %} - option subnet-mask {{ subnet_config.client_prefix_length }}; -{% endif %} -{% if subnet_config.lease is defined and subnet_config.lease is not none %} - default-lease-time {{ subnet_config.lease }}; - max-lease-time {{ subnet_config.lease }}; -{% endif %} -{% if network_config.ping_check is not defined and subnet_config.ping_check is defined %} - ping-check true; -{% endif %} -{% if subnet_config.static_mapping is defined and subnet_config.static_mapping is not none %} -{% for host, host_config in subnet_config.static_mapping.items() if host_config.disable is not defined %} - host {{ host | replace('_','-') if host_decl_name is defined else network | replace('_','-') + '_' + host | replace('_','-') }} { -{% if host_config.ip_address is defined and host_config.ip_address is not none %} - fixed-address {{ host_config.ip_address }}; -{% endif %} - hardware ethernet {{ host_config.mac_address }}; -{% if host_config.static_mapping_parameters is defined and host_config.static_mapping_parameters is not none %} - # The following {{ host_config.static_mapping_parameters | length }} line(s) were added - # as static-mapping-parameters in the CLI and have not been validated -{% for parameter in host_config.static_mapping_parameters %} - {{ parameter }} -{% endfor %} -{% endif %} - } -{% endfor %} -{% endif %} -{% if subnet_config.range is defined and subnet_config.range is not none %} -{# pool configuration can only be used if there follows a range option #} - pool { -{% endif %} -{% if subnet_config.enable_failover is defined %} - failover peer "{{ failover.name }}"; - deny dynamic bootp clients; -{% endif %} -{% if subnet_config.range is defined and subnet_config.range is not none %} -{% for range, range_options in subnet_config.range.items() %} - range {{ range_options.start }} {{ range_options.stop }}; -{% endfor %} -{% endif %} -{% if subnet_config.range is defined and subnet_config.range is not none %} -{# pool configuration can only be used if there follows a range option #} - } -{% endif %} - } -{% endfor %} -{% endif %} - on commit { - set shared-networkname = "{{ network | replace('_','-') }}"; -{% if hostfile_update is defined %} - set ClientIp = binary-to-ascii(10, 8, ".", leased-address); - set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)); - set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name, "empty_hostname"); - if not (ClientName = "empty_hostname") { - set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!"); - execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "commit", ClientName, ClientIp, ClientMac, ClientDomain); - } else { - log(concat("Hostname is not defined for client with IP: ", ClientIP, " MAC: ", ClientMac)); - } -{% endif %} - } -} - -{% endfor %} -{% endif %} diff --git a/data/templates/dhcp-server/dhcpdv6.conf.j2 b/data/templates/dhcp-server/dhcpdv6.conf.j2 new file mode 100644 index 000000000..5c3471316 --- /dev/null +++ b/data/templates/dhcp-server/dhcpdv6.conf.j2 @@ -0,0 +1,132 @@ +### Autogenerated by dhcpv6_server.py ### + +# For options please consult the following website: +# https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html + +log-facility local7; +{% if preference is vyos_defined %} +option dhcp6.preference {{ preference }}; +{% endif %} + +{% if global_parameters.name_server is vyos_defined %} +option dhcp6.name-servers {{ global_parameters.name_server | join(', ') }}; +{% endif %} + +# Vendor specific options - Cisco +option space cisco code width 2 length width 2; +option cisco.tftp-servers code 1 = array of ip6-address; +option vsio.cisco code 9 = encapsulate cisco; + +# Shared network configration(s) +{% if shared_network_name is vyos_defined %} +{% for network, network_config in shared_network_name.items() if network_config.disable is not vyos_defined %} +shared-network {{ network }} { +{% if network_config.common_options is vyos_defined %} +{% if network_config.common_options.info_refresh_time is vyos_defined %} + option dhcp6.info-refresh-time {{ network_config.common_options.info_refresh_time }}; +{% endif %} +{% if network_config.common_options.domain_search is vyos_defined %} + option dhcp6.domain-search "{{ network_config.common_options.domain_search | join('", "') }}"; +{% endif %} +{% if network_config.common_options.name_server is vyos_defined %} + option dhcp6.name-servers {{ network_config.common_options.name_server | join(', ') }}; +{% endif %} +{% endif %} +{% if network_config.subnet is vyos_defined %} +{% for subnet, subnet_config in network_config.subnet.items() %} + subnet6 {{ subnet }} { +{% if subnet_config.address_range is vyos_defined %} +{% if subnet_config.address_range.prefix is vyos_defined %} +{% for prefix, prefix_config in subnet_config.address_range.prefix.items() %} + range6 {{ prefix }} {{ "temporary" if prefix_config.temporary is vyos_defined }}; +{% endfor %} +{% endif %} +{% if subnet_config.address_range.start is vyos_defined %} +{% for address, address_config in subnet_config.address_range.start.items() %} + range6 {{ address }} {{ address_config.stop }}; +{% endfor %} +{% endif %} +{% endif %} +{% if subnet_config.domain_search is vyos_defined %} + option dhcp6.domain-search "{{ subnet_config.domain_search | join('", "') }}"; +{% endif %} +{% if subnet_config.lease_time is vyos_defined %} +{% if subnet_config.lease_time.default is vyos_defined %} + default-lease-time {{ subnet_config.lease_time.default }}; +{% endif %} +{% if subnet_config.lease_time.maximum is vyos_defined %} + max-lease-time {{ subnet_config.lease_time.maximum }}; +{% endif %} +{% if subnet_config.lease_time.minimum is vyos_defined %} + min-lease-time {{ subnet_config.lease_time.minimum }}; +{% endif %} +{% endif %} +{% if subnet_config.name_server is vyos_defined %} + option dhcp6.name-servers {{ subnet_config.name_server | join(', ') }}; +{% endif %} +{% if subnet_config.nis_domain is vyos_defined %} + option dhcp6.nis-domain-name "{{ subnet_config.nis_domain }}"; +{% endif %} +{% if subnet_config.nis_server is vyos_defined %} + option dhcp6.nis-servers {{ subnet_config.nis_server | join(', ') }}; +{% endif %} +{% if subnet_config.nisplus_domain is vyos_defined %} + option dhcp6.nisp-domain-name "{{ subnet_config.nisplus_domain }}"; +{% endif %} +{% if subnet_config.nisplus_server is vyos_defined %} + option dhcp6.nisp-servers {{ subnet_config.nisplus_server | join(', ') }}; +{% endif %} +{% if subnet_config.sip_server is vyos_defined %} +{% set server_ip = [] %} +{% set server_fqdn = [] %} +{% for address in subnet_config.sip_server %} +{% if address | is_ipv6 %} +{% set server_ip = server_ip.append(address) %} +{% else %} +{% set server_fqdn = server_fqdn.append(address) %} +{% endif %} +{% endfor %} +{% if server_ip is vyos_defined and server_ip | length > 0 %} + option dhcp6.sip-servers-addresses {{ server_ip | join(', ') }}; +{% endif %} +{% if server_fqdn is vyos_defined and server_fqdn | length > 0 %} + option dhcp6.sip-servers-names "{{ server_fqdn | join('", "') }}"; +{% endif %} +{% endif %} +{% if subnet_config.sntp_server is vyos_defined %} + option dhcp6.sntp-servers {{ subnet_config.sntp_server | join(', ') }}; +{% endif %} +{% if subnet_config.prefix_delegation.start is vyos_defined %} +{% for prefix, prefix_config in subnet_config.prefix_delegation.start.items() %} + prefix6 {{ prefix }} {{ prefix_config.stop }} /{{ prefix_config.prefix_length }}; +{% endfor %} +{% endif %} +{% if subnet_config.static_mapping is vyos_defined %} + + # begin configuration of static client mappings +{% for host, host_config in subnet_config.static_mapping.items() if host_config.disable is not vyos_defined %} + host {{ network | replace('_','-') }}_{{ host | replace('_','-') }} { +{% if host_config.identifier is vyos_defined %} + host-identifier option dhcp6.client-id {{ host_config.identifier }}; +{% endif %} +{% if host_config.ipv6_address is vyos_defined %} + fixed-address6 {{ host_config.ipv6_address }}; +{% endif %} +{% if host_config.ipv6_prefix is vyos_defined %} + fixed-prefix6 {{ host_config.ipv6_prefix }}; +{% endif %} + } +{% endfor %} +{% endif %} +{% if subnet_config.vendor_option.cisco.tftp_server is vyos_defined %} + option cisco.tftp-servers {{ subnet_config.vendor_option.cisco.tftp_server | join(', ') }}; +{% endif %} + } +{% endfor %} +{% endif %} + on commit { + set shared-networkname = "{{ network }}"; + } +} +{% endfor %} +{% endif %} diff --git a/data/templates/dhcp-server/dhcpdv6.conf.tmpl b/data/templates/dhcp-server/dhcpdv6.conf.tmpl deleted file mode 100644 index 45d629928..000000000 --- a/data/templates/dhcp-server/dhcpdv6.conf.tmpl +++ /dev/null @@ -1,124 +0,0 @@ -### Autogenerated by dhcpv6_server.py ### - -# For options please consult the following website: -# https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html - -log-facility local7; -{% if preference is defined and preference is not none %} -option dhcp6.preference {{ preference }}; -{% endif %} - -{% if global_parameters is defined and global_parameters.name_server is defined and global_parameters.name_server is not none %} -option dhcp6.name-servers {{ global_parameters.name_server | join(', ') }}; -{% endif %} - -# Shared network configration(s) -{% if shared_network_name is defined and shared_network_name is not none %} -{% for network, network_config in shared_network_name.items() if network_config.disable is not defined %} -shared-network {{ network | replace('_','-') }} { -{% if network_config.common_options is defined and network_config.common_options is not none %} -{% if network_config.common_options.info_refresh_time is defined and network_config.common_options.info_refresh_time is not none %} - option dhcp6.info-refresh-time {{ network_config.common_options.info_refresh_time }}; -{% endif %} -{% if network_config.common_options.domain_search is defined and network_config.common_options.domain_search is not none %} - option dhcp6.domain-search "{{ network_config.common_options.domain_search | join('", "') }}"; -{% endif %} -{% if network_config.common_options.name_server is defined and network_config.common_options.name_server is not none %} - option dhcp6.name-servers {{ network_config.common_options.name_server | join(', ') }}; -{% endif %} -{% endif %} -{% if network_config.subnet is defined and network_config.subnet is not none %} -{% for subnet, subnet_config in network_config.subnet.items() %} - subnet6 {{ subnet }} { -{% if subnet_config.address_range is defined and subnet_config.address_range is not none %} -{% if subnet_config.address_range.prefix is defined and subnet_config.address_range.prefix is not none %} -{% for prefix, prefix_config in subnet_config.address_range.prefix.items() %} - range6 {{ prefix }} {{ "temporary" if prefix_config.temporary is defined }}; -{% endfor %} -{% endif %} -{% if subnet_config.address_range.start is defined and subnet_config.address_range.start is not none %} -{% for address, address_config in subnet_config.address_range.start.items() %} - range6 {{ address }} {{ address_config.stop }}; -{% endfor %} -{% endif %} -{% endif %} -{% if subnet_config.domain_search is defined and subnet_config.domain_search is not none %} - option dhcp6.domain-search "{{ subnet_config.domain_search | join('", "') }}"; -{% endif %} -{% if subnet_config.lease_time is defined and subnet_config.lease_time is not none %} -{% if subnet_config.lease_time.default is defined and subnet_config.lease_time.default is not none %} - default-lease-time {{ subnet_config.lease_time.default }}; -{% endif %} -{% if subnet_config.lease_time.maximum is defined and subnet_config.lease_time.maximum is not none %} - max-lease-time {{ subnet_config.lease_time.maximum }}; -{% endif %} -{% if subnet_config.lease_time.minimum is defined and subnet_config.lease_time.minimum is not none %} - min-lease-time {{ subnet_config.lease_time.minimum }}; -{% endif %} -{% endif %} -{% if subnet_config.name_server is defined and subnet_config.name_server is not none %} - option dhcp6.name-servers {{ subnet_config.name_server | join(', ') }}; -{% endif %} -{% if subnet_config.nis_domain is defined and subnet_config.nis_domain is not none %} - option dhcp6.nis-domain-name "{{ subnet_config.nis_domain }}"; -{% endif %} -{% if subnet_config.nis_server is defined and subnet_config.nis_server is not none %} - option dhcp6.nis-servers {{ subnet_config.nis_server | join(', ') }}; -{% endif %} -{% if subnet_config.nisplus_domain is defined and subnet_config.nisplus_domain is not none %} - option dhcp6.nisp-domain-name "{{ subnet_config.nisplus_domain }}"; -{% endif %} -{% if subnet_config.nisplus_server is defined and subnet_config.nisplus_server is not none %} - option dhcp6.nisp-servers {{ subnet_config.nisplus_server | join(', ') }}; -{% endif %} -{% if subnet_config.sip_server is defined and subnet_config.sip_server is not none %} -{% set server_ip = [] %} -{% set server_fqdn = [] %} -{% for address in subnet_config.sip_server %} -{% if address | is_ipv6 %} -{% set server_ip = server_ip.append(address) %} -{% else %} -{% set server_fqdn = server_fqdn.append(address) %} -{% endif %} -{% endfor %} -{% if server_ip is defined and server_ip | length > 0 %} - option dhcp6.sip-servers-addresses {{ server_ip | join(', ') }}; -{% endif %} -{% if server_fqdn is defined and server_fqdn | length > 0 %} - option dhcp6.sip-servers-names "{{ server_fqdn | join('", "') }}"; -{% endif %} -{% endif %} -{% if subnet_config.sntp_server is defined and subnet_config.sntp_server is not none %} - option dhcp6.sntp-servers {{ subnet_config.sntp_server | join(', ') }}; -{% endif %} -{% if subnet_config.prefix_delegation is defined and subnet_config.prefix_delegation.start is defined and subnet_config.prefix_delegation.start is not none %} -{% for prefix, prefix_config in subnet_config.prefix_delegation.start.items() %} - prefix6 {{ prefix }} {{ prefix_config.stop }} /{{ prefix_config.prefix_length }}; -{% endfor %} -{% endif %} -{% if subnet_config.static_mapping is defined and subnet_config.static_mapping is not none %} - - # begin configuration of static client mappings -{% for host, host_config in subnet_config.static_mapping.items() if host_config.disable is not defined %} - host {{ network | replace('_','-') }}_{{ host | replace('_','-') }} { -{% if host_config.identifier is defined and host_config.identifier is not none %} - host-identifier option dhcp6.client-id {{ host_config.identifier }}; -{% endif %} -{% if host_config.ipv6_address is defined and host_config.ipv6_address is not none %} - fixed-address6 {{ host_config.ipv6_address }}; -{% endif %} -{% if host_config.ipv6_prefix is defined and host_config.ipv6_prefix is not none %} - fixed-prefix6 {{ host_config.ipv6_prefix }}; -{% endif %} - } -{% endfor %} -{% endif %} - } -{% endfor %} -{% endif %} - on commit { - set shared-networkname = "{{ network | replace('_','-') }}"; - } -} -{% endfor %} -{% endif %} diff --git a/data/templates/dns-forwarding/recursor.conf.tmpl b/data/templates/dns-forwarding/recursor.conf.j2 index d44f756e8..c1950e1bc 100644 --- a/data/templates/dns-forwarding/recursor.conf.tmpl +++ b/data/templates/dns-forwarding/recursor.conf.j2 @@ -1,3 +1,4 @@ +{# j2lint: disable=single-statement-per-line #} ### Autogenerated by dns_forwarding.py ### # XXX: pdns recursor doesn't like whitespace near entry separators, @@ -19,8 +20,11 @@ max-cache-entries={{ cache_size }} # negative TTL for NXDOMAIN max-negative-ttl={{ negative_ttl }} +# timeout +network-timeout={{ timeout }} + # ignore-hosts-file -export-etc-hosts={{ 'no' if ignore_hosts_file is defined else 'yes' }} +export-etc-hosts={{ 'no' if ignore_hosts_file is vyos_defined else 'yes' }} # listen-address local-address={{ listen_address | join(',') }} @@ -29,7 +33,10 @@ local-address={{ listen_address | join(',') }} dnssec={{ dnssec }} # serve rfc1918 records -serve-rfc1918={{ 'no' if no_serve_rfc1918 is defined else 'yes' }} +serve-rfc1918={{ 'no' if no_serve_rfc1918 is vyos_defined else 'yes' }} + +# zones +auth-zones={% for z in authoritative_zones %}{{ z.name }}={{ z.file }}{{- "," if not loop.last -}}{% endfor %} forward-zones-file=recursor.forward-zones.conf diff --git a/data/templates/dns-forwarding/recursor.conf.lua.tmpl b/data/templates/dns-forwarding/recursor.conf.lua.j2 index e2506238d..e2506238d 100644 --- a/data/templates/dns-forwarding/recursor.conf.lua.tmpl +++ b/data/templates/dns-forwarding/recursor.conf.lua.j2 diff --git a/data/templates/dns-forwarding/recursor.forward-zones.conf.tmpl b/data/templates/dns-forwarding/recursor.forward-zones.conf.j2 index 3ab0c804d..de3269e47 100644 --- a/data/templates/dns-forwarding/recursor.forward-zones.conf.tmpl +++ b/data/templates/dns-forwarding/recursor.forward-zones.conf.j2 @@ -1,3 +1,4 @@ +{# j2lint: disable=operator-enclosed-by-spaces #} # Autogenerated by VyOS (vyos-hostsd) # Do not edit, your changes will get overwritten @@ -7,11 +8,11 @@ {# the order of tags, then by the order of nameservers within that tag #} {% set n = namespace(dot_zone_ns='') %} {% for tag in name_server_tags_recursor %} -{% set ns = '' %} -{% if tag in name_servers %} -{% set ns = ns + name_servers[tag]|join(', ') %} -{% set n.dot_zone_ns = (n.dot_zone_ns, ns)|join(', ') if n.dot_zone_ns != '' else ns %} -{% endif %} +{% set ns = '' %} +{% if tag in name_servers %} +{% set ns = ns + name_servers[tag] | join(', ') %} +{% set n.dot_zone_ns = (n.dot_zone_ns, ns) | join(', ') if n.dot_zone_ns != '' else ns %} +{% endif %} # {{ tag }}: {{ ns }} {% endfor %} @@ -19,10 +20,10 @@ +.={{ n.dot_zone_ns }} {% endif %} -{% if forward_zones is defined %} +{% if forward_zones is vyos_defined %} # zones added via 'service dns forwarding domain' -{% for zone, zonedata in forward_zones.items() %} -{{ "+" if zonedata['recursion_desired'] is defined }}{{ zone | replace('_', '-') }}={{ zonedata['server']|join(', ') }} -{% endfor %} +{% for zone, zonedata in forward_zones.items() %} +{{ "+" if zonedata.recursion_desired is vyos_defined }}{{ zone | replace('_', '-') }}={{ zonedata.server | join(', ') }} +{% endfor %} {% endif %} diff --git a/data/templates/dns-forwarding/recursor.vyos-hostsd.conf.lua.j2 b/data/templates/dns-forwarding/recursor.vyos-hostsd.conf.lua.j2 new file mode 100644 index 000000000..987c7de1f --- /dev/null +++ b/data/templates/dns-forwarding/recursor.vyos-hostsd.conf.lua.j2 @@ -0,0 +1,30 @@ +-- Autogenerated by VyOS (vyos-hostsd) -- +-- Do not edit, your changes will get overwritten -- + +{% if hosts %} +-- from 'system static-host-mapping' and DHCP server +{% for tag, taghosts in hosts.items() %} +{% for host, hostprops in taghosts.items() %} +addNTA("{{ host }}.", "{{ tag }}") +{% for a in hostprops['aliases'] %} +addNTA("{{ a }}.", "{{ tag }} alias") +{% endfor %} +{% endfor %} +{% endfor %} +{% endif %} + +{% if forward_zones is vyos_defined %} +-- from 'service dns forwarding domain' +{% for zone, zonedata in forward_zones.items() %} +{% if zonedata.addnta is vyos_defined %} +addNTA("{{ zone }}", "static") +{% endif %} +{% endfor %} +{% endif %} + +{% if authoritative_zones is vyos_defined %} +-- from 'service dns forwarding authoritative-domain' +{% for zone in authoritative_zones %} +addNTA("{{ zone }}", "static") +{% endfor %} +{% endif %} diff --git a/data/templates/dns-forwarding/recursor.vyos-hostsd.conf.lua.tmpl b/data/templates/dns-forwarding/recursor.vyos-hostsd.conf.lua.tmpl deleted file mode 100644 index 784d5c360..000000000 --- a/data/templates/dns-forwarding/recursor.vyos-hostsd.conf.lua.tmpl +++ /dev/null @@ -1,24 +0,0 @@ --- Autogenerated by VyOS (vyos-hostsd) -- --- Do not edit, your changes will get overwritten -- - -{% if hosts %} --- from 'system static-host-mapping' and DHCP server -{% for tag, taghosts in hosts.items() %} -{% for host, hostprops in taghosts.items() %} -addNTA("{{ host }}.", "{{ tag }}") -{% for a in hostprops['aliases'] %} -addNTA("{{ a }}.", "{{ tag }} alias") -{% endfor %} -{% endfor %} -{% endfor %} -{% endif %} - -{% if forward_zones is defined %} --- from 'service dns forwarding domain' -{% for zone, zonedata in forward_zones.items() %} -{% if zonedata['addnta'] is defined %} -addNTA("{{ zone }}", "static") -{% endif %} -{% endfor %} -{% endif %} - diff --git a/data/templates/dns-forwarding/recursor.zone.conf.j2 b/data/templates/dns-forwarding/recursor.zone.conf.j2 new file mode 100644 index 000000000..25193c2ec --- /dev/null +++ b/data/templates/dns-forwarding/recursor.zone.conf.j2 @@ -0,0 +1,6 @@ +; +; Autogenerated by dns_forwarding.py +; +{% for r in records %} +{{ r.name }} {{ r.ttl }} {{ r.type }} {{ r.value }} +{% endfor %} diff --git a/data/templates/dynamic-dns/ddclient.conf.j2 b/data/templates/dynamic-dns/ddclient.conf.j2 new file mode 100644 index 000000000..3c2d17cbb --- /dev/null +++ b/data/templates/dynamic-dns/ddclient.conf.j2 @@ -0,0 +1,51 @@ +### Autogenerated by dynamic_dns.py ### +daemon=1m +syslog=yes +ssl=yes + +{% if interface is vyos_defined %} +{% for iface, iface_config in interface.items() %} +# ddclient configuration for interface "{{ iface }}" +{% if iface_config.use_web is vyos_defined %} +{% set web_skip = ", web-skip='" ~ iface_config.use_web.skip ~ "'" if iface_config.use_web.skip is vyos_defined else '' %} +use=web, web='{{ iface_config.use_web.url }}'{{ web_skip }} +{% else %} +{{ 'usev6=if' if iface_config.ipv6_enable is vyos_defined else 'use=if' }}, if={{ iface }} +{% endif %} + +{% if iface_config.rfc2136 is vyos_defined %} +{% for rfc2136, config in iface_config.rfc2136.items() %} +{% for dns_record in config.record if config.record is vyos_defined %} +# RFC2136 dynamic DNS configuration for {{ rfc2136 }}, {{ config.zone }}, {{ dns_record }} +server={{ config.server }} +protocol=nsupdate +password={{ config.key }} +ttl={{ config.ttl }} +zone={{ config.zone }} +{{ dns_record }} + +{% endfor %} +{% endfor %} +{% endif %} + +{% if iface_config.service is vyos_defined %} +{% for service, config in iface_config.service.items() %} +{% for dns_record in config.host_name %} +# DynDNS provider configuration for {{ service }}, {{ dns_record }} +protocol={{ config.protocol }}, +max-interval=28d, +login={{ config.login }}, +password='{{ config.password }}', +{% if config.server is vyos_defined %} +server={{ config.server }}, +{% endif %} +{% if config.zone is vyos_defined %} +zone={{ config.zone }}, +{% endif %} +{{ dns_record }} + +{% endfor %} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} diff --git a/data/templates/dynamic-dns/ddclient.conf.tmpl b/data/templates/dynamic-dns/ddclient.conf.tmpl deleted file mode 100644 index 517e4bad4..000000000 --- a/data/templates/dynamic-dns/ddclient.conf.tmpl +++ /dev/null @@ -1,49 +0,0 @@ -### Autogenerated by dynamic_dns.py ### -daemon=1m -syslog=yes -ssl=yes - -{% for iface in interface %} -# ddclient configuration for interface "{{ iface }}" -{% if interface[iface].use_web is defined and interface[iface].use_web is not none %} -{% set web_skip = ", web-skip='" + interface[iface].use_web.skip + "'" if interface[iface].use_web.skip is defined else '' %} -use=web, web='{{ interface[iface].use_web.url }}'{{ web_skip }} -{% else %} -{{ 'usev6=if' if interface[iface].ipv6_enable is defined else 'use=if' }}, if={{ iface }} -{% endif %} - -{% if interface[iface].rfc2136 is defined and interface[iface].rfc2136 is not none %} -{% for rfc2136, config in interface[iface].rfc2136.items() %} -{% for dns_record in config.record if config.record is defined %} -# RFC2136 dynamic DNS configuration for {{ rfc2136 }}, {{ config.zone }}, {{ dns_record }} -server={{ config.server }} -protocol=nsupdate -password={{ config.key }} -ttl={{ config.ttl }} -zone={{ config.zone }} -{{ dns_record }} - -{% endfor %} -{% endfor %} -{% endif %} - -{% if interface[iface].service is defined and interface[iface].service is not none %} -{% for service, config in interface[iface].service.items() %} -{% for dns_record in config.host_name %} -# DynDNS provider configuration for {{ service }}, {{ dns_record }} -protocol={{ config.protocol }}, -max-interval=28d, -login={{ config.login }}, -password='{{ config.password }}', -{% if config.server %} -server={{ config.server }}, -{% endif %} -{% if config.zone %} -zone={{ config.zone }}, -{% endif %} -{{ dns_record }} - -{% endfor %} -{% endfor %} -{% endif %} -{% endfor %} diff --git a/data/templates/ethernet/wpa_supplicant.conf.tmpl b/data/templates/ethernet/wpa_supplicant.conf.j2 index 308d777f1..8f140f6cb 100644 --- a/data/templates/ethernet/wpa_supplicant.conf.tmpl +++ b/data/templates/ethernet/wpa_supplicant.conf.j2 @@ -31,19 +31,19 @@ ap_scan=0 fast_reauth=1 network={ -{% if eapol is defined and eapol is not none %} -{% if eapol.ca_certificate is defined and eapol.ca_certificate is not none %} +{% if eapol is vyos_defined %} +{% if eapol.ca_certificate is vyos_defined %} ca_cert="/run/wpa_supplicant/{{ ifname }}_ca.pem" -{% endif %} +{% endif %} client_cert="/run/wpa_supplicant/{{ ifname }}_cert.pem" private_key="/run/wpa_supplicant/{{ ifname }}_cert.key" -{% endif %} +{% endif %} # list of accepted authenticated key management protocols key_mgmt=IEEE8021X eap=TLS -{% if mac is defined and mac is not none %} +{% if mac is vyos_defined %} identity="{{ mac }}" {% else %} identity="{{ hw_id }}" diff --git a/data/templates/firewall/nftables-defines.j2 b/data/templates/firewall/nftables-defines.j2 new file mode 100644 index 000000000..4fa92f2e3 --- /dev/null +++ b/data/templates/firewall/nftables-defines.j2 @@ -0,0 +1,32 @@ +{% if group is vyos_defined %} +{% if group.address_group is vyos_defined %} +{% for group_name, group_conf in group.address_group.items() %} +define A_{{ group_name }} = { {{ group_conf.address | join(",") }} } +{% endfor %} +{% endif %} +{% if group.ipv6_address_group is vyos_defined %} +{% for group_name, group_conf in group.ipv6_address_group.items() %} +define A6_{{ group_name }} = { {{ group_conf.address | join(",") }} } +{% endfor %} +{% endif %} +{% if group.mac_group is vyos_defined %} +{% for group_name, group_conf in group.mac_group.items() %} +define M_{{ group_name }} = { {{ group_conf.mac_address | join(",") }} } +{% endfor %} +{% endif %} +{% if group.network_group is vyos_defined %} +{% for group_name, group_conf in group.network_group.items() %} +define N_{{ group_name }} = { {{ group_conf.network | join(",") }} } +{% endfor %} +{% endif %} +{% if group.ipv6_network_group is vyos_defined %} +{% for group_name, group_conf in group.ipv6_network_group.items() %} +define N6_{{ group_name }} = { {{ group_conf.network | join(",") }} } +{% endfor %} +{% endif %} +{% if group.port_group is vyos_defined %} +{% for group_name, group_conf in group.port_group.items() %} +define P_{{ group_name }} = { {{ group_conf.port | join(",") }} } +{% endfor %} +{% endif %} +{% endif %}
\ No newline at end of file diff --git a/data/templates/firewall/nftables-nat.j2 b/data/templates/firewall/nftables-nat.j2 new file mode 100644 index 000000000..1481e9104 --- /dev/null +++ b/data/templates/firewall/nftables-nat.j2 @@ -0,0 +1,182 @@ +#!/usr/sbin/nft -f + +{% macro nat_rule(rule, config, chain) %} +{% set comment = '' %} +{% set base_log = '' %} +{% set src_addr = 'ip saddr ' ~ config.source.address.replace('!','!= ') if config.source.address is vyos_defined %} +{% set dst_addr = 'ip daddr ' ~ config.destination.address.replace('!','!= ') if config.destination.address is vyos_defined %} +{# negated port groups need special treatment, move != in front of { } group #} +{% if config.source.port is vyos_defined and config.source.port.startswith('!') %} +{% set src_port = 'sport != { ' ~ config.source.port.replace('!','') ~ ' }' %} +{% else %} +{% set src_port = 'sport { ' ~ config.source.port ~ ' }' if config.source.port is vyos_defined %} +{% endif %} +{# negated port groups need special treatment, move != in front of { } group #} +{% if config.destination.port is vyos_defined and config.destination.port.startswith('!') %} +{% set dst_port = 'dport != { ' ~ config.destination.port.replace('!','') ~ ' }' %} +{% else %} +{% set dst_port = 'dport { ' ~ config.destination.port ~ ' }' if config.destination.port is vyos_defined %} +{% endif %} +{% if chain is vyos_defined('PREROUTING') %} +{% set comment = 'DST-NAT-' ~ rule %} +{% set base_log = '[NAT-DST-' ~ rule %} +{% set interface = ' iifname "' ~ config.inbound_interface ~ '"' if config.inbound_interface is vyos_defined and config.inbound_interface is not vyos_defined('any') else '' %} +{% if config.translation.address is vyos_defined %} +{# support 1:1 network translation #} +{% if config.translation.address | is_ip_network %} +{% set trns_addr = 'dnat ip prefix to ip daddr map { ' ~ config.destination.address ~ ' : ' ~ config.translation.address ~ ' }' %} +{# we can now clear out the dst_addr part as it's already covered in aboves map #} +{% set dst_addr = '' %} +{% else %} +{% set trns_addr = 'dnat to ' ~ config.translation.address %} +{% endif %} +{% endif %} +{% elif chain is vyos_defined('POSTROUTING') %} +{% set comment = 'SRC-NAT-' ~ rule %} +{% set base_log = '[NAT-SRC-' ~ rule %} +{% set interface = ' oifname "' ~ config.outbound_interface ~ '"' if config.outbound_interface is vyos_defined and config.outbound_interface is not vyos_defined('any') else '' %} +{% if config.translation.address is vyos_defined %} +{% if config.translation.address is vyos_defined('masquerade') %} +{% set trns_addr = config.translation.address %} +{% if config.translation.port is vyos_defined %} +{% set trns_addr = trns_addr ~ ' to ' %} +{% endif %} +{# support 1:1 network translation #} +{% elif config.translation.address | is_ip_network %} +{% set trns_addr = 'snat ip prefix to ip saddr map { ' ~ config.source.address ~ ' : ' ~ config.translation.address ~ ' }' %} +{# we can now clear out the src_addr part as it's already covered in aboves map #} +{% set src_addr = '' %} +{% else %} +{% set trns_addr = 'snat to ' ~ config.translation.address %} +{% endif %} +{% endif %} +{% endif %} +{% set trns_port = ':' ~ config.translation.port if config.translation.port is vyos_defined %} +{# protocol has a default value thus it is always present #} +{% if config.protocol is vyos_defined('tcp_udp') %} +{% set protocol = 'tcp' %} +{% set comment = comment ~ ' tcp_udp' %} +{% else %} +{% set protocol = config.protocol %} +{% endif %} +{% if config.log is vyos_defined %} +{% if config.exclude is vyos_defined %} +{% set log = base_log ~ '-EXCL]' %} +{% elif config.translation.address is vyos_defined('masquerade') %} +{% set log = base_log ~ '-MASQ]' %} +{% else %} +{% set log = base_log ~ ']' %} +{% endif %} +{% endif %} +{% if config.exclude is vyos_defined %} +{# rule has been marked as 'exclude' thus we simply return here #} +{% set trns_addr = 'return' %} +{% set trns_port = '' %} +{% endif %} +{# T1083: NAT address and port translation options #} +{% if config.translation.options is vyos_defined %} +{% if config.translation.options.address_mapping is vyos_defined('persistent') %} +{% set trns_opts_addr = 'persistent' %} +{% endif %} +{% if config.translation.options.port_mapping is vyos_defined('random') %} +{% set trns_opts_port = 'random' %} +{% elif config.translation.options.port_mapping is vyos_defined('fully-random') %} +{% set trns_opts_port = 'fully-random' %} +{% endif %} +{% endif %} +{% if trns_opts_addr is vyos_defined and trns_opts_port is vyos_defined %} +{% set trns_opts = trns_opts_addr ~ ',' ~ trns_opts_port %} +{% elif trns_opts_addr is vyos_defined %} +{% set trns_opts = trns_opts_addr %} +{% elif trns_opts_port is vyos_defined %} +{% set trns_opts = trns_opts_port %} +{% endif %} +{% set output = 'add rule ip nat ' ~ chain ~ interface %} +{% if protocol is not vyos_defined('all') %} +{% set output = output ~ ' ip protocol ' ~ protocol %} +{% endif %} +{% if src_addr is vyos_defined %} +{% set output = output ~ ' ' ~ src_addr %} +{% endif %} +{% if src_port is vyos_defined %} +{% set output = output ~ ' ' ~ protocol ~ ' ' ~ src_port %} +{% endif %} +{% if dst_addr is vyos_defined %} +{% set output = output ~ ' ' ~ dst_addr %} +{% endif %} +{% if dst_port is vyos_defined %} +{% set output = output ~ ' ' ~ protocol ~ ' ' ~ dst_port %} +{% endif %} +{# Count packets #} +{% set output = output ~ ' counter' %} +{# Special handling of log option, we must repeat the entire rule before the #} +{# NAT translation options are added, this is essential #} +{% if log is vyos_defined %} +{% set log_output = output ~ ' log prefix "' ~ log ~ '" comment "' ~ comment ~ '"' %} +{% endif %} +{% if trns_addr is vyos_defined %} +{% set output = output ~ ' ' ~ trns_addr %} +{% endif %} +{% if trns_port is vyos_defined %} +{# Do not add a whitespace here, translation port must be directly added after IP address #} +{# e.g. 192.0.2.10:3389 #} +{% set output = output ~ trns_port %} +{% endif %} +{% if trns_opts is vyos_defined %} +{% set output = output ~ ' ' ~ trns_opts %} +{% endif %} +{% if comment is vyos_defined %} +{% set output = output ~ ' comment "' ~ comment ~ '"' %} +{% endif %} +{{ log_output if log_output is vyos_defined }} +{{ output }} +{# Special handling if protocol is tcp_udp, we must repeat the entire rule with udp as protocol #} +{% if config.protocol is vyos_defined('tcp_udp') %} +{# Beware of trailing whitespace, without it the comment tcp_udp will be changed to udp_udp #} +{{ log_output | replace('tcp ', 'udp ') if log_output is vyos_defined }} +{{ output | replace('tcp ', 'udp ') }} +{% endif %} +{% endmacro %} + +# Start with clean SNAT and DNAT chains +flush chain ip nat PREROUTING +flush chain ip nat POSTROUTING +{% if helper_functions is vyos_defined('remove') %} +{# NAT if going to be disabled - remove rules and targets from nftables #} +{% set base_command = 'delete rule ip raw' %} +{{ base_command }} PREROUTING handle {{ pre_ct_ignore }} +{{ base_command }} OUTPUT handle {{ out_ct_ignore }} +{{ base_command }} PREROUTING handle {{ pre_ct_conntrack }} +{{ base_command }} OUTPUT handle {{ out_ct_conntrack }} + +delete chain ip raw NAT_CONNTRACK + +{% elif helper_functions is vyos_defined('add') %} +{# NAT if enabled - add targets to nftables #} +add chain ip raw NAT_CONNTRACK +add rule ip raw NAT_CONNTRACK counter accept +{% set base_command = 'add rule ip raw' %} +{{ base_command }} PREROUTING position {{ pre_ct_ignore }} counter jump VYOS_CT_HELPER +{{ base_command }} OUTPUT position {{ out_ct_ignore }} counter jump VYOS_CT_HELPER +{{ base_command }} PREROUTING position {{ pre_ct_conntrack }} counter jump NAT_CONNTRACK +{{ base_command }} OUTPUT position {{ out_ct_conntrack }} counter jump NAT_CONNTRACK +{% endif %} + +# +# Destination NAT rules build up here +# +add rule ip nat PREROUTING counter jump VYOS_PRE_DNAT_HOOK +{% if destination.rule is vyos_defined %} +{% for rule, config in destination.rule.items() if config.disable is not vyos_defined %} +{{ nat_rule(rule, config, 'PREROUTING') }} +{% endfor %} +{% endif %} +# +# Source NAT rules build up here +# +add rule ip nat POSTROUTING counter jump VYOS_PRE_SNAT_HOOK +{% if source.rule is vyos_defined %} +{% for rule, config in source.rule.items() if config.disable is not vyos_defined %} +{{ nat_rule(rule, config, 'POSTROUTING') }} +{% endfor %} +{% endif %} diff --git a/data/templates/firewall/nftables-nat.tmpl b/data/templates/firewall/nftables-nat.tmpl deleted file mode 100644 index 40ed1b916..000000000 --- a/data/templates/firewall/nftables-nat.tmpl +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/sbin/nft -f - -{% macro nat_rule(rule, config, chain) %} -{% set comment = '' %} -{% set base_log = '' %} -{% set src_addr = 'ip saddr ' + config.source.address.replace('!','!= ') if config.source is defined and config.source.address is defined and config.source.address is not none %} -{% set dst_addr = 'ip daddr ' + config.destination.address.replace('!','!= ') if config.destination is defined and config.destination.address is defined and config.destination.address is not none %} -{# negated port groups need special treatment, move != in front of { } group #} -{% if config.source is defined and config.source.port is defined and config.source.port is not none and config.source.port.startswith('!=') %} -{% set src_port = 'sport != { ' + config.source.port.replace('!=','') + ' }' %} -{% else %} -{% set src_port = 'sport { ' + config.source.port + ' }' if config.source is defined and config.source.port is defined and config.source.port is not none %} -{% endif %} -{# negated port groups need special treatment, move != in front of { } group #} -{% if config.destination is defined and config.destination.port is defined and config.destination.port is not none and config.destination.port.startswith('!=') %} -{% set dst_port = 'dport != { ' + config.destination.port.replace('!=','') + ' }' %} -{% else %} -{% set dst_port = 'dport { ' + config.destination.port + ' }' if config.destination is defined and config.destination.port is defined and config.destination.port is not none %} -{% endif %} -{% if chain == 'PREROUTING' %} -{% set comment = 'DST-NAT-' + rule %} -{% set base_log = '[NAT-DST-' + rule %} -{% set interface = ' iifname "' + config.inbound_interface + '"' if config.inbound_interface is defined and config.inbound_interface != 'any' else '' %} -{% if config.translation is defined and config.translation.address is defined and config.translation.address is not none %} -{# support 1:1 network translation #} -{% if config.translation.address | is_ip_network %} -{% set trns_addr = 'dnat ip prefix to ip daddr map { ' + config.destination.address + ' : ' + config.translation.address + ' }' %} -{# we can now clear out the dst_addr part as it's already covered in aboves map #} -{% set dst_addr = '' %} -{% else %} -{% set trns_addr = 'dnat to ' + config.translation.address %} -{% endif %} -{% endif %} -{% elif chain == 'POSTROUTING' %} -{% set comment = 'SRC-NAT-' + rule %} -{% set base_log = '[NAT-SRC-' + rule %} -{% set interface = ' oifname "' + config.outbound_interface + '"' if config.outbound_interface is defined and config.outbound_interface != 'any' else '' %} -{% if config.translation is defined and config.translation.address is defined and config.translation.address is not none %} -{% if config.translation.address == 'masquerade' %} -{% set trns_addr = config.translation.address %} -{% if config.translation.port is defined and config.translation.port is not none %} -{% set trns_addr = trns_addr + ' to ' %} -{% endif %} -{# support 1:1 network translation #} -{% elif config.translation.address | is_ip_network %} -{% set trns_addr = 'snat ip prefix to ip saddr map { ' + config.source.address + ' : ' + config.translation.address + ' }' %} -{# we can now clear out the src_addr part as it's already covered in aboves map #} -{% set src_addr = '' %} -{% else %} -{% set trns_addr = 'snat to ' + config.translation.address %} -{% endif %} -{% endif %} -{% endif %} -{% set trns_port = ':' + config.translation.port if config.translation is defined and config.translation.port is defined and config.translation.port is not none %} -{# protocol has a default value thus it is always present #} -{% if config.protocol == 'tcp_udp' %} -{% set protocol = 'tcp' %} -{% set comment = comment + ' tcp_udp' %} -{% else %} -{% set protocol = config.protocol %} -{% endif %} -{% if config.log is defined %} -{% if config.exclude is defined %} -{% set log = base_log + '-EXCL]' %} -{% elif config.translation is defined and config.translation.address is defined and config.translation.address == 'masquerade' %} -{% set log = base_log +'-MASQ]' %} -{% else %} -{% set log = base_log + ']' %} -{% endif %} -{% endif %} -{% if config.exclude is defined %} -{# rule has been marked as 'exclude' thus we simply return here #} -{% set trns_addr = 'return' %} -{% set trns_port = '' %} -{% endif %} -{# T1083: NAT address and port translation options #} -{% if config.translation is defined and config.translation.options is defined and config.translation.options is not none %} -{% if config.translation.options.address_mapping is defined and config.translation.options.address_mapping == "persistent" %} -{% set trns_opts_addr = 'persistent' %} -{% endif %} -{% if config.translation.options.port_mapping is defined %} -{% if config.translation.options.port_mapping == "random" %} -{% set trns_opts_port = 'random' %} -{% elif config.translation.options.port_mapping == "fully-random" %} -{% set trns_opts_port = 'fully-random' %} -{% endif %} -{% endif %} -{% endif %} -{% if trns_opts_addr and trns_opts_port %} -{% set trns_opts = trns_opts_addr + ',' + trns_opts_port %} -{% elif trns_opts_addr %} -{% set trns_opts = trns_opts_addr %} -{% elif trns_opts_port %} -{% set trns_opts = trns_opts_port %} -{% endif %} -{% set output = 'add rule ip nat ' + chain + interface %} -{% if protocol != 'all' %} -{% set output = output + ' ip protocol ' + protocol %} -{% endif %} -{% if src_addr %} -{% set output = output + ' ' + src_addr %} -{% endif %} -{% if src_port %} -{% set output = output + ' ' + protocol + ' ' + src_port %} -{% endif %} -{% if dst_addr %} -{% set output = output + ' ' + dst_addr %} -{% endif %} -{% if dst_port %} -{% set output = output + ' ' + protocol + ' ' + dst_port %} -{% endif %} -{# Count packets #} -{% set output = output + ' counter' %} -{# Special handling of log option, we must repeat the entire rule before the #} -{# NAT translation options are added, this is essential #} -{% if log %} -{% set log_output = output + ' log prefix "' + log + '" comment "' + comment + '"' %} -{% endif %} -{% if trns_addr %} -{% set output = output + ' ' + trns_addr %} -{% endif %} -{% if trns_port %} -{# Do not add a whitespace here, translation port must be directly added after IP address #} -{# e.g. 192.0.2.10:3389 #} -{% set output = output + trns_port %} -{% endif %} -{% if trns_opts %} -{% set output = output + ' ' + trns_opts %} -{% endif %} -{% if comment %} -{% set output = output + ' comment "' + comment + '"' %} -{% endif %} -{{ log_output if log_output }} -{{ output }} -{# Special handling if protocol is tcp_udp, we must repeat the entire rule with udp as protocol #} -{% if config.protocol == 'tcp_udp' %} -{# Beware of trailing whitespace, without it the comment tcp_udp will be changed to udp_udp #} -{{ log_output | replace('tcp ', 'udp ') if log_output }} -{{ output | replace('tcp ', 'udp ') }} -{% endif %} -{% endmacro %} - -# Start with clean NAT table -flush table ip nat -{% if helper_functions == 'remove' %} -{# NAT if going to be disabled - remove rules and targets from nftables #} -{% set base_command = 'delete rule ip raw' %} -{{ base_command }} PREROUTING handle {{ pre_ct_ignore }} -{{ base_command }} OUTPUT handle {{ out_ct_ignore }} -{{ base_command }} PREROUTING handle {{ pre_ct_conntrack }} -{{ base_command }} OUTPUT handle {{ out_ct_conntrack }} - -delete chain ip raw NAT_CONNTRACK - -{% elif helper_functions == 'add' %} -{# NAT if enabled - add targets to nftables #} -add chain ip raw NAT_CONNTRACK -add rule ip raw NAT_CONNTRACK counter accept -{% set base_command = 'add rule ip raw' %} -{{ base_command }} PREROUTING position {{ pre_ct_ignore }} counter jump VYATTA_CT_HELPER -{{ base_command }} OUTPUT position {{ out_ct_ignore }} counter jump VYATTA_CT_HELPER -{{ base_command }} PREROUTING position {{ pre_ct_conntrack }} counter jump NAT_CONNTRACK -{{ base_command }} OUTPUT position {{ out_ct_conntrack }} counter jump NAT_CONNTRACK -{% endif %} - -# -# Destination NAT rules build up here -# -{% if destination is defined and destination.rule is defined and destination.rule is not none %} -{% for rule, config in destination.rule.items() if config.disable is not defined %} -{{ nat_rule(rule, config, 'PREROUTING') }} -{% endfor %} -{% endif %} -# -# Source NAT rules build up here -# -{% if source is defined and source.rule is defined and source.rule is not none %} -{% for rule, config in source.rule.items() if config.disable is not defined %} -{{ nat_rule(rule, config, 'POSTROUTING') }} -{% endfor %} -{% endif %} diff --git a/data/templates/firewall/nftables-nat66.j2 b/data/templates/firewall/nftables-nat66.j2 new file mode 100644 index 000000000..003b138b2 --- /dev/null +++ b/data/templates/firewall/nftables-nat66.j2 @@ -0,0 +1,102 @@ +#!/usr/sbin/nft -f + +{% macro nptv6_rule(rule,config, chain) %} +{% set comment = '' %} +{% set base_log = '' %} +{% set src_prefix = 'ip6 saddr ' ~ config.source.prefix if config.source.prefix is vyos_defined %} +{% set dest_address = 'ip6 daddr ' ~ config.destination.address if config.destination.address is vyos_defined %} +{% if chain is vyos_defined('PREROUTING') %} +{% set comment = 'DST-NAT66-' ~ rule %} +{% set base_log = '[NAT66-DST-' ~ rule %} +{% set interface = ' iifname "' ~ config.inbound_interface ~ '"' if config.inbound_interface is vyos_defined and config.inbound_interface is not vyos_defined('any') else '' %} +{% if config.translation.address | is_ip_network %} +{# support 1:1 network translation #} +{% set dnat_type = 'dnat prefix to ' %} +{% else %} +{% set dnat_type = 'dnat to ' %} +{% endif %} +{% set trns_address = dnat_type ~ config.translation.address if config.translation.address is vyos_defined %} +{% elif chain is vyos_defined('POSTROUTING') %} +{% set comment = 'SRC-NAT66-' ~ rule %} +{% set base_log = '[NAT66-SRC-' ~ rule %} +{% if config.translation.address is vyos_defined %} +{% if config.translation.address is vyos_defined('masquerade') %} +{% set trns_address = config.translation.address %} +{% else %} +{% if config.translation.address | is_ip_network %} +{# support 1:1 network translation #} +{% set snat_type = 'snat prefix to ' %} +{% else %} +{% set snat_type = 'snat to ' %} +{% endif %} +{% set trns_address = snat_type ~ config.translation.address %} +{% endif %} +{% endif %} +{% set interface = ' oifname "' ~ config.outbound_interface ~ '"' if config.outbound_interface is vyos_defined else '' %} +{% endif %} +{% if config.log is vyos_defined %} +{% if config.translation.address is vyos_defined('masquerade') %} +{% set log = base_log ~ '-MASQ]' %} +{% else %} +{% set log = base_log ~ ']' %} +{% endif %} +{% endif %} +{% set output = 'add rule ip6 nat ' ~ chain ~ interface %} +{# Count packets #} +{% set output = output ~ ' counter' %} +{# Special handling of log option, we must repeat the entire rule before the #} +{# NAT translation options are added, this is essential #} +{% if log is vyos_defined %} +{% set log_output = output ~ ' log prefix "' ~ log ~ '" comment "' ~ comment ~ '"' %} +{% endif %} +{% if src_prefix is vyos_defined %} +{% set output = output ~ ' ' ~ src_prefix %} +{% endif %} +{% if dest_address is vyos_defined %} +{% set output = output ~ ' ' ~ dest_address %} +{% endif %} +{% if trns_address is vyos_defined %} +{% set output = output ~ ' ' ~ trns_address %} +{% endif %} +{% if comment is vyos_defined %} +{% set output = output ~ ' comment "' ~ comment ~ '"' %} +{% endif %} +{{ log_output if log_output is vyos_defined }} +{{ output }} +{% endmacro %} + +# Start with clean NAT table +flush table ip6 nat +{% if helper_functions is vyos_defined('remove') %} +{# NAT if going to be disabled - remove rules and targets from nftables #} +{% set base_command = 'delete rule ip6 raw' %} +{{ base_command }} PREROUTING handle {{ pre_ct_conntrack }} +{{ base_command }} OUTPUT handle {{ out_ct_conntrack }} + +delete chain ip6 raw NAT_CONNTRACK + +{% elif helper_functions is vyos_defined('add') %} +{# NAT if enabled - add targets to nftables #} +add chain ip6 raw NAT_CONNTRACK +add rule ip6 raw NAT_CONNTRACK counter accept +{% set base_command = 'add rule ip6 raw' %} +{{ base_command }} PREROUTING position {{ pre_ct_conntrack }} counter jump NAT_CONNTRACK +{{ base_command }} OUTPUT position {{ out_ct_conntrack }} counter jump NAT_CONNTRACK +{% endif %} + +# +# Destination NAT66 rules build up here +# +{% if destination.rule is vyos_defined %} +{% for rule, config in destination.rule.items() if config.disable is not vyos_defined %} +{{ nptv6_rule(rule, config, 'PREROUTING') }} +{% endfor %} +{% endif %} +# +# Source NAT66 rules build up here +# +{% if source.rule is vyos_defined %} +{% for rule, config in source.rule.items() if config.disable is not vyos_defined %} +{{ nptv6_rule(rule, config, 'POSTROUTING') }} +{% endfor %} +{% endif %} diff --git a/data/templates/firewall/nftables-nat66.tmpl b/data/templates/firewall/nftables-nat66.tmpl deleted file mode 100644 index e5c1b1b8d..000000000 --- a/data/templates/firewall/nftables-nat66.tmpl +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/sbin/nft -f - -{% macro nptv6_rule(rule,config, chain) %} -{% set comment = '' %} -{% set base_log = '' %} -{% set src_prefix = "ip6 saddr " + config.source.prefix if config.source is defined and config.source.prefix is defined and config.source.prefix is not none %} -{% set dest_address = "ip6 daddr " + config.destination.address if config.destination is defined and config.destination.address is defined and config.destination.address is not none %} -{% if chain == "PREROUTING" %} -{% set comment = "DST-NAT66-" + rule %} -{% set base_log = '[NAT66-DST-' + rule %} -{% set interface = " iifname \"" + config.inbound_interface + "\"" if config.inbound_interface is defined and config.inbound_interface != 'any' else '' %} -{% if config.translation.address | is_ip_network %} -{# support 1:1 network translation #} -{% set dnat_type = "dnat prefix to " %} -{% else %} -{% set dnat_type = "dnat to " %} -{% endif %} -{% set trns_address = dnat_type + config.translation.address if config.translation is defined and config.translation.address is defined and config.translation.address is not none %} -{% elif chain == "POSTROUTING" %} -{% set comment = 'SRC-NAT66-' + rule %} -{% set base_log = '[NAT66-SRC-' + rule %} -{% if config.translation is defined and config.translation.address is defined and config.translation.address is not none %} -{% if config.translation.address == 'masquerade' %} -{% set trns_address = config.translation.address %} -{% else %} -{% if config.translation.address | is_ip_network %} -{# support 1:1 network translation #} -{% set snat_type = "snat prefix to " %} -{% else %} -{% set snat_type = "snat to " %} -{% endif %} -{% set trns_address = snat_type + config.translation.address %} -{% endif %} -{% endif %} -{% set interface = " oifname \"" + config.outbound_interface + "\"" if config.outbound_interface is defined else '' %} -{% endif %} -{% if config.log is defined %} -{% if config.translation is defined and config.translation.address is defined and config.translation.address == 'masquerade' %} -{% set log = base_log +'-MASQ]' %} -{% else %} -{% set log = base_log + "]" %} -{% endif %} -{% endif %} -{% set output = "add rule ip6 nat " + chain + interface %} -{# Count packets #} -{% set output = output + " counter" %} -{# Special handling of log option, we must repeat the entire rule before the #} -{# NAT translation options are added, this is essential #} -{% if log %} -{% set log_output = output + " log prefix \"" + log + "\" comment \"" + comment + "\"" %} -{% endif %} -{% if src_prefix %} -{% set output = output + " " + src_prefix %} -{% endif %} -{% if dest_address %} -{% set output = output + " " + dest_address %} -{% endif %} -{% if trns_address %} -{% set output = output + " " + trns_address %} -{% endif %} -{% if comment %} -{% set output = output + " comment \"" + comment + "\"" %} -{% endif %} -{{ log_output if log_output }} -{{ output }} -{% endmacro %} - -# Start with clean NAT table -flush table ip6 nat -{% if helper_functions == 'remove' %} -{# NAT if going to be disabled - remove rules and targets from nftables #} -{% set base_command = "delete rule ip6 raw" %} -{{base_command}} PREROUTING handle {{ pre_ct_conntrack }} -{{base_command}} OUTPUT handle {{ out_ct_conntrack }} - -delete chain ip6 raw NAT_CONNTRACK - -{% elif helper_functions == 'add' %} -{# NAT if enabled - add targets to nftables #} -add chain ip6 raw NAT_CONNTRACK -add rule ip6 raw NAT_CONNTRACK counter accept -{% set base_command = "add rule ip6 raw" %} -{{ base_command }} PREROUTING position {{ pre_ct_conntrack }} counter jump NAT_CONNTRACK -{{ base_command }} OUTPUT position {{ out_ct_conntrack }} counter jump NAT_CONNTRACK -{% endif %} - -# -# Destination NAT66 rules build up here -# -{% if destination is defined and destination.rule is defined and destination.rule is not none %} -{% for rule, config in destination.rule.items() if config.disable is not defined %} -{{ nptv6_rule(rule, config, 'PREROUTING') }} -{% endfor %} -{% endif %} -# -# Source NAT66 rules build up here -# -{% if source is defined and source.rule is defined and source.rule is not none %} -{% for rule, config in source.rule.items() if config.disable is not defined %} -{{ nptv6_rule(rule, config, 'POSTROUTING') }} -{% endfor %} -{% endif %} diff --git a/data/templates/firewall/nftables-policy.j2 b/data/templates/firewall/nftables-policy.j2 new file mode 100644 index 000000000..0154c9f7e --- /dev/null +++ b/data/templates/firewall/nftables-policy.j2 @@ -0,0 +1,55 @@ +#!/usr/sbin/nft -f + +{% if cleanup_commands is vyos_defined %} +{% for command in cleanup_commands %} +{{ command }} +{% endfor %} +{% endif %} + +include "/run/nftables_defines.conf" + +table ip mangle { +{% if first_install is vyos_defined %} + chain VYOS_PBR_PREROUTING { + type filter hook prerouting priority -150; policy accept; + } + chain VYOS_PBR_POSTROUTING { + type filter hook postrouting priority -150; policy accept; + } +{% endif %} +{% if route is vyos_defined %} +{% for route_text, conf in route.items() %} + chain VYOS_PBR_{{ route_text }} { +{% if conf.rule is vyos_defined %} +{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %} + {{ rule_conf | nft_rule(route_text, rule_id, 'ip') }} +{% endfor %} +{% endif %} + {{ conf | nft_default_rule(route_text) }} + } +{% endfor %} +{% endif %} +} + +table ip6 mangle { +{% if first_install is vyos_defined %} + chain VYOS_PBR6_PREROUTING { + type filter hook prerouting priority -150; policy accept; + } + chain VYOS_PBR6_POSTROUTING { + type filter hook postrouting priority -150; policy accept; + } +{% endif %} +{% if route6 is vyos_defined %} +{% for route_text, conf in route6.items() %} + chain VYOS_PBR6_{{ route_text }} { +{% if conf.rule is vyos_defined %} +{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %} + {{ rule_conf | nft_rule(route_text, rule_id, 'ip6') }} +{% endfor %} +{% endif %} + {{ conf | nft_default_rule(route_text) }} + } +{% endfor %} +{% endif %} +} diff --git a/data/templates/firewall/nftables-vrf-zones.tmpl b/data/templates/firewall/nftables-vrf-zones.j2 index eecf47b78..eecf47b78 100644 --- a/data/templates/firewall/nftables-vrf-zones.tmpl +++ b/data/templates/firewall/nftables-vrf-zones.j2 diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2 new file mode 100644 index 000000000..fac3fad03 --- /dev/null +++ b/data/templates/firewall/nftables.j2 @@ -0,0 +1,274 @@ +#!/usr/sbin/nft -f + +{% if cleanup_commands is vyos_defined %} +{% for command in cleanup_commands %} +{{ command }} +{% endfor %} +{% endif %} + +include "/run/nftables_defines.conf" + +table ip filter { +{% if first_install is vyos_defined %} + chain VYOS_FW_FORWARD { + type filter hook forward priority 0; policy accept; + jump VYOS_POST_FW + } + chain VYOS_FW_LOCAL { + type filter hook input priority 0; policy accept; + jump VYOS_POST_FW + } + chain VYOS_FW_OUTPUT { + type filter hook output priority 0; policy accept; + jump VYOS_POST_FW + } + chain VYOS_POST_FW { + return + } + chain VYOS_FRAG_MARK { + type filter hook prerouting priority -450; policy accept; + ip frag-off & 0x3fff != 0 meta mark set 0xffff1 return + } +{% endif %} +{% if name is vyos_defined %} +{% set ns = namespace(sets=[]) %} +{% for name_text, conf in name.items() %} + chain NAME_{{ name_text }} { +{% if conf.rule is vyos_defined %} +{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %} + {{ rule_conf | nft_rule(name_text, rule_id) }} +{% if rule_conf.recent is vyos_defined %} +{% set ns.sets = ns.sets + [name_text + '_' + rule_id] %} +{% endif %} +{% endfor %} +{% endif %} + {{ conf | nft_default_rule(name_text) }} + } +{% endfor %} +{% for set_name in ns.sets %} + set RECENT_{{ set_name }} { + type ipv4_addr + size 65535 + flags dynamic + } +{% endfor %} +{% endif %} +{% if state_policy is vyos_defined %} + chain VYOS_STATE_POLICY { +{% if state_policy.established is vyos_defined %} + {{ state_policy.established | nft_state_policy('established') }} +{% endif %} +{% if state_policy.invalid is vyos_defined %} + {{ state_policy.invalid | nft_state_policy('invalid') }} +{% endif %} +{% if state_policy.related is vyos_defined %} + {{ state_policy.related | nft_state_policy('related') }} +{% endif %} + return + } +{% endif %} +} + +table ip6 filter { +{% if first_install is vyos_defined %} + chain VYOS_FW6_FORWARD { + type filter hook forward priority 0; policy accept; + jump VYOS_POST_FW6 + } + chain VYOS_FW6_LOCAL { + type filter hook input priority 0; policy accept; + jump VYOS_POST_FW6 + } + chain VYOS_FW6_OUTPUT { + type filter hook output priority 0; policy accept; + jump VYOS_POST_FW6 + } + chain VYOS_POST_FW6 { + return + } + chain VYOS_FRAG6_MARK { + type filter hook prerouting priority -450; policy accept; + exthdr frag exists meta mark set 0xffff1 return + } +{% endif %} +{% if ipv6_name is vyos_defined %} +{% set ns = namespace(sets=[]) %} +{% for name_text, conf in ipv6_name.items() %} + chain NAME6_{{ name_text }} { +{% if conf.rule is vyos_defined %} +{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %} + {{ rule_conf | nft_rule(name_text, rule_id, 'ip6') }} +{% if rule_conf.recent is vyos_defined %} +{% set ns.sets = ns.sets + [name_text + '_' + rule_id] %} +{% endif %} +{% endfor %} +{% endif %} + {{ conf | nft_default_rule(name_text) }} + } +{% endfor %} +{% for set_name in ns.sets %} + set RECENT6_{{ set_name }} { + type ipv6_addr + size 65535 + flags dynamic + } +{% endfor %} +{% endif %} +{% if state_policy is vyos_defined %} + chain VYOS_STATE_POLICY6 { +{% if state_policy.established is vyos_defined %} + {{ state_policy.established | nft_state_policy('established', ipv6=True) }} +{% endif %} +{% if state_policy.invalid is vyos_defined %} + {{ state_policy.invalid | nft_state_policy('invalid', ipv6=True) }} +{% endif %} +{% if state_policy.related is vyos_defined %} + {{ state_policy.related | nft_state_policy('related', ipv6=True) }} +{% endif %} + return + } +{% endif %} +} + +{% if first_install is vyos_defined %} +table ip nat { + chain PREROUTING { + type nat hook prerouting priority -100; policy accept; + counter jump VYOS_PRE_DNAT_HOOK + } + + chain POSTROUTING { + type nat hook postrouting priority 100; policy accept; + counter jump VYOS_PRE_SNAT_HOOK + } + + chain VYOS_PRE_DNAT_HOOK { + return + } + + chain VYOS_PRE_SNAT_HOOK { + return + } +} + +table ip6 nat { + chain PREROUTING { + type nat hook prerouting priority -100; policy accept; + counter jump VYOS_DNPT_HOOK + } + + chain POSTROUTING { + type nat hook postrouting priority 100; policy accept; + counter jump VYOS_SNPT_HOOK + } + + chain VYOS_DNPT_HOOK { + return + } + + chain VYOS_SNPT_HOOK { + return + } +} + +table inet mangle { + chain FORWARD { + type filter hook forward priority -150; policy accept; + } +} + +table raw { + chain VYOS_TCP_MSS { + type filter hook forward priority -300; policy accept; + } + + chain PREROUTING { + type filter hook prerouting priority -200; policy accept; + counter jump VYOS_CT_IGNORE + counter jump VYOS_CT_TIMEOUT + counter jump VYOS_CT_PREROUTING_HOOK + counter jump FW_CONNTRACK + notrack + } + + chain OUTPUT { + type filter hook output priority -200; policy accept; + counter jump VYOS_CT_IGNORE + counter jump VYOS_CT_TIMEOUT + counter jump VYOS_CT_OUTPUT_HOOK + counter jump FW_CONNTRACK + notrack + } + + ct helper rpc_tcp { + type "rpc" protocol tcp; + } + + ct helper rpc_udp { + type "rpc" protocol udp; + } + + ct helper tns_tcp { + type "tns" protocol tcp; + } + + chain VYOS_CT_HELPER { + ct helper set "rpc_tcp" tcp dport {111} return + ct helper set "rpc_udp" udp dport {111} return + ct helper set "tns_tcp" tcp dport {1521,1525,1536} return + return + } + + chain VYOS_CT_IGNORE { + return + } + + chain VYOS_CT_TIMEOUT { + return + } + + chain VYOS_CT_PREROUTING_HOOK { + return + } + + chain VYOS_CT_OUTPUT_HOOK { + return + } + + chain FW_CONNTRACK { + accept + } +} + +table ip6 raw { + chain VYOS_TCP_MSS { + type filter hook forward priority -300; policy accept; + } + + chain PREROUTING { + type filter hook prerouting priority -300; policy accept; + counter jump VYOS_CT_PREROUTING_HOOK + counter jump FW_CONNTRACK + notrack + } + + chain OUTPUT { + type filter hook output priority -300; policy accept; + counter jump VYOS_CT_OUTPUT_HOOK + counter jump FW_CONNTRACK + notrack + } + + chain VYOS_CT_PREROUTING_HOOK { + return + } + + chain VYOS_CT_OUTPUT_HOOK { + return + } + + chain FW_CONNTRACK { + accept + } +} +{% endif %} diff --git a/data/templates/firewall/upnpd.conf.j2 b/data/templates/firewall/upnpd.conf.j2 new file mode 100644 index 000000000..27573cbf9 --- /dev/null +++ b/data/templates/firewall/upnpd.conf.j2 @@ -0,0 +1,172 @@ +# This is the UPNP configuration file + +# WAN network interface +ext_ifname={{ wan_interface }} +{% if wan_ip is vyos_defined %} +# If the WAN interface has several IP addresses, you +# can specify the one to use below +{% for addr in wan_ip %} +ext_ip={{ addr }} +{% endfor %} +{% endif %} + +# LAN network interfaces IPs / networks +{% if listen is vyos_defined %} +# There can be multiple listening IPs for SSDP traffic, in that case +# use multiple 'listening_ip=...' lines, one for each network interface. +# It can be IP address or network interface name (ie. "eth0") +# It is mandatory to use the network interface name in order to enable IPv6 +# HTTP is available on all interfaces. +# When MULTIPLE_EXTERNAL_IP is enabled, the external IP +# address associated with the subnet follows. For example: +# listening_ip=192.168.0.1/24 88.22.44.13 +{% for addr in listen %} +{% if addr | is_ipv4 %} +listening_ip={{ addr }} +{% elif addr | is_ipv6 %} +ipv6_listening_ip={{ addr }} +{% else %} +listening_ip={{ addr }} +{% endif %} +{% endfor %} +{% endif %} + +# CAUTION: mixing up WAN and LAN interfaces may introduce security risks! +# Be sure to assign the correct interfaces to LAN and WAN and consider +# implementing UPnP permission rules at the bottom of this configuration file + +# Port for HTTP (descriptions and SOAP) traffic. Set to 0 for autoselect. +#http_port=0 +# Port for HTTPS. Set to 0 for autoselect (default) +#https_port=0 + +# Path to the UNIX socket used to communicate with MiniSSDPd +# If running, MiniSSDPd will manage M-SEARCH answering. +# default is /var/run/minissdpd.sock +#minissdpdsocket=/var/run/minissdpd.sock + +{% if nat_pmp is vyos_defined %} +# Enable NAT-PMP support (default is no) +enable_natpmp=yes +{% endif %} + +# Enable UPNP support (default is yes) +enable_upnp=yes + +{% if pcp_lifetime is vyos_defined %} +# PCP +# Configure the minimum and maximum lifetime of a port mapping in seconds +# 120s and 86400s (24h) are suggested values from PCP-base +{% if pcp_lifetime.max is vyos_defined %} +max_lifetime={{ pcp_lifetime.max }} +{% endif %} +{% if pcp_lifetime.min is vyos_defined %} +min_lifetime={{ pcp_lifetime.min }} +{% endif %} +{% endif %} + + +# To enable the next few runtime options, see compile time +# ENABLE_MANUFACTURER_INFO_CONFIGURATION (config.h) + +{% if friendly_name is vyos_defined %} +# Name of this service, default is "`uname -s` router" +friendly_name= {{ friendly_name }} +{% endif %} + +# Manufacturer name, default is "`uname -s`" +manufacturer_name=VyOS + +# Manufacturer URL, default is URL of OS vendor +manufacturer_url=https://vyos.io/ + +# Model name, default is "`uname -s` router" +model_name=VyOS Router Model + +# Model description, default is "`uname -s` router" +model_description=Vyos open source enterprise router/firewall operating system + +# Model URL, default is URL of OS vendor +model_url=https://vyos.io/ + +{% if secure_mode is vyos_defined %} +# Secure Mode, UPnP clients can only add mappings to their own IP +secure_mode=yes +{% else %} +# Secure Mode, UPnP clients can only add mappings to their own IP +secure_mode=no +{% endif %} + +{% if presentation_url is vyos_defined %} +# Default presentation URL is HTTP address on port 80 +# If set to an empty string, no presentationURL element will appear +# in the XML description of the device, which prevents MS Windows +# from displaying an icon in the "Network Connections" panel. +#presentation_url= {{ presentation_url }} +{% endif %} + +# Report system uptime instead of daemon uptime +system_uptime=yes + +# Unused rules cleaning. +# never remove any rule before this threshold for the number +# of redirections is exceeded. default to 20 +clean_ruleset_threshold=10 +# Clean process work interval in seconds. default to 0 (disabled). +# a 600 seconds (10 minutes) interval makes sense +clean_ruleset_interval=600 + +# Anchor name in pf (default is miniupnpd) +anchor=VyOS + +uuid={{ uuid }} + +# Lease file location +lease_file=/config/upnp.leases + +# Daemon's serial and model number when reporting to clients +# (in XML description) +#serial=12345678 +#model_number=1 + +{% if rules is vyos_defined %} +# UPnP permission rules +# (allow|deny) (external port range) IP/mask (internal port range) +# A port range is <min port>-<max port> or <port> if there is only +# one port in the range. +# IP/mask format must be nnn.nnn.nnn.nnn/nn +# It is advised to only allow redirection of port >= 1024 +# and end the rule set with "deny 0-65535 0.0.0.0/0 0-65535" +# The following default ruleset allows specific LAN side IP addresses +# to request only ephemeral ports. It is recommended that users +# modify the IP ranges to match their own internal networks, and +# also consider implementing network-specific restrictions +# CAUTION: failure to enforce any rules may permit insecure requests to be made! +{% for rule, config in rules.items() %} +{% if config.disable is vyos_defined %} +{{ config.action }} {{ config.external_port_range }} {{ config.ip }} {{ config.internal_port_range }} +{% endif %} +{% endfor %} +{% endif %} + +{% if stun is vyos_defined %} +# WAN interface must have public IP address. Otherwise it is behind NAT +# and port forwarding is impossible. In some cases WAN interface can be +# behind unrestricted NAT 1:1 when all incoming traffic is NAT-ed and +# routed to WAN interfaces without any filtering. In this cases miniupnpd +# needs to know public IP address and it can be learnt by asking external +# server via STUN protocol. Following option enable retrieving external +# public IP address from STUN server and detection of NAT type. You need +# to specify also external STUN server in stun_host option below. +# This option is disabled by default. +ext_perform_stun=yes +# Specify STUN server, either hostname or IP address +# Some public STUN servers: +# stun.stunprotocol.org +# stun.sipgate.net +# stun.xten.com +# stun.l.google.com (on non standard port 19302) +ext_stun_host={{ stun.host }} +# Specify STUN UDP port, by default it is standard port 3478. +ext_stun_port={{ stun.port }} +{% endif %} diff --git a/data/templates/frr/bfdd.frr.j2 b/data/templates/frr/bfdd.frr.j2 new file mode 100644 index 000000000..c4adeb402 --- /dev/null +++ b/data/templates/frr/bfdd.frr.j2 @@ -0,0 +1,58 @@ +{% if profile is vyos_defined or peer is vyos_defined %} +bfd +{% if profile is vyos_defined %} +{% for profile_name, profile_config in profile.items() %} + profile {{ profile_name }} + detect-multiplier {{ profile_config.interval.multiplier }} + receive-interval {{ profile_config.interval.receive }} + transmit-interval {{ profile_config.interval.transmit }} +{% if profile_config.interval.echo_interval is vyos_defined %} + echo transmit-interval {{ profile_config.interval.echo_interval }} + echo receive-interval {{ profile_config.interval.echo_interval }} +{% endif %} +{% if profile_config.echo_mode is vyos_defined %} + echo-mode +{% endif %} +{% if profile_config.passive is vyos_defined %} + passive-mode +{% endif %} +{% if profile_config.shutdown is vyos_defined %} + shutdown +{% else %} + no shutdown +{% endif %} + exit + ! +{% endfor %} +{% endif %} +{% if peer is vyos_defined %} +{% for peer_name, peer_config in peer.items() %} + peer {{ peer_name }} {{ 'multihop' if peer_config.multihop is vyos_defined }} {{ 'local-address ' ~ peer_config.source.address if peer_config.source.address is vyos_defined }} {{ 'interface ' ~ peer_config.source.interface if peer_config.source.interface is vyos_defined }} {{ 'vrf ' ~ peer_config.vrf if peer_config.vrf is vyos_defined }} + detect-multiplier {{ peer_config.interval.multiplier }} + receive-interval {{ peer_config.interval.receive }} + transmit-interval {{ peer_config.interval.transmit }} +{% if peer_config.interval.echo_interval is vyos_defined %} + echo transmit-interval {{ peer_config.interval.echo_interval }} + echo receive-interval {{ peer_config.interval.echo_interval }} +{% endif %} +{% if peer_config.echo_mode is vyos_defined %} + echo-mode +{% endif %} +{% if peer_config.passive is vyos_defined %} + passive-mode +{% endif %} +{% if peer_config.profile is vyos_defined %} + profile {{ peer_config.profile }} +{% endif %} +{% if peer_config.shutdown is vyos_defined %} + shutdown +{% else %} + no shutdown +{% endif %} + exit + ! +{% endfor %} +{% endif %} +exit +! +{% endif %} diff --git a/data/templates/frr/bfdd.frr.tmpl b/data/templates/frr/bfdd.frr.tmpl deleted file mode 100644 index 16f8be92c..000000000 --- a/data/templates/frr/bfdd.frr.tmpl +++ /dev/null @@ -1,44 +0,0 @@ -! -bfd -{% if profile is defined and profile is not none %} -{% for profile_name, profile_config in profile.items() %} - profile {{ profile_name }} - detect-multiplier {{ profile_config.interval.multiplier }} - receive-interval {{ profile_config.interval.receive }} - transmit-interval {{ profile_config.interval.transmit }} -{% if profile_config.interval['echo-interval'] is defined and profile_config.interval['echo-interval'] is not none %} - echo-interval {{ profile_config.interval['echo-interval'] }} -{% endif %} -{% if profile_config['echo-mode'] is defined %} - echo-mode -{% endif %} -{% if profile_config.shutdown is defined %} - shutdown -{% else %} - no shutdown -{% endif %} - exit -{% endfor %} -{% endif %} -{% if peer is defined and peer is not none %} -{% for peer_name, peer_config in peer.items() %} - peer {{ peer_name }}{{ ' multihop' if peer_config.multihop is defined }}{{ ' local-address ' + peer_config.source.address if peer_config.source is defined and peer_config.source.address is defined }}{{ ' interface ' + peer_config.source.interface if peer_config.source is defined and peer_config.source.interface is defined }} - detect-multiplier {{ peer_config.interval.multiplier }} - receive-interval {{ peer_config.interval.receive }} - transmit-interval {{ peer_config.interval.transmit }} -{% if peer_config.interval['echo-interval'] is defined and peer_config.interval['echo-interval'] is not none %} - echo-interval {{ peer_config.interval['echo-interval'] }} -{% endif %} -{% if peer_config['echo-mode'] is defined %} - echo-mode -{% endif %} -{% if peer_config.shutdown is defined %} - shutdown -{% else %} - no shutdown -{% endif %} - exit -{% endfor %} -{% endif %} - end -! diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2 new file mode 100644 index 000000000..7029f39af --- /dev/null +++ b/data/templates/frr/bgpd.frr.j2 @@ -0,0 +1,533 @@ +{### MACRO definition for recurring peer patter, this can be either fed by a ###} +{### peer-group or an individual BGP neighbor ###} +{% macro bgp_neighbor(neighbor, config, peer_group=false) %} +{% if peer_group == true %} + neighbor {{ neighbor }} peer-group +{% elif config.peer_group is vyos_defined %} + neighbor {{ neighbor }} peer-group {{ config.peer_group }} +{% endif %} +{% if config.remote_as is vyos_defined %} + neighbor {{ neighbor }} remote-as {{ config.remote_as }} +{% endif %} +{% if config.interface.remote_as is vyos_defined %} + neighbor {{ neighbor }} interface remote-as {{ config.interface.remote_as }} +{% endif %} +{% if config.advertisement_interval is vyos_defined %} + neighbor {{ neighbor }} advertisement-interval {{ config.advertisement_interval }} +{% endif %} +{% if config.bfd is vyos_defined %} + neighbor {{ neighbor }} bfd +{% if config.bfd.check_control_plane_failure is vyos_defined %} + neighbor {{ neighbor }} bfd check-control-plane-failure +{% endif %} +{% if config.bfd.profile is vyos_defined %} + neighbor {{ neighbor }} bfd profile {{ config.bfd.profile }} +{% endif %} +{% endif %} +{% if config.capability is vyos_defined %} +{% if config.capability.dynamic is vyos_defined %} + neighbor {{ neighbor }} capability dynamic +{% endif %} +{% if config.capability.extended_nexthop is vyos_defined %} + neighbor {{ neighbor }} capability extended-nexthop +{% endif %} +{% endif %} +{% if config.description is vyos_defined %} + neighbor {{ neighbor }} description {{ config.description }} +{% endif %} +{% if config.disable_capability_negotiation is vyos_defined %} + neighbor {{ neighbor }} dont-capability-negotiate +{% endif %} +{% if config.ebgp_multihop is vyos_defined %} + neighbor {{ neighbor }} ebgp-multihop {{ config.ebgp_multihop }} +{% endif %} +{% if config.graceful_restart is vyos_defined %} +{% if config.graceful_restart is vyos_defined('enable') %} +{% set graceful_restart = 'graceful-restart' %} +{% elif config.graceful_restart is vyos_defined('disable') %} +{% set graceful_restart = 'graceful-restart-disable' %} +{% elif config.graceful_restart is vyos_defined('restart-helper') %} +{% set graceful_restart = 'graceful-restart-helper' %} +{% endif %} + neighbor {{ neighbor }} {{ graceful_restart }} +{% endif %} +{% if config.local_as is vyos_defined %} +{% for local_as, local_as_config in config.local_as.items() %} +{# There can be only one local-as value, this is checked in the Python code #} + neighbor {{ neighbor }} local-as {{ local_as }} {{ 'no-prepend' if local_as_config.no_prepend is vyos_defined }} {{ 'replace-as' if local_as_config.no_prepend is vyos_defined and local_as_config.no_prepend.replace_as is vyos_defined }} +{% endfor %} +{% endif %} +{% if config.override_capability is vyos_defined %} + neighbor {{ neighbor }} override-capability +{% endif %} +{% if config.passive is vyos_defined %} + neighbor {{ neighbor }} passive +{% endif %} +{% if config.password is vyos_defined %} + neighbor {{ neighbor }} password {{ config.password }} +{% endif %} +{% if config.port is vyos_defined %} + neighbor {{ neighbor }} port {{ config.port }} +{% endif %} +{% if config.shutdown is vyos_defined %} + neighbor {{ neighbor }} shutdown +{% endif %} +{% if config.solo is vyos_defined %} + neighbor {{ neighbor }} solo +{% endif %} +{% if config.strict_capability_match is vyos_defined %} + neighbor {{ neighbor }} strict-capability-match +{% endif %} +{% if config.ttl_security.hops is vyos_defined %} + neighbor {{ neighbor }} ttl-security hops {{ config.ttl_security.hops }} +{% endif %} +{% if config.timers.connect is vyos_defined %} + neighbor {{ neighbor }} timers connect {{ config.timers.connect }} +{% endif %} +{% if config.timers.keepalive is vyos_defined and config.timers.holdtime is vyos_defined %} + neighbor {{ neighbor }} timers {{ config.timers.keepalive }} {{ config.timers.holdtime }} +{% endif %} +{% if config.update_source is vyos_defined %} + neighbor {{ neighbor }} update-source {{ config.update_source }} +{% endif %} +{% if config.interface is vyos_defined %} +{% if config.interface.peer_group is vyos_defined %} + neighbor {{ neighbor }} interface peer-group {{ config.interface.peer_group }} +{% endif %} +{% if config.interface.source_interface is vyos_defined %} + neighbor {{ neighbor }} interface {{ config.interface.source_interface }} +{% endif %} +{% if config.interface.v6only is vyos_defined %} +{% if config.interface.v6only.peer_group is vyos_defined %} + neighbor {{ neighbor }} interface v6only peer-group {{ config.interface.v6only.peer_group }} +{% endif %} +{% if config.interface.v6only.remote_as is vyos_defined %} + neighbor {{ neighbor }} interface v6only remote-as {{ config.interface.v6only.remote_as }} +{% endif %} +{% endif %} +{% endif %} + ! +{% if config.address_family is vyos_defined %} +{% for afi, afi_config in config.address_family.items() %} +{% if afi == 'ipv4_unicast' %} + address-family ipv4 unicast +{% elif afi == 'ipv4_multicast' %} + address-family ipv4 multicast +{% elif afi == 'ipv4_labeled_unicast' %} + address-family ipv4 labeled-unicast +{% elif afi == 'ipv4_vpn' %} + address-family ipv4 vpn +{% elif afi == 'ipv4_flowspec' %} + address-family ipv4 flowspec +{% elif afi == 'ipv6_unicast' %} + address-family ipv6 unicast +{% elif afi == 'ipv6_multicast' %} + address-family ipv6 multicast +{% elif afi == 'ipv6_labeled_unicast' %} + address-family ipv6 labeled-unicast +{% elif afi == 'ipv6_vpn' %} + address-family ipv6 vpn +{% elif afi == 'ipv6_flowspec' %} + address-family ipv6 flowspec +{% elif afi == 'l2vpn_evpn' %} + address-family l2vpn evpn +{% endif %} +{% if afi_config.addpath_tx_all is vyos_defined %} + neighbor {{ neighbor }} addpath-tx-all-paths +{% endif %} +{% if afi_config.addpath_tx_per_as is vyos_defined %} + neighbor {{ neighbor }} addpath-tx-bestpath-per-AS +{% endif %} +{% if afi_config.allowas_in is vyos_defined %} + neighbor {{ neighbor }} allowas-in {{ afi_config.allowas_in.number if afi_config.allowas_in.number is vyos_defined }} +{% endif %} +{% if afi_config.as_override is vyos_defined %} + neighbor {{ neighbor }} as-override +{% endif %} +{% if afi_config.conditionally_advertise is vyos_defined %} +{% if afi_config.conditionally_advertise.advertise_map is vyos_defined %} +{% set exist_non_exist_map = 'exist-map' %} +{% if afi_config.conditionally_advertise.exist_map is vyos_defined %} +{% set exist_non_exist_map = 'exist-map ' ~ afi_config.conditionally_advertise.exist_map %} +{% elif afi_config.conditionally_advertise.non_exist_map is vyos_defined %} +{% set exist_non_exist_map = 'non-exist-map ' ~ afi_config.conditionally_advertise.non_exist_map %} +{% endif %} + neighbor {{ neighbor }} advertise-map {{ afi_config.conditionally_advertise.advertise_map }} {{ exist_non_exist_map }} +{% endif %} +{% endif %} +{% if afi_config.remove_private_as is vyos_defined %} + neighbor {{ neighbor }} remove-private-AS +{% endif %} +{% if afi_config.route_reflector_client is vyos_defined %} + neighbor {{ neighbor }} route-reflector-client +{% endif %} +{% if afi_config.weight is vyos_defined %} + neighbor {{ neighbor }} weight {{ afi_config.weight }} +{% endif %} +{% if afi_config.attribute_unchanged is vyos_defined %} + neighbor {{ neighbor }} attribute-unchanged {{ 'as-path ' if afi_config.attribute_unchanged.as_path is vyos_defined }}{{ 'med ' if afi_config.attribute_unchanged.med is vyos_defined }}{{ 'next-hop ' if afi_config.attribute_unchanged.next_hop is vyos_defined }} +{% endif %} +{% if afi_config.capability.orf.prefix_list.send is vyos_defined %} + neighbor {{ neighbor }} capability orf prefix-list send +{% endif %} +{% if afi_config.capability.orf.prefix_list.receive is vyos_defined %} + neighbor {{ neighbor }} capability orf prefix-list receive +{% endif %} +{% if afi_config.default_originate is vyos_defined %} + neighbor {{ neighbor }} default-originate {{ 'route-map ' ~ afi_config.default_originate.route_map if afi_config.default_originate.route_map is vyos_defined }} +{% endif %} +{% if afi_config.distribute_list.export is vyos_defined %} + neighbor {{ neighbor }} distribute-list {{ afi_config.distribute_list.export }} out +{% endif %} +{% if afi_config.distribute_list.import is vyos_defined %} + neighbor {{ neighbor }} distribute-list {{ afi_config.distribute_list.import }} in +{% endif %} +{% if afi_config.filter_list.export is vyos_defined %} + neighbor {{ neighbor }} filter-list {{ afi_config.filter_list.export }} out +{% endif %} +{% if afi_config.filter_list.import is vyos_defined %} + neighbor {{ neighbor }} filter-list {{ afi_config.filter_list.import }} in +{% endif %} +{% if afi_config.maximum_prefix is vyos_defined %} + neighbor {{ neighbor }} maximum-prefix {{ afi_config.maximum_prefix }} +{% endif %} +{% if afi_config.maximum_prefix_out is vyos_defined %} + neighbor {{ neighbor }} maximum-prefix-out {{ afi_config.maximum_prefix_out }} +{% endif %} +{% if afi_config.nexthop_self is vyos_defined %} + neighbor {{ neighbor }} next-hop-self {{ 'force' if afi_config.nexthop_self.force is vyos_defined }} +{% endif %} +{% if afi_config.route_server_client is vyos_defined %} + neighbor {{ neighbor }} route-server-client +{% endif %} +{% if afi_config.route_map.export is vyos_defined %} + neighbor {{ neighbor }} route-map {{ afi_config.route_map.export }} out +{% endif %} +{% if afi_config.route_map.import is vyos_defined %} + neighbor {{ neighbor }} route-map {{ afi_config.route_map.import }} in +{% endif %} +{% if afi_config.prefix_list.export is vyos_defined %} + neighbor {{ neighbor }} prefix-list {{ afi_config.prefix_list.export }} out +{% endif %} +{% if afi_config.prefix_list.import is vyos_defined %} + neighbor {{ neighbor }} prefix-list {{ afi_config.prefix_list.import }} in +{% endif %} +{% if afi_config.soft_reconfiguration.inbound is vyos_defined %} + neighbor {{ neighbor }} soft-reconfiguration inbound +{% endif %} +{% if afi_config.unsuppress_map is vyos_defined %} + neighbor {{ neighbor }} unsuppress-map {{ afi_config.unsuppress_map }} +{% endif %} +{% if afi_config.disable_send_community.extended is vyos_defined %} + no neighbor {{ neighbor }} send-community extended +{% endif %} +{% if afi_config.disable_send_community.standard is vyos_defined %} + no neighbor {{ neighbor }} send-community standard +{% endif %} + neighbor {{ neighbor }} activate + exit-address-family + ! +{% endfor %} +{% endif %} +{% endmacro %} +! +router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }} +{% if parameters.ebgp_requires_policy is vyos_defined %} + bgp ebgp-requires-policy +{% else %} + no bgp ebgp-requires-policy +{% endif %} +{# Option must be set before any neighbor - see https://phabricator.vyos.net/T3463 #} + no bgp default ipv4-unicast +{# Workaround for T2100 until we have decided about a migration script #} + no bgp network import-check +{% if address_family is vyos_defined %} +{% for afi, afi_config in address_family.items() %} + ! +{% if afi == 'ipv4_unicast' %} + address-family ipv4 unicast +{% elif afi == 'ipv4_multicast' %} + address-family ipv4 multicast +{% elif afi == 'ipv4_labeled_unicast' %} + address-family ipv4 labeled-unicast +{% elif afi == 'ipv4_vpn' %} + address-family ipv4 vpn +{% elif afi == 'ipv4_flowspec' %} + address-family ipv4 flowspec +{% elif afi == 'ipv6_unicast' %} + address-family ipv6 unicast +{% elif afi == 'ipv6_multicast' %} + address-family ipv6 multicast +{% elif afi == 'ipv6_labeled_unicast' %} + address-family ipv6 labeled-unicast +{% elif afi == 'ipv6_vpn' %} + address-family ipv6 vpn +{% elif afi == 'ipv6_flowspec' %} + address-family ipv6 flowspec +{% elif afi == 'l2vpn_evpn' %} + address-family l2vpn evpn +{% if afi_config.rd is vyos_defined %} + rd {{ afi_config.rd }} +{% endif %} +{% endif %} +{% if afi_config.aggregate_address is vyos_defined %} +{% for aggregate, aggregate_config in afi_config.aggregate_address.items() %} + aggregate-address {{ aggregate }}{{ ' as-set' if aggregate_config.as_set is vyos_defined }}{{ ' summary-only' if aggregate_config.summary_only is vyos_defined }} +{% if aggregate_config.route_map is vyos_defined %} + aggregate-address {{ aggregate }} route-map {{ aggregate_config.route_map }} +{% endif %} +{% endfor %} +{% endif %} +{% if afi_config.maximum_paths.ebgp is vyos_defined %} + maximum-paths {{ afi_config.maximum_paths.ebgp }} +{% endif %} +{% if afi_config.maximum_paths.ibgp is vyos_defined %} + maximum-paths ibgp {{ afi_config.maximum_paths.ibgp }} +{% endif %} +{% if afi_config.redistribute is vyos_defined %} +{% for protocol, protocol_config in afi_config.redistribute.items() %} +{% if protocol == 'table' %} + redistribute table {{ protocol_config.table }} +{% else %} +{% set redistribution_protocol = protocol %} +{% if protocol == 'ospfv3' %} +{% set redistribution_protocol = 'ospf6' %} +{% endif %} + redistribute {{ redistribution_protocol }} {{ 'metric ' ~ protocol_config.metric if protocol_config.metric is vyos_defined }} {{ 'route-map ' ~ protocol_config.route_map if protocol_config.route_map is vyos_defined }} + {####### we need this blank line!! #######} + +{% endif %} +{% endfor %} +{% endif %} +{% if afi_config.network is vyos_defined %} +{% for network, network_config in afi_config.network.items() %} + network {{ network }} {{ 'route-map ' ~ network_config.route_map if network_config.route_map is vyos_defined }} {{ 'backdoor' if network_config.backdoor is vyos_defined }} {{ 'rd ' ~ network_config.rd if network_config.rd is vyos_defined }} {{ 'label ' ~ network_config.label if network_config.label is vyos_defined }} +{####### we need this blank line!! #######} + +{% endfor %} +{% endif %} +{% if afi_config.advertise is vyos_defined %} +{% for adv_afi, adv_afi_config in afi_config.advertise.items() %} +{% if adv_afi_config.unicast is vyos_defined %} + advertise {{ adv_afi }} unicast {{ 'route-map ' ~ adv_afi_config.unicast.route_map if adv_afi_config.unicast.route_map is vyos_defined }} +{% endif %} +{% endfor %} +{% endif %} +{% if afi_config.distance.external is vyos_defined and afi_config.distance.internal is vyos_defined and afi_config.distance.local is vyos_defined %} + distance bgp {{ afi_config.distance.external }} {{ afi_config.distance.internal }} {{ afi_config.distance.local }} +{% endif %} +{% if afi_config.distance.prefix is vyos_defined %} +{% for prefix in afi_config.distance.prefix %} + distance {{ afi_config.distance.prefix[prefix].distance }} {{ prefix }} +{% endfor %} +{% endif %} +{% if afi_config.export.vpn is vyos_defined %} + export vpn +{% endif %} +{% if afi_config.import.vpn is vyos_defined %} + import vpn +{% endif %} +{% if afi_config.import.vrf is vyos_defined %} +{% for vrf in afi_config.import.vrf %} + import vrf {{ vrf }} +{% endfor %} +{% endif %} +{% if afi_config.label.vpn.export is vyos_defined %} + label vpn export {{ afi_config.label.vpn.export }} +{% endif %} +{% if afi_config.local_install is vyos_defined %} +{% for interface in afi_config.local_install.interface %} + local-install {{ interface }} +{% endfor %} +{% endif %} +{% if afi_config.advertise_all_vni is vyos_defined %} + advertise-all-vni +{% endif %} +{% if afi_config.advertise_default_gw is vyos_defined %} + advertise-default-gw +{% endif %} +{% if afi_config.advertise_pip is vyos_defined %} + advertise-pip ip {{ afi_config.advertise_pip }} +{% endif %} +{% if afi_config.advertise_svi_ip is vyos_defined %} + advertise-svi-ip +{% endif %} +{% if afi_config.rt_auto_derive is vyos_defined %} + autort rfc8365-compatible +{% endif %} +{% if afi_config.flooding.disable is vyos_defined %} + flooding disable +{% endif %} +{% if afi_config.flooding.head_end_replication is vyos_defined %} + flooding head-end-replication +{% endif %} +{% if afi_config.rd.vpn.export is vyos_defined %} + rd vpn export {{ afi_config.rd.vpn.export }} +{% endif %} +{% if afi_config.route_target.vpn.both is vyos_defined %} + route-target vpn both {{ afi_config.route_target.vpn.both }} +{% else %} +{% if afi_config.route_target.vpn.export is vyos_defined %} + route-target vpn export {{ afi_config.route_target.vpn.export }} +{% endif %} +{% if afi_config.route_target.vpn.import is vyos_defined %} + route-target vpn import {{ afi_config.route_target.vpn.import }} +{% endif %} +{% endif %} +{% if afi_config.route_target.both is vyos_defined %} + route-target both {{ afi_config.route_target.both }} +{% else %} +{% if afi_config.route_target.export is vyos_defined %} + route-target export {{ afi_config.route_target.export }} +{% endif %} +{% if afi_config.route_target.import is vyos_defined %} + route-target import {{ afi_config.route_target.import }} +{% endif %} +{% endif %} +{% if afi_config.route_map.vpn.export is vyos_defined %} + route-map vpn export {{ afi_config.route_map.vpn.export }} +{% endif %} +{% if afi_config.route_map.vpn.import is vyos_defined %} + route-map vpn import {{ afi_config.route_map.vpn.import }} +{% endif %} +{% if afi_config.vni is vyos_defined %} +{% for vni, vni_config in afi_config.vni.items() %} + vni {{ vni }} +{% if vni_config.advertise_default_gw is vyos_defined %} + advertise-default-gw +{% endif %} +{% if vni_config.advertise_svi_ip is vyos_defined %} + advertise-svi-ip +{% endif %} +{% if vni_config.rd is vyos_defined %} + rd {{ vni_config.rd }} +{% endif %} +{% if vni_config.route_target.both is vyos_defined %} + route-target both {{ vni_config.route_target.both }} +{% endif %} +{% if vni_config.route_target.export is vyos_defined %} + route-target export {{ vni_config.route_target.export }} +{% endif %} +{% if vni_config.route_target.import is vyos_defined %} + route-target import {{ vni_config.route_target.import }} +{% endif %} + exit-vni +{% endfor %} +{% endif %} + exit-address-family +{% endfor %} +{% endif %} + ! +{% if peer_group is vyos_defined %} +{% for peer, config in peer_group.items() %} +{{ bgp_neighbor(peer, config, true) }} +{% endfor %} +{% endif %} + ! +{% if neighbor is vyos_defined %} +{% for peer, config in neighbor.items() %} +{{ bgp_neighbor(peer, config) }} +{% endfor %} +{% endif %} + ! +{% if listen.limit is vyos_defined %} + bgp listen limit {{ listen.limit }} +{% endif %} +{% if listen.range is vyos_defined %} +{% for prefix, options in listen.range.items() %} +{% if options.peer_group is vyos_defined %} + bgp listen range {{ prefix }} peer-group {{ options.peer_group }} +{% endif %} +{% endfor %} +{% endif %} +{% if parameters.always_compare_med is vyos_defined %} + bgp always-compare-med +{% endif %} +{% if parameters.bestpath.as_path is vyos_defined %} +{% for option in parameters.bestpath.as_path %} +{# replace is required for multipath-relax option #} + bgp bestpath as-path {{ option | replace('_', '-') }} +{% endfor %} +{% endif %} +{% if parameters.bestpath.bandwidth is vyos_defined %} + bgp bestpath bandwidth {{ parameters.bestpath.bandwidth }} +{% endif %} +{% if parameters.bestpath.compare_routerid is vyos_defined %} + bgp bestpath compare-routerid +{% endif %} +{% if parameters.bestpath.med is vyos_defined %} + bgp bestpath med {{ 'confed' if parameters.bestpath.med.confed is vyos_defined }} {{ 'missing-as-worst' if parameters.bestpath.med.missing_as_worst is vyos_defined }} +{% endif %} +{% if parameters.cluster_id is vyos_defined %} + bgp cluster-id {{ parameters.cluster_id }} +{% endif %} +{% if parameters.conditional_advertisement.timer is vyos_defined %} + bgp conditional-advertisement timer {{ parameters.conditional_advertisement.timer }} +{% endif %} +{% if parameters.confederation.identifier is vyos_defined %} + bgp confederation identifier {{ parameters.confederation.identifier }} +{% endif %} +{% if parameters.confederation.peers is vyos_defined %} + bgp confederation peers {{ parameters.confederation.peers | join(' ') }} +{% endif %} +{% if parameters.dampening.half_life is vyos_defined %} +{# Doesn't work in current FRR configuration; vtysh (bgp dampening 16 751 2001 61) #} + bgp dampening {{ parameters.dampening.half_life }} {{ parameters.dampening.re_use if parameters.dampening.re_use is vyos_defined }} {{ parameters.dampening.start_suppress_time if parameters.dampening.start_suppress_time is vyos_defined }} {{ parameters.dampening.max_suppress_time if parameters.dampening.max_suppress_time is vyos_defined }} +{% endif %} +{% if parameters.default.local_pref is vyos_defined %} + bgp default local-preference {{ parameters.default.local_pref }} +{% endif %} +{% if parameters.deterministic_med is vyos_defined %} + bgp deterministic-med +{% endif %} +{% if parameters.distance.global.external is vyos_defined and parameters.distance.global.internal is vyos_defined and parameters.distance.global.local is vyos_defined %} + distance bgp {{ parameters.distance.global.external }} {{ parameters.distance.global.internal }} {{ parameters.distance.global.local }} +{% endif %} +{% if parameters.distance.prefix is vyos_defined %} +{% for prefix in parameters.distance.prefix %} + distance {{ parameters.distance.prefix[prefix].distance }} {{ prefix }} +{% endfor %} +{% endif %} +{% if parameters.fast_convergence is vyos_defined %} + bgp fast-convergence +{% endif %} +{% if parameters.graceful_restart is vyos_defined %} + bgp graceful-restart {{ 'stalepath-time ' ~ parameters.graceful_restart.stalepath_time if parameters.graceful_restart.stalepath_time is vyos_defined }} +{% endif %} +{% if parameters.graceful_shutdown is vyos_defined %} + bgp graceful-shutdown +{% endif %} +{% if parameters.log_neighbor_changes is vyos_defined %} + bgp log-neighbor-changes +{% endif %} +{% if parameters.minimum_holdtime is vyos_defined %} + bgp minimum-holdtime {{ parameters.minimum_holdtime }} +{% endif %} +{% if parameters.network_import_check is vyos_defined %} + bgp network import-check +{% endif %} +{% if parameters.no_client_to_client_reflection is vyos_defined %} + no bgp client-to-client reflection +{% endif %} +{% if parameters.no_fast_external_failover is vyos_defined %} + no bgp fast-external-failover +{% endif %} +{% if parameters.no_suppress_duplicates is vyos_defined %} + no bgp suppress-duplicates +{% endif %} +{% if parameters.reject_as_sets is vyos_defined %} + bgp reject-as-sets +{% endif %} +{% if parameters.router_id is vyos_defined and parameters.router_id is not none %} + bgp router-id {{ parameters.router_id }} +{% endif %} +{% if parameters.shutdown is vyos_defined %} + bgp shutdown +{% endif %} +{% if parameters.suppress_fib_pending is vyos_defined %} + bgp suppress-fib-pending +{% endif %} +{% if timers.keepalive is vyos_defined and timers.holdtime is vyos_defined %} + timers bgp {{ timers.keepalive }} {{ timers.holdtime }} +{% endif %} +exit diff --git a/data/templates/frr/bgpd.frr.tmpl b/data/templates/frr/bgpd.frr.tmpl deleted file mode 100644 index 61936bb56..000000000 --- a/data/templates/frr/bgpd.frr.tmpl +++ /dev/null @@ -1,528 +0,0 @@ -{### MACRO definition for recurring peer patter, this can be either fed by a ###} -{### peer-group or an individual BGP neighbor ###} -{% macro bgp_neighbor(neighbor, config, peer_group=false) %} -{% if peer_group == true %} - neighbor {{ neighbor }} peer-group -{% elif config.peer_group is defined and config.peer_group is not none %} - neighbor {{ neighbor }} peer-group {{ config.peer_group }} -{% endif %} -{% if config.remote_as is defined and config.remote_as is not none %} - neighbor {{ neighbor }} remote-as {{ config.remote_as }} -{% endif %} -{% if config.interface is defined and config.interface.remote_as is defined and config.interface.remote_as is not none %} - neighbor {{ neighbor }} interface remote-as {{ config.interface.remote_as }} -{% endif %} -{% if config.advertisement_interval is defined and config.advertisement_interval is not none %} - neighbor {{ neighbor }} advertisement-interval {{ config.advertisement_interval }} -{% endif %} -{% if config.bfd is defined %} - neighbor {{ neighbor }} bfd -{% endif %} -{% if config.capability is defined and config.capability is not none %} -{% if config.capability.dynamic is defined %} - neighbor {{ neighbor }} capability dynamic -{% endif %} -{% if config.capability.extended_nexthop is defined %} - neighbor {{ neighbor }} capability extended-nexthop -{% endif %} -{% endif %} -{% if config.description is defined and config.description is not none %} - neighbor {{ neighbor }} description {{ config.description }} -{% endif %} -{% if config.disable_capability_negotiation is defined %} - neighbor {{ neighbor }} dont-capability-negotiate -{% endif %} -{% if config.ebgp_multihop is defined and config.ebgp_multihop is not none %} - neighbor {{ neighbor }} ebgp-multihop {{ config.ebgp_multihop }} -{% endif %} -{% if config.graceful_restart is defined and config.graceful_restart is not none %} -{% if config.graceful_restart == 'enable' %} -{% set graceful_restart = 'graceful-restart' %} -{% elif config.graceful_restart == 'disable' %} -{% set graceful_restart = 'graceful-restart-disable' %} -{% elif config.graceful_restart == 'restart-helper' %} -{% set graceful_restart = 'graceful-restart-helper' %} -{% endif %} - neighbor {{ neighbor }} {{ graceful_restart }} -{% endif %} -{% if config.local_as is defined and config.local_as is not none %} -{% for local_as, local_as_config in config.local_as.items() %} -{# There can be only one local-as value, this is checked in the Python code #} - neighbor {{ neighbor }} local-as {{ local_as }} {{ 'no-prepend' if local_as_config.no_prepend is defined }} {{ 'replace-as' if local_as_config.no_prepend is defined and local_as_config.no_prepend.replace_as is defined }} -{% endfor %} -{% endif %} -{% if config.override_capability is defined %} - neighbor {{ neighbor }} override-capability -{% endif %} -{% if config.passive is defined %} - neighbor {{ neighbor }} passive -{% endif %} -{% if config.password is defined and config.password is not none %} - neighbor {{ neighbor }} password {{ config.password }} -{% endif %} -{% if config.port is defined and config.port is not none %} - neighbor {{ neighbor }} port {{ config.port }} -{% endif %} -{% if config.shutdown is defined %} - neighbor {{ neighbor }} shutdown -{% endif %} -{% if config.solo is defined %} - neighbor {{ neighbor }} solo -{% endif %} -{% if config.strict_capability_match is defined %} - neighbor {{ neighbor }} strict-capability-match -{% endif %} -{% if config.ttl_security is defined and config.ttl_security.hops is defined and config.ttl_security.hops is not none %} - neighbor {{ neighbor }} ttl-security hops {{ config.ttl_security.hops }} -{% endif %} -{% if config.timers is defined %} -{% if config.timers.connect is defined and config.timers.connect is not none %} - neighbor {{ neighbor }} timers connect {{ config.timers.connect }} -{% endif %} -{% if config.timers.holdtime is defined and config.timers.keepalive is defined and config.timers.holdtime is not none and config.timers.keepalive is not none %} - neighbor {{ neighbor }} timers {{ config.timers.keepalive }} {{ config.timers.holdtime }} -{% endif %} -{% endif %} -{% if config.update_source is defined and config.update_source is not none %} - neighbor {{ neighbor }} update-source {{ config.update_source }} -{% endif %} -{% if config.interface is defined and config.interface is not none %} -{% if config.interface.peer_group is defined and config.interface.peer_group is not none %} - neighbor {{ neighbor }} interface peer-group {{ config.interface.peer_group }} -{% endif %} -{% if config.interface.source_interface is defined and config.interface.source_interface is not none %} - neighbor {{ neighbor }} interface {{ config.interface.source_interface }} -{% endif %} -{% if config.interface.v6only is defined and config.interface.v6only is not none %} -{% if config.interface.v6only.peer_group is defined and config.interface.v6only.peer_group is not none %} - neighbor {{ neighbor }} interface v6only peer-group {{ config.interface.v6only.peer_group }} -{% endif %} -{% if config.interface.v6only.remote_as is defined and config.interface.v6only.remote_as is not none %} - neighbor {{ neighbor }} interface v6only remote-as {{ config.interface.v6only.remote_as }} -{% endif %} -{% endif %} -{% endif %} - ! -{% if config.address_family is defined and config.address_family is not none %} -{% for afi, afi_config in config.address_family.items() %} -{% if afi == 'ipv4_unicast' %} - address-family ipv4 unicast -{% elif afi == 'ipv4_multicast' %} - address-family ipv4 multicast -{% elif afi == 'ipv4_labeled_unicast' %} - address-family ipv4 labeled-unicast -{% elif afi == 'ipv4_vpn' %} - address-family ipv4 vpn -{% elif afi == 'ipv4_flowspec' %} - address-family ipv4 flowspec -{% elif afi == 'ipv6_unicast' %} - address-family ipv6 unicast -{% elif afi == 'ipv6_multicast' %} - address-family ipv6 multicast -{% elif afi == 'ipv6_labeled_unicast' %} - address-family ipv6 labeled-unicast -{% elif afi == 'ipv6_vpn' %} - address-family ipv6 vpn -{% elif afi == 'ipv6_flowspec' %} - address-family ipv6 flowspec -{% elif afi == 'l2vpn_evpn' %} - address-family l2vpn evpn -{% endif %} -{% if afi_config.addpath_tx_all is defined %} - neighbor {{ neighbor }} addpath-tx-all-paths -{% endif %} -{% if afi_config.addpath_tx_per_as is defined %} - neighbor {{ neighbor }} addpath-tx-bestpath-per-AS -{% endif %} -{% if afi_config.allowas_in is defined and afi_config.allowas_in is not none %} - neighbor {{ neighbor }} allowas-in {{ afi_config.allowas_in.number if afi_config.allowas_in.number is defined }} -{% endif %} -{% if afi_config.as_override is defined %} - neighbor {{ neighbor }} as-override -{% endif %} -{% if afi_config.remove_private_as is defined %} - neighbor {{ neighbor }} remove-private-AS -{% endif %} -{% if afi_config.route_reflector_client is defined %} - neighbor {{ neighbor }} route-reflector-client -{% endif %} -{% if afi_config.weight is defined and afi_config.weight is not none %} - neighbor {{ neighbor }} weight {{ afi_config.weight }} -{% endif %} -{% if afi_config.attribute_unchanged is defined and afi_config.attribute_unchanged is not none %} - neighbor {{ neighbor }} attribute-unchanged {{ 'as-path ' if afi_config.attribute_unchanged.as_path is defined }}{{ 'med ' if afi_config.attribute_unchanged.med is defined }}{{ 'next-hop ' if afi_config.attribute_unchanged.next_hop is defined }} -{% endif %} -{% if afi_config.capability is defined and afi_config.capability.orf is defined and afi_config.capability.orf.prefix_list is defined and afi_config.capability.orf.prefix_list.send is defined %} - neighbor {{ neighbor }} capability orf prefix-list send -{% endif %} -{% if afi_config.capability is defined and afi_config.capability.orf is defined and afi_config.capability.orf.prefix_list is defined and afi_config.capability.orf.prefix_list.receive is defined %} - neighbor {{ neighbor }} capability orf prefix-list receive -{% endif %} -{% if afi_config.default_originate is defined %} - neighbor {{ neighbor }} default-originate {{ 'route-map ' ~ afi_config.default_originate.route_map if afi_config.default_originate.route_map is defined }} -{% endif %} -{% if afi_config.distribute_list is defined and afi_config.distribute_list is not none %} -{% if afi_config.distribute_list.export is defined and afi_config.distribute_list.export is not none %} - neighbor {{ neighbor }} distribute-list {{ afi_config.distribute_list.export }} out -{% endif %} -{% if afi_config.distribute_list.import is defined and afi_config.distribute_list.import is not none %} - neighbor {{ neighbor }} distribute-list {{ afi_config.distribute_list.import }} in -{% endif %} -{% endif %} -{% if afi_config.filter_list is defined and afi_config.filter_list is not none %} -{% if afi_config.filter_list.export is defined and afi_config.filter_list.export is not none %} - neighbor {{ neighbor }} filter-list {{ afi_config.filter_list.export }} out -{% endif %} -{% if afi_config.filter_list.import is defined and afi_config.filter_list.import is not none %} - neighbor {{ neighbor }} filter-list {{ afi_config.filter_list.import }} in -{% endif %} -{% endif %} -{% if afi_config.maximum_prefix is defined and afi_config.maximum_prefix is not none %} - neighbor {{ neighbor }} maximum-prefix {{ afi_config.maximum_prefix }} -{% endif %} -{% if afi_config.maximum_prefix_out is defined and afi_config.maximum_prefix_out is not none %} - neighbor {{ neighbor }} maximum-prefix-out {{ afi_config.maximum_prefix_out }} -{% endif %} -{% if afi_config.nexthop_self is defined %} - neighbor {{ neighbor }} next-hop-self {{ 'force' if afi_config.nexthop_self.force is defined }} -{% endif %} -{% if afi_config.route_server_client is defined %} - neighbor {{ neighbor }} route-server-client -{% endif %} -{% if afi_config.route_map is defined and afi_config.route_map is not none %} -{% if afi_config.route_map.export is defined and afi_config.route_map.export is not none %} - neighbor {{ neighbor }} route-map {{ afi_config.route_map.export }} out -{% endif %} -{% if afi_config.route_map.import is defined and afi_config.route_map.import is not none %} - neighbor {{ neighbor }} route-map {{ afi_config.route_map.import }} in -{% endif %} -{% endif %} -{% if afi_config.prefix_list is defined and afi_config.prefix_list is not none %} -{% if afi_config.prefix_list.export is defined and afi_config.prefix_list.export is not none %} - neighbor {{ neighbor }} prefix-list {{ afi_config.prefix_list.export }} out -{% endif %} -{% if afi_config.prefix_list.import is defined and afi_config.prefix_list.import is not none %} - neighbor {{ neighbor }} prefix-list {{ afi_config.prefix_list.import }} in -{% endif %} -{% endif %} -{% if afi_config.soft_reconfiguration is defined and afi_config.soft_reconfiguration.inbound is defined %} - neighbor {{ neighbor }} soft-reconfiguration inbound -{% endif %} -{% if afi_config.unsuppress_map is defined and afi_config.unsuppress_map is not none %} - neighbor {{ neighbor }} unsuppress-map {{ afi_config.unsuppress_map }} -{% endif %} -{% if afi_config.disable_send_community is defined and afi_config.disable_send_community.extended is defined %} - no neighbor {{ neighbor }} send-community extended -{% endif %} -{% if afi_config.disable_send_community is defined and afi_config.disable_send_community.standard is defined %} - no neighbor {{ neighbor }} send-community standard -{% endif %} - neighbor {{ neighbor }} activate - exit-address-family - ! -{% endfor %} -{% endif %} -{% endmacro %} -! -router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is defined and vrf is not none }} -{% if parameters is defined and parameters.ebgp_requires_policy is defined %} - bgp ebgp-requires-policy -{% else %} - no bgp ebgp-requires-policy -{% endif %} -{# Option must be set before any neighbor - see https://phabricator.vyos.net/T3463 #} - no bgp default ipv4-unicast -{# Workaround for T2100 until we have decided about a migration script #} - no bgp network import-check -{% if address_family is defined and address_family is not none %} -{% for afi, afi_config in address_family.items() %} - ! -{% if afi == 'ipv4_unicast' %} - address-family ipv4 unicast -{% elif afi == 'ipv4_multicast' %} - address-family ipv4 multicast -{% elif afi == 'ipv4_labeled_unicast' %} - address-family ipv4 labeled-unicast -{% elif afi == 'ipv4_vpn' %} - address-family ipv4 vpn -{% elif afi == 'ipv4_flowspec' %} - address-family ipv4 flowspec -{% elif afi == 'ipv6_unicast' %} - address-family ipv6 unicast -{% elif afi == 'ipv6_multicast' %} - address-family ipv6 multicast -{% elif afi == 'ipv6_labeled_unicast' %} - address-family ipv6 labeled-unicast -{% elif afi == 'ipv6_vpn' %} - address-family ipv6 vpn -{% elif afi == 'ipv6_flowspec' %} - address-family ipv6 flowspec -{% elif afi == 'l2vpn_evpn' %} - address-family l2vpn evpn -{% if afi_config.rd is defined and afi_config.rd is not none %} - rd {{ afi_config.rd }} -{% endif %} -{% endif %} -{% if afi_config.aggregate_address is defined and afi_config.aggregate_address is not none %} -{% for aggregate, aggregate_config in afi_config.aggregate_address.items() %} - aggregate-address {{ aggregate }}{{ ' as-set' if aggregate_config.as_set is defined }}{{ ' summary-only' if aggregate_config.summary_only is defined }} -{% if aggregate_config.route_map is defined and aggregate_config.route_map is not none %} - aggregate-address {{ aggregate }} route-map {{ aggregate_config.route_map }} -{% endif %} -{% endfor %} -{% endif %} -{% if afi_config.maximum_paths is defined and afi_config.maximum_paths.ebgp is defined and afi_config.maximum_paths.ebgp is not none %} - maximum-paths {{ afi_config.maximum_paths.ebgp }} -{% endif %} -{% if afi_config.maximum_paths is defined and afi_config.maximum_paths.ibgp is defined and afi_config.maximum_paths.ibgp is not none %} - maximum-paths ibgp {{ afi_config.maximum_paths.ibgp }} -{% endif %} -{% if afi_config.redistribute is defined and afi_config.redistribute is not none %} -{% for protocol in afi_config.redistribute %} -{% if protocol == 'table' %} - redistribute table {{ afi_config.redistribute[protocol].table }} -{% else %} -{% set redistribution_protocol = protocol %} -{% if protocol == 'ospfv3' %} -{% set redistribution_protocol = 'ospf6' %} -{% endif %} - redistribute {{ redistribution_protocol }}{% if afi_config.redistribute[protocol].metric is defined %} metric {{ afi_config.redistribute[protocol].metric }}{% endif %}{% if afi_config.redistribute[protocol].route_map is defined %} route-map {{ afi_config.redistribute[protocol].route_map }}{% endif %} -{####### we need this blank line!! #######} - -{% endif %} -{% endfor %} -{% endif %} -{% if afi_config.network is defined and afi_config.network is not none %} -{% for network in afi_config.network %} - network {{ network }}{% if afi_config.network[network].route_map is defined %} route-map {{ afi_config.network[network].route_map }}{% endif %}{% if afi_config.network[network].backdoor is defined %} backdoor{% endif %}{% if afi_config.network[network].rd is defined and afi_config.network[network].label is defined%} rd {{ afi_config.network[network].rd }} label {{ afi_config.network[network].label }}{% endif %} -{####### we need this blank line!! #######} - -{% endfor %} -{% endif %} -{% if afi_config.advertise is defined and afi_config.advertise is not none %} -{% for adv_afi, adv_afi_config in afi_config.advertise.items() %} -{% if adv_afi_config.unicast is defined and adv_afi_config.unicast is not none %} - advertise {{ adv_afi }} unicast {{ 'route-map ' ~ adv_afi_config.unicast.route_map if adv_afi_config.unicast.route_map is defined }} -{% endif %} -{% endfor %} -{% endif %} -{% if afi_config.distance is defined and afi_config.distance is not none %} -{% if afi_config.distance is defined and afi_config.distance.external is defined and afi_config.distance.internal is defined and afi_config.distance.local is defined %} - distance bgp {{ afi_config.distance.external }} {{ afi_config.distance.internal }} {{ afi_config.distance.local }} -{% endif %} -{% if afi_config.distance.prefix is defined and afi_config.distance.prefix is not none %} -{% for prefix in afi_config.distance.prefix %} - distance {{ afi_config.distance.prefix[prefix].distance }} {{ prefix }} -{% endfor %} -{% endif %} -{% endif %} -{% if afi_config.export is defined and afi_config.export.vpn is defined %} - export vpn -{% endif %} -{% if afi_config.import is defined and afi_config.import is not none %} -{% if afi_config.import.vpn is defined %} - import vpn -{% endif %} -{% if afi_config.import.vrf is defined and afi_config.import.vrf is not none %} -{% for vrf in afi_config.import.vrf %} - import vrf {{ vrf }} -{% endfor %} -{% endif %} -{% endif %} -{% if afi_config.label is defined and afi_config.label.vpn is defined and afi_config.label.vpn.export is defined and afi_config.label.vpn.export is not none %} - label vpn export {{ afi_config.label.vpn.export }} -{% endif %} -{% if afi_config.local_install is defined and afi_config.local_install is not none %} -{% for interface in afi_config.local_install.interface %} - local-install {{ interface }} -{% endfor %} -{% endif %} -{% if afi_config.advertise_all_vni is defined %} - advertise-all-vni -{% endif %} -{% if afi_config.advertise_default_gw is defined %} - advertise-default-gw -{% endif %} -{% if afi_config.advertise_pip is defined and afi_config.advertise_pip is not none %} - advertise-pip ip {{ afi_config.advertise_pip }} -{% endif %} -{% if afi_config.advertise_svi_ip is defined %} - advertise-svi-ip -{% endif %} -{% if afi_config.rt_auto_derive is defined %} - autort rfc8365-compatible -{% endif %} -{% if afi_config.flooding is defined and afi_config.flooding.disable is defined %} - flooding disable -{% endif %} -{% if afi_config.flooding is defined and afi_config.flooding.head_end_replication is defined %} - flooding head-end-replication -{% endif %} -{% if afi_config.rd is defined and afi_config.rd.vpn is defined and afi_config.rd.vpn.export is defined %} - rd vpn export {{ afi_config.rd.vpn.export }} -{% endif %} -{% if afi_config.route_target is defined and afi_config.route_target is not none %} -{% if afi_config.route_target.vpn is defined and afi_config.route_target.vpn is not none %} -{% if afi_config.route_target.vpn.both is defined and afi_config.route_target.vpn.both is not none %} - route-target vpn both {{ afi_config.route_target.vpn.both }} -{% else %} -{% if afi_config.route_target.vpn.export is defined and afi_config.route_target.vpn.export is not none %} - route-target vpn export {{ afi_config.route_target.vpn.export }} -{% endif %} -{% if afi_config.route_target.vpn.import is defined and afi_config.route_target.vpn.import is not none %} - route-target vpn import {{ afi_config.route_target.vpn.import }} -{% endif %} -{% endif %} -{% endif %} -{% if afi_config.route_target.both is defined and afi_config.route_target.both is not none %} - route-target both {{ afi_config.route_target.both }} -{% else %} -{% if afi_config.route_target.export is defined and afi_config.route_target.export is not none %} - route-target export {{ afi_config.route_target.export }} -{% endif %} -{% if afi_config.route_target.import is defined and afi_config.route_target.import is not none %} - route-target import {{ afi_config.route_target.import }} -{% endif %} -{% endif %} -{% endif %} -{% if afi_config.route_map is defined and afi_config.route_map.vpn is defined and afi_config.route_map.vpn is not none %} -{% if afi_config.route_map.vpn.export is defined and afi_config.route_map.vpn.export is not none %} - route-map vpn export {{ afi_config.route_map.vpn.export }} -{% endif %} -{% if afi_config.route_map.vpn.import is defined and afi_config.route_map.vpn.import is not none %} - route-map vpn import {{ afi_config.route_map.vpn.import }} -{% endif %} -{% endif %} -{% if afi_config.vni is defined and afi_config.vni is not none %} -{% for vni, vni_config in afi_config.vni.items() %} - vni {{ vni }} -{% if vni_config.advertise_default_gw is defined %} - advertise-default-gw -{% endif %} -{% if vni_config.advertise_svi_ip is defined %} - advertise-svi-ip -{% endif %} -{% if vni_config.rd is defined and vni_config.rd is not none %} - rd {{ vni_config.rd }} -{% endif %} -{% if vni_config.route_target is defined and vni_config.route_target is not none %} -{% if vni_config.route_target.both is defined and vni_config.route_target.both is not none %} - route-target both {{ vni_config.route_target.both }} -{% endif %} -{% if vni_config.route_target.export is defined and vni_config.route_target.export is not none %} - route-target export {{ vni_config.route_target.export }} -{% endif %} -{% if vni_config.route_target.import is defined and vni_config.route_target.import is not none %} - route-target import {{ vni_config.route_target.import }} -{% endif %} -{% endif %} - exit-vni -{% endfor %} -{% endif %} - exit-address-family -{% endfor %} -{% endif %} - ! -{% if peer_group is defined and peer_group is not none %} -{% for peer, config in peer_group.items() %} -{{ bgp_neighbor(peer, config, true) }} -{% endfor %} -{% endif %} - ! -{% if neighbor is defined and neighbor is not none %} -{% for peer, config in neighbor.items() %} -{{ bgp_neighbor(peer, config) }} -{% endfor %} -{% endif %} - ! -{% if listen is defined %} -{% if listen.limit is defined and listen.limit is not none %} - bgp listen limit {{ listen.limit }} -{% endif %} -{% for prefix, options in listen.range.items() %} -{% if options.peer_group is defined and options.peer_group is not none %} - bgp listen range {{ prefix }} peer-group {{ options.peer_group }} -{% endif %} -{% endfor %} -{% endif %} -{% if parameters is defined %} -{% if parameters.always_compare_med is defined %} - bgp always-compare-med -{% endif %} -{% if parameters.bestpath is defined and parameters.bestpath is not none %} -{% if parameters.bestpath.as_path is defined and parameters.bestpath.as_path is not none %} -{% for option in parameters.bestpath.as_path %} -{# replace is required for multipath-relax option #} - bgp bestpath as-path {{ option|replace('_', '-') }} -{% endfor %} -{% endif %} -{% if parameters.bestpath.bandwidth is defined and parameters.bestpath.bandwidth is not none %} - bgp bestpath bandwidth {{ parameters.bestpath.bandwidth }} -{% endif %} -{% if parameters.bestpath.compare_routerid is defined %} - bgp bestpath compare-routerid -{% endif %} -{% if parameters.bestpath.med is defined and parameters.bestpath.med is not none %} - bgp bestpath med {{ 'confed' if parameters.bestpath.med.confed is defined }} {{ 'missing-as-worst' if parameters.bestpath.med.missing_as_worst is defined }} -{% endif %} -{% endif %} -{% if parameters.cluster_id is defined and parameters.cluster_id is not none %} - bgp cluster-id {{ parameters.cluster_id }} -{% endif %} -{% if parameters.confederation is defined and parameters.confederation is not none %} -{% if parameters.confederation.identifier is defined and parameters.confederation.identifier is not none %} - bgp confederation identifier {{ parameters.confederation.identifier }} -{% endif %} -{% if parameters.confederation.peers is defined and parameters.confederation.peers is not none %} - bgp confederation peers {{ parameters.confederation.peers | join(' ') }} -{% endif %} -{% endif %} -{% if parameters.dampening is defined and parameters.dampening is defined and parameters.dampening.half_life is defined and parameters.dampening.half_life is not none %} -{# Doesn't work in current FRR configuration; vtysh (bgp dampening 16 751 2001 61) #} - bgp dampening {{ parameters.dampening.half_life }} {{ parameters.dampening.re_use if parameters.dampening.re_use is defined }} {{ parameters.dampening.start_suppress_time if parameters.dampening.start_suppress_time is defined }} {{ parameters.dampening.max_suppress_time if parameters.dampening.max_suppress_time is defined }} -{% endif %} -{% if parameters.default is defined and parameters.default is not none %} -{% if parameters.default.local_pref is defined and parameters.default.local_pref is not none %} - bgp default local-preference {{ parameters.default.local_pref }} -{% endif %} -{% endif %} -{% if parameters.deterministic_med is defined %} - bgp deterministic-med -{% endif %} -{% if parameters.distance is defined and parameters.distance is not none %} -{% if parameters.distance.global is defined and parameters.distance.global.external is defined and parameters.distance.global.internal is defined and parameters.distance.global.local is defined %} - distance bgp {{ parameters.distance.global.external }} {{ parameters.distance.global.internal }} {{ parameters.distance.global.local }} -{% endif %} -{% if parameters.distance.prefix is defined and parameters.distance.prefix is not none %} -{% for prefix in parameters.distance.prefix %} - distance {{ parameters.distance.prefix[prefix].distance }} {{ prefix }} -{% endfor %} -{% endif %} -{% endif %} -{% if parameters.graceful_restart is defined %} - bgp graceful-restart {{ 'stalepath-time ' ~ parameters.graceful_restart.stalepath_time if parameters.graceful_restart.stalepath_time is defined }} -{% endif %} -{% if parameters.graceful_shutdown is defined %} - bgp graceful-shutdown -{% endif %} -{% if parameters.log_neighbor_changes is defined %} - bgp log-neighbor-changes -{% endif %} -{% if parameters.network_import_check is defined %} - bgp network import-check -{% endif %} -{% if parameters.no_client_to_client_reflection is defined %} - no bgp client-to-client reflection -{% endif %} -{% if parameters.no_fast_external_failover is defined %} - no bgp fast-external-failover -{% endif %} -{% if parameters.router_id is defined and parameters.router_id is not none %} - bgp router-id {{ parameters.router_id }} -{% endif %} -{% endif %} -{% if timers is defined and timers.keepalive is defined and timers.holdtime is defined %} - timers bgp {{ timers.keepalive }} {{ timers.holdtime }} -{% endif %} - end -!
\ No newline at end of file diff --git a/data/templates/frr/igmp.frr.j2 b/data/templates/frr/igmp.frr.j2 new file mode 100644 index 000000000..ce1f8fdda --- /dev/null +++ b/data/templates/frr/igmp.frr.j2 @@ -0,0 +1,41 @@ +! +{% for iface in old_ifaces %} +interface {{ iface }} +{% for group in old_ifaces[iface].gr_join %} +{% if old_ifaces[iface].gr_join[group] %} +{% for source in old_ifaces[iface].gr_join[group] %} + no ip igmp join {{ group }} {{ source }} +{% endfor %} +{% else %} + no ip igmp join {{ group }} +{% endif %} +{% endfor %} + no ip igmp +! +{% endfor %} +{% for interface, interface_config in ifaces.items() %} +interface {{ interface }} +{% if interface_config.version %} + ip igmp version {{ interface_config.version }} +{% else %} +{# IGMP default version 3 #} + ip igmp +{% endif %} +{% if interface_config.query_interval %} + ip igmp query-interval {{ interface_config.query_interval }} +{% endif %} +{% if interface_config.query_max_resp_time %} + ip igmp query-max-response-time {{ interface_config.query_max_resp_time }} +{% endif %} +{% for group in interface_config.gr_join %} +{% if ifaces[iface].gr_join[group] %} +{% for source in ifaces[iface].gr_join[group] %} + ip igmp join {{ group }} {{ source }} +{% endfor %} +{% else %} + ip igmp join {{ group }} +{% endif %} +{% endfor %} +! +{% endfor %} +! diff --git a/data/templates/frr/igmp.frr.tmpl b/data/templates/frr/igmp.frr.tmpl deleted file mode 100644 index 49b5aeaa5..000000000 --- a/data/templates/frr/igmp.frr.tmpl +++ /dev/null @@ -1,41 +0,0 @@ -! -{% for iface in old_ifaces %} -interface {{ iface }} -{% for group in old_ifaces[iface].gr_join %} -{% if old_ifaces[iface].gr_join[group] %} -{% for source in old_ifaces[iface].gr_join[group] %} - no ip igmp join {{ group }} {{ source }} -{% endfor %} -{% else %} - no ip igmp join {{ group }} -{% endif %} -{% endfor %} - no ip igmp -! -{% endfor %} -{% for iface in ifaces %} -interface {{ iface }} -{% if ifaces[iface].version %} - ip igmp version {{ ifaces[iface].version }} -{% else %} -{# IGMP default version 3 #} - ip igmp -{% endif %} -{% if ifaces[iface].query_interval %} - ip igmp query-interval {{ ifaces[iface].query_interval }} -{% endif %} -{% if ifaces[iface].query_max_resp_time %} - ip igmp query-max-response-time {{ ifaces[iface].query_max_resp_time }} -{% endif %} -{% for group in ifaces[iface].gr_join %} -{% if ifaces[iface].gr_join[group] %} -{% for source in ifaces[iface].gr_join[group] %} - ip igmp join {{ group }} {{ source }} -{% endfor %} -{% else %} - ip igmp join {{ group }} -{% endif %} -{% endfor %} -! -{% endfor %} -! diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2 new file mode 100644 index 000000000..8e95348bc --- /dev/null +++ b/data/templates/frr/isisd.frr.j2 @@ -0,0 +1,197 @@ +! +{% if interface is vyos_defined %} +{% for iface, iface_config in interface.items() %} +interface {{ iface }} + ip router isis VyOS + ipv6 router isis VyOS +{% if iface_config.bfd is vyos_defined %} + isis bfd +{% if iface_config.bfd.profile is vyos_defined %} + isis bfd profile {{ iface_config.bfd.profile }} +{% endif %} +{% endif %} +{% if iface_config.network.point_to_point is vyos_defined %} + isis network point-to-point +{% endif %} +{% if iface_config.circuit_type is vyos_defined %} + isis circuit-type {{ iface_config.circuit_type }} +{% endif %} +{% if iface_config.hello_interval is vyos_defined %} + isis hello-interval {{ iface_config.hello_interval }} +{% endif %} +{% if iface_config.hello_multiplier is vyos_defined %} + isis hello-multiplier {{ iface_config.hello_multiplier }} +{% endif %} +{% if iface_config.hello_padding is vyos_defined %} + isis hello padding +{% endif %} +{% if iface_config.metric is vyos_defined %} + isis metric {{ iface_config.metric }} +{% endif %} +{% if iface_config.passive is vyos_defined %} + isis passive +{% endif %} +{% if iface_config.password.md5 is vyos_defined %} + isis password md5 {{ iface_config.password.md5 }} +{% elif iface_config.password.plaintext_password is vyos_defined %} + isis password clear {{ iface_config.password.plaintext_password }} +{% endif %} +{% if iface_config.priority is vyos_defined %} + isis priority {{ iface_config.priority }} +{% endif %} +{% if iface_config.psnp_interval is vyos_defined %} + isis psnp-interval {{ iface_config.psnp_interval }} +{% endif %} +{% if iface_config.no_three_way_handshake is vyos_defined %} + no isis three-way-handshake +{% endif %} +exit +! +{% endfor %} +{% endif %} +! +router isis VyOS {{ 'vrf ' + vrf if vrf is vyos_defined }} + net {{ net }} +{% if dynamic_hostname is vyos_defined %} + hostname dynamic +{% endif %} +{% if purge_originator is vyos_defined %} + purge-originator +{% endif %} +{% if set_attached_bit is vyos_defined %} + set-attached-bit +{% endif %} +{% if set_overload_bit is vyos_defined %} + set-overload-bit +{% endif %} +{% if domain_password.md5 is vyos_defined %} + domain-password md5 {{ domain_password.plaintext_password }} +{% elif domain_password.plaintext_password is vyos_defined %} + domain-password clear {{ domain_password.plaintext_password }} +{% endif %} +{% if log_adjacency_changes is vyos_defined %} + log-adjacency-changes +{% endif %} +{% if lsp_gen_interval is vyos_defined %} + lsp-gen-interval {{ lsp_gen_interval }} +{% endif %} +{% if lsp_mtu is vyos_defined %} + lsp-mtu {{ lsp_mtu }} +{% endif %} +{% if lsp_refresh_interval is vyos_defined %} + lsp-refresh-interval {{ lsp_refresh_interval }} +{% endif %} +{% if max_lsp_lifetime is vyos_defined %} + max-lsp-lifetime {{ max_lsp_lifetime }} +{% endif %} +{% if spf_interval is vyos_defined %} + spf-interval {{ spf_interval }} +{% endif %} +{% if traffic_engineering.enable is vyos_defined %} + mpls-te on +{% endif %} +{% if traffic_engineering.address is vyos_defined %} + mpls-te router-address {{ traffic_engineering.address }} +{% endif %} +{% if traffic_engineering.inter_as is vyos_defined %} +{% set level = '' %} +{% if traffic_engineering.inter_as.level_1 is vyos_defined %} +{% set level = ' level-1' %} +{% endif %} +{% if traffic_engineering.inter_as.level_1_2 is vyos_defined %} +{% set level = ' level-1-2' %} +{% endif %} +{% if traffic_engineering.inter_as.level_2 is vyos_defined %} +{% set level = ' level-2-only' %} +{% endif %} + mpls-te inter-as{{ level }} +{% endif %} +{% if segment_routing is vyos_defined %} +{% if segment_routing.enable is vyos_defined %} + segment-routing on +{% endif %} +{% if segment_routing.maximum_label_depth is vyos_defined %} + segment-routing node-msd {{ segment_routing.maximum_label_depth }} +{% endif %} +{% if segment_routing.global_block is vyos_defined %} +{% if segment_routing.local_block is vyos_defined %} + segment-routing global-block {{ segment_routing.global_block.low_label_value }} {{ segment_routing.global_block.high_label_value }} local-block {{ segment_routing.local_block.low_label_value }} {{ segment_routing.local_block.high_label_value }} +{% else %} + segment-routing global-block {{ segment_routing.global_block.low_label_value }} {{ segment_routing.global_block.high_label_value }} +{% endif %} +{% endif %} +{% if segment_routing.prefix is vyos_defined %} +{% for prefix, prefix_config in segment_routing.prefix.items() %} +{% if prefix_config.absolute is vyos_defined %} +{% if prefix_config.absolute.value is vyos_defined %} + segment-routing prefix {{ prefixes }} absolute {{ prefix_config.absolute.value }} +{% if prefix_config.absolute.explicit_null is vyos_defined %} + segment-routing prefix {{ prefixes }} absolute {{ prefix_config.absolute.value }} explicit-null +{% endif %} +{% if prefix_config.absolute.no_php_flag is vyos_defined %} + segment-routing prefix {{ prefixes }} absolute {{ prefix_config.absolute.value }} no-php-flag +{% endif %} +{% endif %} +{% if prefix_config.index is vyos_defined %} +{% if prefix_config.index.value is vyos_defined %} + segment-routing prefix {{ prefixes }} index {{ prefix_config.index.value }} +{% if prefix_config.index.explicit_null is vyos_defined %} + segment-routing prefix {{ prefixes }} index {{ prefix_config.index.value }} explicit-null +{% endif %} +{% if prefix_config.index.no_php_flag is vyos_defined %} + segment-routing prefix {{ prefixes }} index {{ prefix_config.index.value }} no-php-flag +{% endif %} +{% endif %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{% endif %} +{% if spf_delay_ietf.init_delay is vyos_defined %} + spf-delay-ietf init-delay {{ spf_delay_ietf.init_delay }} short-delay {{ spf_delay_ietf.short_delay }} long-delay {{ spf_delay_ietf.long_delay }} holddown {{ spf_delay_ietf.holddown }} time-to-learn {{ spf_delay_ietf.time_to_learn }} +{% endif %} +{% if area_password.md5 is vyos_defined %} + area-password md5 {{ area_password.md5 }} +{% elif area_password.plaintext_password is vyos_defined %} + area-password clear {{ area_password.plaintext_password }} +{% endif %} +{% if default_information.originate is vyos_defined %} +{% for afi, afi_config in default_information.originate.items() %} +{% for level, level_config in afi_config.items() %} + default-information originate {{ afi }} {{ level | replace('_', '-') }} {{ 'always' if level_config.always is vyos_defined }} {{ 'route-map ' ~ level_config.route_map if level_config.route_map is vyos_defined }} {{ 'metric ' ~ level_config.metric if level_config.metric is vyos_defined }} +{% endfor %} +{% endfor %} +{% endif %} +{% if redistribute.ipv4 is vyos_defined %} +{% for protocol, protocol_options in redistribute.ipv4.items() %} +{% for level, level_config in protocol_options.items() %} +{% if level_config.metric is vyos_defined %} + redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} metric {{ level_config.metric }} +{% elif level_config.route_map is vyos_defined %} + redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} route-map {{ level_config.route_map }} +{% else %} + redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} +{% endif %} +{% endfor %} +{% endfor %} +{% endif %} +{% if redistribute.ipv6 is vyos_defined %} +{% for protocol, protocol_options in redistribute.ipv6.items() %} +{% for level, level_config in protocol_options.items() %} +{% if level_config.metric is vyos_defined %} + redistribute ipv6 {{ protocol }} {{ level | replace('_', '-') }} metric {{ level_config.metric }} +{% elif level_config.route_map is vyos_defined %} + redistribute ipv6 {{ protocol }} {{ level | replace('_', '-') }} route-map {{ level_config.route_map }} +{% else %} + redistribute ipv6 {{ protocol }} {{ level | replace('_', '-') }} +{% endif %} +{% endfor %} +{% endfor %} +{% endif %} +{% if level is vyos_defined('level-2') %} + is-type level-2-only +{% elif level is vyos_defined %} + is-type {{ level }} +{% endif %} +exit +!
\ No newline at end of file diff --git a/data/templates/frr/isisd.frr.tmpl b/data/templates/frr/isisd.frr.tmpl deleted file mode 100644 index 51ac40060..000000000 --- a/data/templates/frr/isisd.frr.tmpl +++ /dev/null @@ -1,198 +0,0 @@ -! -router isis VyOS {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} - net {{ net }} -{% if dynamic_hostname is defined %} - hostname dynamic -{% endif %} -{% if purge_originator is defined %} - purge-originator -{% endif %} -{% if set_attached_bit is defined %} - set-attached-bit -{% endif %} -{% if set_overload_bit is defined %} - set-overload-bit -{% endif %} -{% if domain_password is defined and domain_password is not none %} -{% if domain_password.md5 is defined and domain_password.md5 is not none %} - domain-password md5 {{ domain_password.plaintext_password }} -{% elif domain_password.plaintext_password is defined and domain_password.plaintext_password is not none %} - domain-password clear {{ domain_password.plaintext_password }} -{% endif %} -{% endif %} -{% if log_adjacency_changes is defined %} - log-adjacency-changes -{% endif %} -{% if lsp_gen_interval is defined and lsp_gen_interval is not none %} - lsp-gen-interval {{ lsp_gen_interval }} -{% endif %} -{% if lsp_mtu is defined and lsp_mtu is not none %} - lsp-mtu {{ lsp_mtu }} -{% endif %} -{% if lsp_refresh_interval is defined and lsp_refresh_interval is not none %} - lsp-refresh-interval {{ lsp_refresh_interval }} -{% endif %} -{% if max_lsp_lifetime is defined and max_lsp_lifetime is not none %} - max-lsp-lifetime {{ max_lsp_lifetime }} -{% endif %} -{% if spf_interval is defined and spf_interval is not none %} - spf-interval {{ spf_interval }} -{% endif %} -{% if traffic_engineering is defined and traffic_engineering is not none %} -{% if traffic_engineering.enable is defined %} - mpls-te on -{% endif %} -{% if traffic_engineering.address is defined %} - mpls-te router-address {{ traffic_engineering.address }} -{% endif %} -{% if traffic_engineering.inter_as is defined %} -{% if traffic_engineering.inter_as.level_1 is defined %} - mpls-te inter-as level-1 -{% endif %} -{% if traffic_engineering.inter_as.level_1_2 is defined %} - mpls-te inter-as level-1-2 -{% endif %} -{% if traffic_engineering.inter_as.level_2 is defined %} - mpls-te inter-as level-2-only -{% endif %} -{% else %} - mpls-te inter-as -{% endif %} -{% endif %} -{% if segment_routing is defined %} -{% if segment_routing.enable is defined %} - segment-routing on -{% endif %} -{% if segment_routing.maximum_label_depth is defined %} - segment-routing node-msd {{ segment_routing.maximum_label_depth }} -{% endif %} -{% if segment_routing.global_block is defined %} - segment-routing global-block {{ segment_routing.global_block.low_label_value }} {{ segment_routing.global_block.high_label_value }} -{% endif %} -{% if segment_routing.local_block is defined %} - segment-routing local-block {{ segment_routing.global_block.low_label_value }} {{ segment_routing.local_block.high_label_value }} -{% endif %} -{% if segment_routing.prefix is defined %} -{% for prefixes in segment_routing.prefix %} -{% if segment_routing.prefix[prefixes].absolute is defined %} -{% if segment_routing.prefix[prefixes].absolute.value is defined %} - segment-routing prefix {{ prefixes }} absolute {{ segment_routing.prefix[prefixes].absolute.value }} -{% if segment_routing.prefix[prefixes].absolute.explicit_null is defined %} - segment-routing prefix {{ prefixes }} absolute {{ segment_routing.prefix[prefixes].absolute.value }} explicit-null -{% endif %} -{% if segment_routing.prefix[prefixes].absolute.no_php_flag is defined %} - segment-routing prefix {{ prefixes }} absolute {{ segment_routing.prefix[prefixes].absolute.value }} no-php-flag -{% endif %} -{% endif %} -{% if segment_routing.prefix[prefixes].index is defined %} -{% if segment_routing.prefix[prefixes].index.value is defined %} - segment-routing prefix {{ prefixes }} index {{ segment_routing.prefix[prefixes].index.value }} -{% if segment_routing.prefix[prefixes].index.explicit_null is defined %} - segment-routing prefix {{ prefixes }} index {{ segment_routing.prefix[prefixes].index.value }} explicit-null -{% endif %} -{% if segment_routing.prefix[prefixes].index.no_php_flag is defined %} - segment-routing prefix {{ prefixes }} index {{ segment_routing.prefix[prefixes].index.value }} no-php-flag -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% endfor %} -{% endif %} -{% endif %} -{% if spf_delay_ietf is defined and spf_delay_ietf.init_delay is defined and spf_delay_ietf.init_delay is not none %} - spf-delay-ietf init-delay {{ spf_delay_ietf.init_delay }} short-delay {{ spf_delay_ietf.short_delay }} long-delay {{ spf_delay_ietf.long_delay }} holddown {{ spf_delay_ietf.holddown }} time-to-learn {{ spf_delay_ietf.time_to_learn }} -{% endif %} -{% if area_password is defined and area_password is not none %} -{% if area_password.md5 is defined and area_password.md5 is not none %} - area-password md5 {{ area_password.md5 }} -{% elif area_password.plaintext_password is defined and area_password.plaintext_password is not none %} - area-password clear {{ area_password.plaintext_password }} -{% endif %} -{% endif %} -{% if default_information is defined and default_information.originate is defined and default_information.originate is not none %} -{% for afi, afi_config in default_information.originate.items() %} -{% for level, level_config in afi_config.items() %} - default-information originate {{ afi }} {{ level | replace('_', '-') }} {{ 'always' if level_config.always is defined }} {{ 'route-map ' ~ level_config.route_map if level_config.route_map is defined }} {{ 'metric ' ~ level_config.metric if level_config.metric is defined }} -{% endfor %} -{% endfor %} -{% endif %} -{% if redistribute is defined %} -{% if redistribute.ipv4 is defined and redistribute.ipv4 is not none %} -{% for protocol, protocol_options in redistribute.ipv4.items() %} -{% for level, level_config in protocol_options.items() %} -{% if level_config.metric is defined and level_config.metric is not none %} - redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} metric {{ level_config.metric }} -{% elif level_config.route_map is defined and level_config.route_map is not none %} - redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} route-map {{ level_config.route_map }} -{% else %} - redistribute ipv4 {{ protocol }} {{ level | replace('_', '-') }} -{% endif %} -{% endfor %} -{% endfor %} -{% endif %} -{% if redistribute.ipv6 is defined and redistribute.ipv6 is not none %} -{% for protocol, protocol_options in redistribute.ipv6.items() %} -{% for level, level_config in protocol_options.items() %} -{% if level_config.metric is defined and level_config.metric is not none %} - redistribute ipv6 {{ protocol }} {{ level | replace('_', '-') }} metric {{ level_config.metric }} -{% elif level_config.route_map is defined and level_config.route_map is not none %} - redistribute ipv6 {{ protocol }} {{ level | replace('_', '-') }} route-map {{ level_config.route_map }} -{% else %} - redistribute ipv6 {{ protocol }} {{ level | replace('_', '-') }} -{% endif %} -{% endfor %} -{% endfor %} -{% endif %} -{% endif %} -{% if level is defined and level is not none %} -{% if level == 'level-2' %} - is-type level-2-only -{% else %} - is-type {{ level }} -{% endif %} -{% endif %} -! -{% if interface is defined and interface is not none %} -{% for iface, iface_config in interface.items() %} -interface {{ iface }} {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} - ip router isis VyOS - ipv6 router isis VyOS -{% if iface_config.bfd is defined %} - isis bfd -{% endif %} -{% if iface_config.network is defined and iface_config.network.point_to_point is defined %} - isis network point-to-point -{% endif %} -{% if iface_config.circuit_type is defined %} - isis circuit-type {{ iface_config.circuit_type }} -{% endif %} -{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %} - isis hello-interval {{ iface_config.hello_interval }} -{% endif %} -{% if iface_config.hello_multiplier is defined and iface_config.hello_multiplier is not none %} - isis hello-multiplier {{ iface_config.hello_multiplier }} -{% endif %} -{% if iface_config.hello_padding is defined %} - isis hello padding -{% endif %} -{% if iface_config.metric is defined and iface_config.metric is not none %} - isis metric {{ iface_config.metric }} -{% endif %} -{% if iface_config.passive is defined %} - isis passive -{% endif %} -{% if iface_config.password is defined and iface_config.password.plaintext_password is defined and iface_config.password.plaintext_password is not none %} - isis password clear {{ iface_config.password.plaintext_password }} -{% endif %} -{% if iface_config.priority is defined and iface_config.priority is not none %} - isis priority {{ iface_config.priority }} -{% endif %} -{% if iface_config.psnp_interval is defined and iface_config.psnp_interval is not none %} - isis psnp-interval {{ iface_config.psnp_interval }} -{% endif %} -{% if iface_config.no_three_way_handshake is defined %} - no isis three-way-handshake -{% endif %} -{% endfor %} -{% endif %} -!
\ No newline at end of file diff --git a/data/templates/frr/ldpd.frr.j2 b/data/templates/frr/ldpd.frr.j2 new file mode 100644 index 000000000..11aff331a --- /dev/null +++ b/data/templates/frr/ldpd.frr.j2 @@ -0,0 +1,149 @@ +! +{% if ldp is vyos_defined %} +mpls ldp +{% if ldp.router_id is vyos_defined %} + router-id {{ ldp.router_id }} +{% endif %} +{% if ldp.parameters.cisco_interop_tlv is vyos_defined %} + dual-stack cisco-interop +{% endif %} +{% if ldp.parameters.transport_prefer_ipv4 is vyos_defined %} + dual-stack transport-connection prefer ipv4 +{% endif %} +{% if ldp.parameters.ordered_control is vyos_defined %} + ordered-control +{% endif %} +{% if ldp.neighbor is vyos_defined %} +{% for neighbor, neighbor_config in ldp.neighbor %} +{% if neighbor_config.password is vyos_defined %} + neighbor {{ neighbors }} password {{ neighbor_config.password }} +{% endif %} +{% if neighbor_config.ttl_security is vyos_defined %} +{% if neighbor_config.ttl_security.disable is vyos_defined %} + neighbor {{ neighbors }} ttl-security disable +{% else %} + neighbor {{ neighbors }} ttl-security hops {{ neighbor_config.ttl_security }} +{% endif %} +{% endif %} +{% if neighbor_config.session_holdtime is vyos_defined %} + neighbor {{ neighbors }} session holdtime {{ neighbor_config.session_holdtime }} +{% endif %} +{% endfor %} +{% endif %} + ! +{% if ldp.discovery.transport_ipv4_address is vyos_defined %} + address-family ipv4 +{% if ldp.allocation.ipv4.access_list is vyos_defined %} + label local allocate for {{ ldp.allocation.ipv4.access_list }} +{% else %} + label local allocate host-routes +{% endif %} +{% if ldp.discovery.transport_ipv4_address is vyos_defined %} + discovery transport-address {{ ldp.discovery.transport_ipv4_address }} +{% endif %} +{% if ldp.discovery.hello_ipv4_holdtime is vyos_defined %} + discovery hello holdtime {{ ldp.discovery.hello_ipv4_holdtime }} +{% endif %} +{% if ldp.discovery.hello_ipv4_interval is vyos_defined %} + discovery hello interval {{ ldp.discovery.hello_ipv4_interval }} +{% endif %} +{% if ldp.discovery.session_ipv4_holdtime is vyos_defined %} + session holdtime {{ ldp.discovery.session_ipv4_holdtime }} +{% endif %} +{% if ldp.import.ipv4.import_filter.filter_access_list is vyos_defined %} +{% if ldp.import.ipv4.import_filter.neighbor_access_list is vyos_defined %} + label remote accept for {{ ldp.import.ipv4.import_filter.filter_access_list }} from {{ ldp.import.ipv4.import_filter.neighbor_access_list }} +{% else %} + label remote accept for {{ ldp.import.ipv4.import_filter.filter_access_list }} +{% endif %} +{% endif %} +{% if ldp.export.ipv4.explicit_null is vyos_defined %} + label local advertise explicit-null +{% endif %} +{% if ldp.export.ipv4.export_filter.filter_access_list is vyos_defined %} +{% if ldp.export.ipv4.export_filter.neighbor_access_list is vyos_defined %} + label local advertise for {{ ldp.export.ipv4.export_filter.filter_access_list }} to {{ ldp.export.ipv4.export_filter.neighbor_access_list }} +{% else %} + label local advertise for {{ ldp.export.ipv4.export_filter.filter_access_list }} +{% endif %} +{% endif %} +{% if ldp.targeted_neighbor is vyos_defined %} +{% if ldp.targeted_neighbor.ipv4.enable is vyos_defined %} + discovery targeted-hello accept +{% endif %} +{% if ldp.targeted_neighbor.ipv4.hello_holdtime is vyos_defined %} + discovery targeted-hello holdtime {{ ldp.targeted_neighbor.ipv4.hello_holdtime }} +{% endif %} +{% if ldp.targeted_neighbor.ipv4.hello_interval is vyos_defined %} + discovery targeted-hello interval {{ ldp.targeted_neighbor.ipv4.hello_interval }} +{% endif %} +{% for addresses in ldp.targeted_neighbor.ipv4.address %} + neighbor {{ addresses }} targeted +{% endfor %} +{% endif %} +{% if ldp.interface is vyos_defined %} +{% for interface in ldp.interface %} + interface {{ interface }} + exit +{% endfor %} +{% endif %} + exit-address-family +{% else %} + no address-family ipv4 +{% endif %} + ! +{% if ldp.discovery.transport_ipv6_address is vyos_defined %} + address-family ipv6 +{% if ldp.allocation.ipv6.access_list6 is vyos_defined %} + label local allocate for {{ ldp.allocation.ipv6.access_list6 }} +{% else %} + label local allocate host-routes +{% endif %} +{% if ldp.discovery.transport_ipv6_address is vyos_defined %} + discovery transport-address {{ ldp.discovery.transport_ipv6_address }} +{% endif %} +{% if ldp.discovery.hello_ipv6_holdtime is vyos_defined %} + discovery hello holdtime {{ ldp.discovery.hello_ipv6_holdtime }} +{% endif %} +{% if ldp.discovery.hello_ipv6_interval is vyos_defined %} + discovery hello interval {{ ldp.discovery.hello_ipv6_interval }} +{% endif %} +{% if ldp.discovery.session_ipv6_holdtime is vyos_defined %} + session holdtime {{ ldp.discovery.session_ipv6_holdtime }} +{% endif %} +{% if ldp.import.ipv6.import_filter.filter_access_list6 is vyos_defined %} + label remote accept for {{ ldp.import.ipv6.import_filter.filter_access_list6 }} {{ 'from ' ~ ldp.import.ipv6.import_filter.neighbor_access_list6 if ldp.import.ipv6.import_filter.neighbor_access_list6 is vyos_defined }} +{% endif %} +{% if ldp.export.ipv6.explicit_null is vyos_defined %} + label local advertise explicit-null +{% endif %} +{% if ldp.export.ipv6.export_filter.filter_access_list6 is vyos_defined %} + label local advertise for {{ ldp.export.ipv6.export_filter.filter_access_list6 }} {{ 'to ' ~ ldp.export.ipv6.export_filter.neighbor_access_list6 if ldp.export.ipv6.export_filter.neighbor_access_list6 is vyos_defined }} +{% endif %} +{% if ldp.targeted_neighbor is vyos_defined %} +{% if ldp.targeted_neighbor.ipv6.enable is vyos_defined %} + discovery targeted-hello accept +{% endif %} +{% if ldp.targeted_neighbor.ipv6.hello_holdtime is vyos_defined %} + discovery targeted-hello holdtime {{ ldp.targeted_neighbor.ipv6.hello_holdtime }} +{% endif %} +{% if ldp.targeted_neighbor.ipv6.hello_interval is vyos_defined %} + discovery targeted-hello interval {{ ldp.targeted_neighbor.ipv6.hello_interval }} +{% endif %} +{% for addresses in ldp.targeted_neighbor.ipv6.address %} + neighbor {{ addresses }} targeted +{% endfor %} +{% endif %} +{% if ldp.interface is vyos_defined %} +{% for interface in ldp.interface %} + interface {{ interface }} +{% endfor %} +{% endif %} + exit-address-family +{% else %} + no address-family ipv6 +{% endif %} + ! +exit +{% endif %} +! diff --git a/data/templates/frr/ldpd.frr.tmpl b/data/templates/frr/ldpd.frr.tmpl deleted file mode 100644 index 0a5411552..000000000 --- a/data/templates/frr/ldpd.frr.tmpl +++ /dev/null @@ -1,187 +0,0 @@ -! -{% if ldp is defined %} -mpls ldp -{% if ldp.router_id is defined %} -router-id {{ ldp.router_id }} -{% endif %} -{% if ldp.parameters is defined %} -{% if ldp.parameters.cisco_interop_tlv is defined %} -dual-stack cisco-interop -{% endif %} -{% if ldp.parameters.transport_prefer_ipv4 is defined%} -dual-stack transport-connection prefer ipv4 -{% endif %} -{% if ldp.parameters.ordered_control is defined%} -ordered-control -{% endif %} -{% endif %} -{% if ldp.neighbor is defined %} -{% for neighbors in ldp.neighbor %} -{% if ldp.neighbor[neighbors].password is defined %} -neighbor {{neighbors}} password {{ldp.neighbor[neighbors].password}} -{% endif %} -{% if ldp.neighbor[neighbors].ttl_security is defined %} -{% if 'disable' in ldp.neighbor[neighbors].ttl_security %} -neighbor {{neighbors}} ttl-security disable -{% else %} -neighbor {{neighbors}} ttl-security hops {{ldp.neighbor[neighbors].ttl_security}} -{% endif %} -{% endif %} -{% if ldp.neighbor[neighbors].session_holdtime is defined %} -neighbor {{neighbors}} session holdtime {{ldp.neighbor[neighbors].session_holdtime}} -{% endif %} -{% endfor %} -{% endif %} -! -{% if ldp.discovery is defined %} -{% if ldp.discovery.transport_ipv4_address is defined %} -address-family ipv4 -{% if ldp.allocation is defined %} -{% if ldp.allocation.ipv4 is defined %} -{% if ldp.allocation.ipv4.access_list is defined %} -label local allocate for {{ ldp.allocation.ipv4.access_list }} -{% endif %} -{% endif %} -{% else %} -label local allocate host-routes -{% endif %} -{% if ldp.discovery.transport_ipv4_address is defined %} -discovery transport-address {{ ldp.discovery.transport_ipv4_address }} -{% endif %} -{% if ldp.discovery.hello_ipv4_holdtime is defined %} -discovery hello holdtime {{ ldp.discovery.hello_ipv4_holdtime }} -{% endif %} -{% if ldp.discovery.hello_ipv4_interval is defined %} -discovery hello interval {{ ldp.discovery.hello_ipv4_interval }} -{% endif %} -{% if ldp.discovery.session_ipv4_holdtime is defined %} -session holdtime {{ ldp.discovery.session_ipv4_holdtime }} -{% endif %} -{% if ldp.import is defined %} -{% if ldp.import.ipv4 is defined %} -{% if ldp.import.ipv4.import_filter is defined %} -{% if ldp.import.ipv4.import_filter.filter_access_list is defined %} -{% if ldp.import.ipv4.import_filter.neighbor_access_list is defined %} -label remote accept for {{ ldp.import.ipv4.import_filter.filter_access_list }} from {{ ldp.import.ipv4.import_filter.neighbor_access_list }} -{% else %} -label remote accept for {{ ldp.import.ipv4.import_filter.filter_access_list }} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% if ldp.export is defined %} -{% if ldp.export.ipv4 is defined %} -{% if ldp.export.ipv4.explicit_null is defined %} -label local advertise explicit-null -{% endif %} -{% if ldp.export.ipv4.export_filter is defined %} -{% if ldp.export.ipv4.export_filter.filter_access_list is defined %} -{% if ldp.export.ipv4.export_filter.neighbor_access_list is defined %} -label local advertise for {{ ldp.export.ipv4.export_filter.filter_access_list }} to {{ ldp.export.ipv4.export_filter.neighbor_access_list }} -{% else %} -label local advertise for {{ ldp.export.ipv4.export_filter.filter_access_list }} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% if ldp.targeted_neighbor is defined %} -{% if ldp.targeted_neighbor.ipv4.enable is defined %} -discovery targeted-hello accept -{% endif %} -{% if ldp.targeted_neighbor.ipv4.hello_holdtime is defined %} -discovery targeted-hello holdtime {{ ldp.targeted_neighbor.ipv4.hello_holdtime }} -{% endif %} -{% if ldp.targeted_neighbor.ipv4.hello_interval is defined %} -discovery targeted-hello interval {{ ldp.targeted_neighbor.ipv4.hello_interval }} -{% endif %} -{% for addresses in ldp.targeted_neighbor.ipv4.address %} -neighbor {{addresses}} targeted -{% endfor %} -{% endif %} -{% for interfaces in ldp.interface %} -interface {{interfaces}} -{% endfor %} -exit-address-family -{% else %} -no address-family ipv4 -{% endif %} -{% endif %} -! -{% if ldp.discovery is defined %} -{% if ldp.discovery.transport_ipv6_address is defined %} -address-family ipv6 -{% if ldp.allocation is defined %} -{% if ldp.allocation.ipv6 is defined %} -{% if ldp.allocation.ipv6.access_list6 is defined %} -label local allocate for {{ ldp.allocation.ipv6.access_list6 }} -{% endif %} -{% endif %} -{% else %} -label local allocate host-routes -{% endif %} -{% if ldp.discovery.transport_ipv6_address is defined %} -discovery transport-address {{ ldp.discovery.transport_ipv6_address }} -{% endif %} -{% if ldp.discovery.hello_ipv6_holdtime is defined %} -discovery hello holdtime {{ ldp.discovery.hello_ipv6_holdtime }} -{% endif %} -{% if ldp.discovery.hello_ipv6_interval is defined %} -discovery hello interval {{ ldp.discovery.hello_ipv6_interval }} -{% endif %} -{% if ldp.discovery.session_ipv6_holdtime is defined %} -session holdtime {{ ldp.discovery.session_ipv6_holdtime }} -{% endif %} -{% if ldp.import is defined %} -{% if ldp.import.ipv6 is defined %} -{% if ldp.import.ipv6.import_filter is defined %} -{% if ldp.import.ipv6.import_filter.filter_access_list6 is defined %} -{% if ldp.import.ipv6.import_filter.neighbor_access_list6 is defined %} -label remote accept for {{ ldp.import.ipv6.import_filter.filter_access_list6 }} from {{ ldp.import.ipv6.import_filter.neighbor_access_list6 }} -{% else %} -label remote accept for {{ ldp.import.ipv6.import_filter.filter_access_list6 }} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% if ldp.export is defined %} -{% if ldp.export.ipv6 is defined %} -{% if ldp.export.ipv6.explicit_null is defined %} -label local advertise explicit-null -{% endif %} -{% if ldp.export.ipv6.export_filter is defined %} -{% if ldp.export.ipv6.export_filter.filter_access_list6 is defined %} -{% if ldp.export.ipv6.export_filter.neighbor_access_list6 is defined %} -label local advertise for {{ ldp.export.ipv6.export_filter.filter_access_list6 }} to {{ ldp.export.ipv6.export_filter.neighbor_access_list6 }} -{% else %} -label local advertise for {{ ldp.export.ipv6.export_filter.filter_access_list6 }} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% endif %} -{% if ldp.targeted_neighbor is defined %} -{% if ldp.targeted_neighbor.ipv6.enable is defined %} -discovery targeted-hello accept -{% endif %} -{% if ldp.targeted_neighbor.ipv6.hello_holdtime is defined %} -discovery targeted-hello holdtime {{ ldp.targeted_neighbor.ipv6.hello_holdtime }} -{% endif %} -{% if ldp.targeted_neighbor.ipv6.hello_interval is defined %} -discovery targeted-hello interval {{ ldp.targeted_neighbor.ipv6.hello_interval }} -{% endif %} -{% for addresses in ldp.targeted_neighbor.ipv6.address %} -neighbor {{addresses}} targeted -{% endfor %} -{% endif %} -{% for interfaces in ldp.interface %} -interface {{interfaces}} -{% endfor %} -exit-address-family -{% else %} -no address-family ipv6 -{% endif %} -{% endif %} -{% endif %} diff --git a/data/templates/frr/ospf6d.frr.j2 b/data/templates/frr/ospf6d.frr.j2 new file mode 100644 index 000000000..84394ed1a --- /dev/null +++ b/data/templates/frr/ospf6d.frr.j2 @@ -0,0 +1,95 @@ +! +{% if interface is vyos_defined %} +{% for iface, iface_config in interface.items() %} +interface {{ iface }} +{% if iface_config.area is vyos_defined %} + ipv6 ospf6 area {{ iface_config.area }} +{% endif %} +{% if iface_config.cost is vyos_defined %} + ipv6 ospf6 cost {{ iface_config.cost }} +{% endif %} +{% if iface_config.priority is vyos_defined %} + ipv6 ospf6 priority {{ iface_config.priority }} +{% endif %} +{% if iface_config.hello_interval is vyos_defined %} + ipv6 ospf6 hello-interval {{ iface_config.hello_interval }} +{% endif %} +{% if iface_config.retransmit_interval is vyos_defined %} + ipv6 ospf6 retransmit-interval {{ iface_config.retransmit_interval }} +{% endif %} +{% if iface_config.transmit_delay is vyos_defined %} + ipv6 ospf6 transmit-delay {{ iface_config.transmit_delay }} +{% endif %} +{% if iface_config.dead_interval is vyos_defined %} + ipv6 ospf6 dead-interval {{ iface_config.dead_interval }} +{% endif %} +{% if iface_config.bfd is vyos_defined %} + ipv6 ospf6 bfd +{% endif %} +{% if iface_config.bfd.profile is vyos_defined %} + ipv6 ospf6 bfd profile {{ iface_config.bfd.profile }} +{% endif %} +{% if iface_config.mtu_ignore is vyos_defined %} + ipv6 ospf6 mtu-ignore +{% endif %} +{% if iface_config.ifmtu is vyos_defined %} + ipv6 ospf6 ifmtu {{ iface_config.ifmtu }} +{% endif %} +{% if iface_config.network is vyos_defined %} + ipv6 ospf6 network {{ iface_config.network }} +{% endif %} +{% if iface_config.instance_id is vyos_defined %} + ipv6 ospf6 instance-id {{ iface_config.instance_id }} +{% endif %} +{% if iface_config.passive is vyos_defined %} + ipv6 ospf6 passive +{% endif %} +exit +! +{% endfor %} +{% endif %} +! +router ospf6 {{ 'vrf ' ~ vrf if vrf is vyos_defined }} +{% if area is vyos_defined %} +{% for area_id, area_config in area.items() %} +{% if area_config.area_type is vyos_defined %} +{% for type, type_config in area_config.area_type.items() %} + area {{ area_id }} {{ type }} {{ 'default-information-originate' if type_config.default_information_originate is vyos_defined }} {{ 'no-summary' if type_config.no_summary is vyos_defined }} +{% endfor %} +{% endif %} +{% if area_config.range is vyos_defined %} +{% for prefix, prefix_config in area_config.range.items() %} + area {{ area_id }} range {{ prefix }} {{ 'advertise' if prefix_config.advertise is vyos_defined }} {{ 'not-advertise' if prefix_config.not_advertise is vyos_defined }} +{% endfor %} +{% endif %} +{% if area_config.export_list is vyos_defined %} + area {{ area_id }} export-list {{ area_config.export_list }} +{% endif %} +{% if area_config.import_list is vyos_defined %} + area {{ area_id }} import-list {{ area_config.import_list }} +{% endif %} +{% endfor %} +{% endif %} + auto-cost reference-bandwidth {{ auto_cost.reference_bandwidth }} +{% if default_information.originate is vyos_defined %} + default-information originate {{ 'always' if default_information.originate.always is vyos_defined }} {{ 'metric ' ~ default_information.originate.metric if default_information.originate.metric is vyos_defined }} {{ 'metric-type ' ~ default_information.originate.metric_type if default_information.originate.metric_type is vyos_defined }} {{ 'route-map ' ~ default_information.originate.route_map if default_information.originate.route_map is vyos_defined }} +{% endif %} +{% if distance.global is vyos_defined %} + distance {{ distance.global }} +{% endif %} +{% if distance.ospfv3 is vyos_defined %} + distance ospf6 {{ 'intra-area ' ~ distance.ospfv3.intra_area if distance.ospfv3.intra_area is vyos_defined }} {{ 'inter-area ' ~ distance.ospfv3.inter_area if distance.ospfv3.inter_area is vyos_defined }} {{ 'external ' ~ distance.ospfv3.external if distance.ospfv3.external is vyos_defined }} +{% endif %} +{% if log_adjacency_changes is vyos_defined %} + log-adjacency-changes {{ "detail" if log_adjacency_changes.detail is vyos_defined }} +{% endif %} +{% if parameters.router_id is vyos_defined %} + ospf6 router-id {{ parameters.router_id }} +{% endif %} +{% if redistribute is vyos_defined %} +{% for protocol, options in redistribute.items() %} + redistribute {{ protocol }} {{ 'route-map ' ~ options.route_map if options.route_map is vyos_defined }} +{% endfor %} +{% endif %} +exit +! diff --git a/data/templates/frr/ospf6d.frr.tmpl b/data/templates/frr/ospf6d.frr.tmpl deleted file mode 100644 index a8c53738f..000000000 --- a/data/templates/frr/ospf6d.frr.tmpl +++ /dev/null @@ -1,92 +0,0 @@ -! -{% if interface is defined and interface is not none %} -{% for iface, iface_config in interface.items() %} -interface {{ iface }} -{% if iface_config.cost is defined and iface_config.cost is not none %} - ipv6 ospf6 cost {{ iface_config.cost }} -{% endif %} -{% if iface_config.priority is defined and iface_config.priority is not none %} - ipv6 ospf6 priority {{ iface_config.priority }} -{% endif %} -{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %} - ipv6 ospf6 hello-interval {{ iface_config.hello_interval }} -{% endif %} -{% if iface_config.retransmit_interval is defined and iface_config.retransmit_interval is not none %} - ipv6 ospf6 retransmit-interval {{ iface_config.retransmit_interval }} -{% endif %} -{% if iface_config.transmit_delay is defined and iface_config.transmit_delay is not none %} - ipv6 ospf6 transmit-delay {{ iface_config.transmit_delay }} -{% endif %} -{% if iface_config.dead_interval is defined and iface_config.dead_interval is not none %} - ipv6 ospf6 dead-interval {{ iface_config.dead_interval }} -{% endif %} -{% if iface_config.bfd is defined %} - ipv6 ospf6 bfd -{% endif %} -{% if iface_config.mtu_ignore is defined %} - ipv6 ospf6 mtu-ignore -{% endif %} -{% if iface_config.ifmtu is defined and iface_config.ifmtu is not none %} - ipv6 ospf6 ifmtu {{ iface_config.ifmtu }} -{% endif %} -{% if iface_config.network is defined and iface_config.network is not none %} - ipv6 ospf6 network {{ iface_config.network }} -{% endif %} -{% if iface_config.instance_id is defined and iface_config.instance_id is not none %} - ipv6 ospf6 instance-id {{ iface_config.instance_id }} -{% endif %} -{% if iface_config.passive is defined %} - ipv6 ospf6 passive -{% endif %} -! -{% endfor %} -{% endif %} -! -router ospf6 -{% if area is defined and area is not none %} -{% for area_id, area_config in area.items() %} -{% if area_config.interface is defined and area_config.interface is not none %} -{% for interface in area_config.interface %} - interface {{ interface }} area {{ area_id }} -{% endfor %} -{% endif %} -{% if area_config.area_type is defined and area_config.area_type is not none %} -{% for type, type_config in area_config.area_type.items() %} - area {{ area_id }} {{ type }} {{ 'no-summary' if type_config.no_summary is defined }} -{% endfor %} -{% endif %} -{% if area_config.range is defined and area_config.range is not none %} -{% for prefix, prefix_config in area_config.range.items() %} - area {{ area_id }} range {{ prefix }} {{ 'advertise' if prefix_config.advertise is defined }} {{ 'not-advertise' if prefix_config.not_advertise is defined }} -{% endfor %} -{% endif %} -{% if area_config.export_list is defined and area_config.export_list is not none %} - area {{ area_id }} export-list {{ area_config.export_list }} -{% endif %} -{% if area_config.import_list is defined and area_config.import_list is not none %} - area {{ area_id }} import-list {{ area_config.import_list }} -{% endif %} -{% endfor %} -{% endif %} -{% if distance is defined and distance is not none %} -{% if distance.global is defined and distance.global is not none %} - distance {{ distance.global }} -{% endif %} -{% if distance.ospfv3 is defined and distance.ospfv3 is not none %} - distance ospf6 {{ 'intra-area ' + distance.ospfv3.intra_area if distance.ospfv3.intra_area is defined }} {{ 'inter-area ' + distance.ospfv3.inter_area if distance.ospfv3.inter_area is defined }} {{ 'external ' + distance.ospfv3.external if distance.ospfv3.external is defined }} -{% endif %} -{% endif %} -{% if log_adjacency_changes is defined %} - log-adjacency-changes {{ "detail" if log_adjacency_changes.detail is defined }} -{% endif %} -{% if parameters is defined and parameters is not none %} -{% if parameters.router_id is defined and parameters.router_id is not none %} - ospf6 router-id {{ parameters.router_id }} -{% endif %} -{% endif %} -{% if redistribute is defined and redistribute is not none %} -{% for protocol, options in redistribute.items() %} - redistribute {{ protocol }} {{ 'route-map ' + options.route_map if options.route_map is defined }} -{% endfor %} -{% endif %} -! diff --git a/data/templates/frr/ospfd.frr.j2 b/data/templates/frr/ospfd.frr.j2 new file mode 100644 index 000000000..427fc8be7 --- /dev/null +++ b/data/templates/frr/ospfd.frr.j2 @@ -0,0 +1,189 @@ +! +{% if interface is vyos_defined %} +{% for iface, iface_config in interface.items() %} +interface {{ iface }} +{% if iface_config.authentication.plaintext_password is vyos_defined %} + ip ospf authentication-key {{ iface_config.authentication.plaintext_password }} +{% elif iface_config.authentication.md5 is vyos_defined %} + ip ospf authentication message-digest +{% if iface_config.authentication.md5.key_id is vyos_defined %} +{% for key, key_config in iface_config.authentication.md5.key_id.items() %} + ip ospf message-digest-key {{ key }} md5 {{ key_config.md5_key }} +{% endfor %} +{% endif %} +{% endif %} +{% if iface_config.area is vyos_defined %} + ip ospf area {{ iface_config.area }} +{% endif %} +{% if iface_config.bandwidth is vyos_defined %} + bandwidth {{ iface_config.bandwidth }} +{% endif %} +{% if iface_config.cost is vyos_defined %} + ip ospf cost {{ iface_config.cost }} +{% endif %} +{% if iface_config.priority is vyos_defined %} + ip ospf priority {{ iface_config.priority }} +{% endif %} +{% if iface_config.hello_interval is vyos_defined %} + ip ospf hello-interval {{ iface_config.hello_interval }} +{% endif %} +{% if iface_config.retransmit_interval is vyos_defined %} + ip ospf retransmit-interval {{ iface_config.retransmit_interval }} +{% endif %} +{% if iface_config.transmit_delay is vyos_defined %} + ip ospf transmit-delay {{ iface_config.transmit_delay }} +{% endif %} +{% if iface_config.dead_interval is vyos_defined %} + ip ospf dead-interval {{ iface_config.dead_interval }} +{% elif iface_config.hello_multiplier is vyos_defined %} + ip ospf dead-interval minimal hello-multiplier {{ iface_config.hello_multiplier }} +{% endif %} +{% if iface_config.bfd is vyos_defined %} + ip ospf bfd +{% endif %} +{% if iface_config.bfd.profile is vyos_defined %} + ip ospf bfd profile {{ iface_config.bfd.profile }} +{% endif %} +{% if iface_config.mtu_ignore is vyos_defined %} + ip ospf mtu-ignore +{% endif %} +{% if iface_config.network is vyos_defined %} + ip ospf network {{ iface_config.network }} +{% endif %} +{% if iface_config.passive is vyos_defined %} + {{ 'no ' if iface_config.passive.disable is vyos_defined }}ip ospf passive +{% endif %} +exit +! +{% endfor %} +{% endif %} +! +router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }} +{% if access_list is vyos_defined %} +{% for acl, acl_config in access_list.items() %} +{% for protocol in acl_config.export if acl_config.export is vyos_defined %} + distribute-list {{ acl }} out {{ protocol }} +{% endfor %} +{% endfor %} +{% endif %} +{% if area is vyos_defined %} +{% for area_id, area_config in area.items() %} +{% if area_config.area_type is vyos_defined %} +{% for type, type_config in area_config.area_type.items() if type != 'normal' %} + area {{ area_id }} {{ type }} {{ 'no-summary' if type_config.no_summary is vyos_defined }} +{% if type_config.default_cost is vyos_defined %} + area {{ area_id }} default-cost {{ type_config.default_cost }} +{% endif %} +{% endfor %} +{% endif %} +{% if area_config.authentication is vyos_defined %} + area {{ area_id }} authentication {{ 'message-digest' if area_config.authentication is vyos_defined('md5') }} +{% endif %} +{% for network in area_config.network if area_config.network is vyos_defined %} + network {{ network }} area {{ area_id }} +{% 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 +{% endif %} +{% if range_config.substitute is vyos_defined %} + area {{ area_id }} range {{ range }} substitute {{ range_config.substitute }} +{% endif %} +{% endfor %} +{% endif %} +{% if area_config.export_list is vyos_defined %} + area {{ area_id }} export-list {{ area_config.export_list }} +{% endif %} +{% if area_config.import_list is vyos_defined %} + area {{ area_id }} import-list {{ area_config.import_list }} +{% endif %} +{% if area_config.shortcut is vyos_defined %} + area {{ area_id }} shortcut {{ area_config.shortcut }} +{% endif %} +{% if area_config.virtual_link is vyos_defined %} +{% for link, link_config in area_config.virtual_link.items() %} +{% if link_config.authentication.plaintext_password is vyos_defined %} + area {{ area_id }} virtual-link {{ link }} authentication-key {{ link_config.authentication.plaintext_password }} +{% elif link_config.authentication.md5.key_id is vyos_defined %} +{% for key, key_config in link_config.authentication.md5.key_id.items() %} + area {{ area_id }} virtual-link {{ link }} message-digest-key {{ key }} md5 {{ key_config.md5_key }} +{% endfor %} +{% endif %} +{# The following values are default values #} + area {{ area_id }} virtual-link {{ link }} hello-interval {{ link_config.hello_interval }} retransmit-interval {{ link_config.retransmit_interval }} transmit-delay {{ link_config.transmit_delay }} dead-interval {{ link_config.dead_interval }} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +{% if auto_cost.reference_bandwidth is vyos_defined %} + auto-cost reference-bandwidth {{ auto_cost.reference_bandwidth }} +{% endif %} +{% if default_information.originate is vyos_defined %} + default-information originate {{ 'always' if default_information.originate.always is vyos_defined }} {{ 'metric ' + default_information.originate.metric if default_information.originate.metric is vyos_defined }} {{ 'metric-type ' + default_information.originate.metric_type if default_information.originate.metric_type is vyos_defined }} {{ 'route-map ' + default_information.originate.route_map if default_information.originate.route_map is vyos_defined }} +{% endif %} +{% if default_metric is vyos_defined %} + default-metric {{ default_metric }} +{% endif %} +{% if maximum_paths is vyos_defined %} + maximum-paths {{ maximum_paths }} +{% endif %} +{% if distance.global is vyos_defined %} + distance {{ distance.global }} +{% endif %} +{% if distance.ospf is vyos_defined %} + distance ospf {{ 'intra-area ' + distance.ospf.intra_area if distance.ospf.intra_area is vyos_defined }} {{ 'inter-area ' + distance.ospf.inter_area if distance.ospf.inter_area is vyos_defined }} {{ 'external ' + distance.ospf.external if distance.ospf.external is vyos_defined }} +{% endif %} +{% if log_adjacency_changes is vyos_defined %} + log-adjacency-changes {{ "detail" if log_adjacency_changes.detail is vyos_defined }} +{% endif %} +{% if max_metric.router_lsa.administrative is vyos_defined %} + max-metric router-lsa administrative +{% endif %} +{% if max_metric.router_lsa.on_shutdown is vyos_defined %} + max-metric router-lsa on-shutdown {{ max_metric.router_lsa.on_shutdown }} +{% endif %} +{% if max_metric.router_lsa.on_startup is vyos_defined %} + max-metric router-lsa on-startup {{ max_metric.router_lsa.on_startup }} +{% endif %} +{% if mpls_te.enable is vyos_defined %} + mpls-te on + mpls-te router-address {{ mpls_te.router_address }} +{% endif %} +{% if neighbor is vyos_defined %} +{% for address, address_config in neighbor.items() %} + neighbor {{ address }} {{ 'priority ' + address_config.priority if address_config.priority is vyos_defined }} {{ 'poll-interval ' + address_config.poll_interval if address_config.poll_interval is vyos_defined }} +{% endfor %} +{% endif %} +{% if parameters.abr_type is vyos_defined %} + ospf abr-type {{ parameters.abr_type }} +{% endif %} +{% if parameters.router_id is vyos_defined %} + ospf router-id {{ parameters.router_id }} +{% endif %} +{% if passive_interface.default is vyos_defined %} + passive-interface default +{% endif %} +{% if redistribute is vyos_defined %} +{% for protocol, protocols_options in redistribute.items() %} +{% if protocol == 'table' %} +{% for table, table_options in protocols_options.items() %} + redistribute {{ protocol }} {{ table }} {{ 'metric ' + table_options.metric if table_options.metric is vyos_defined }} {{ 'metric-type ' + table_options.metric_type if table_options.metric_type is vyos_defined }} {{ 'route-map ' + table_options.route_map if table_options.route_map is vyos_defined }} +{% endfor %} +{% else %} + redistribute {{ protocol }} {{ 'metric ' + protocols_options.metric if protocols_options.metric is vyos_defined }} {{ 'metric-type ' + protocols_options.metric_type if protocols_options.metric_type is vyos_defined }} {{ 'route-map ' + protocols_options.route_map if protocols_options.route_map is vyos_defined }} +{% endif %} +{% endfor %} +{% endif %} +{% if refresh.timers is vyos_defined %} + refresh timer {{ refresh.timers }} +{% endif %} +{% if timers.throttle.spf.delay is vyos_defined and timers.throttle.spf.initial_holdtime is vyos_defined and timers.throttle.spf.max_holdtime is vyos_defined %} +{# Timer values have default values #} + timers throttle spf {{ timers.throttle.spf.delay }} {{ timers.throttle.spf.initial_holdtime }} {{ timers.throttle.spf.max_holdtime }} +{% endif %} +exit +! diff --git a/data/templates/frr/ospfd.frr.tmpl b/data/templates/frr/ospfd.frr.tmpl deleted file mode 100644 index 90a6bbd56..000000000 --- a/data/templates/frr/ospfd.frr.tmpl +++ /dev/null @@ -1,192 +0,0 @@ -! -{% if interface is defined and interface is not none %} -{% for iface, iface_config in interface.items() %} -interface {{ iface }} {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} -{% if iface_config.authentication is defined and iface_config.authentication is not none %} -{% if iface_config.authentication.plaintext_password is defined and iface_config.authentication.plaintext_password is not none %} - ip ospf authentication-key {{ iface_config.authentication.plaintext_password }} -{% elif iface_config.authentication.md5 is defined %} - ip ospf authentication message-digest -{% if iface_config.authentication.md5.key_id is defined and iface_config.authentication.md5.key_id is not none %} -{% for key, key_config in iface_config.authentication.md5.key_id.items() %} - ip ospf message-digest-key {{ key }} md5 {{ key_config.md5_key }} -{% endfor %} -{% endif %} -{% endif %} -{% endif %} -{% if iface_config.area is defined and iface_config.area is not none %} - ip ospf area {{ iface_config.area }} -{% endif %} -{% if iface_config.bandwidth is defined and iface_config.bandwidth is not none %} - bandwidth {{ iface_config.bandwidth }} -{% endif %} -{% if iface_config.cost is defined and iface_config.cost is not none %} - ip ospf cost {{ iface_config.cost }} -{% endif %} -{% if iface_config.priority is defined and iface_config.priority is not none %} - ip ospf priority {{ iface_config.priority }} -{% endif %} -{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %} - ip ospf hello-interval {{ iface_config.hello_interval }} -{% endif %} -{% if iface_config.retransmit_interval is defined and iface_config.retransmit_interval is not none %} - ip ospf retransmit-interval {{ iface_config.retransmit_interval }} -{% endif %} -{% if iface_config.transmit_delay is defined and iface_config.transmit_delay is not none %} - ip ospf transmit-delay {{ iface_config.transmit_delay }} -{% endif %} -{% if iface_config.dead_interval is defined and iface_config.dead_interval is not none %} - ip ospf dead-interval {{ iface_config.dead_interval }} -{% elif iface_config.hello_multiplier is defined and iface_config.hello_multiplier is not none %} - ip ospf dead-interval minimal hello-multiplier {{ iface_config.hello_multiplier }} -{% endif %} -{% if iface_config.bfd is defined %} - ip ospf bfd -{% endif %} -{% if iface_config.mtu_ignore is defined %} - ip ospf mtu-ignore -{% endif %} -{% if iface_config.network is defined and iface_config.network is not none %} - ip ospf network {{ iface_config.network }} -{% endif %} -! -{% endfor %} -{% endif %} -! -router ospf {{ 'vrf ' + vrf if vrf is defined and vrf is not none }} -{% if access_list is defined and access_list is not none %} -{% for acl, acl_config in access_list.items() %} -{% for protocol in acl_config.export if acl_config.export is defined %} - distribute-list {{ acl }} out {{ protocol }} -{% endfor %} -{% endfor %} -{% endif %} -{% if area is defined and area is not none %} -{% for area_id, area_config in area.items() %} -{% if area_config.area_type is defined and area_config.area_type is not none %} -{% for type, type_config in area_config.area_type.items() if type != 'normal' %} - area {{ area_id }} {{ type }} {{ 'no-summary' if type_config.no_summary is defined }} -{% if type_config.default_cost is defined and type_config.default_cost is not none %} - area {{ area_id }} default-cost {{ type_config.default_cost }} -{% endif %} -{% endfor %} -{% endif %} -{% if area_config.authentication is defined and area_config.authentication is not none %} - area {{ area_id }} authentication {{ 'message-digest' if area_config.authentication == 'md5' }} -{% endif %} -{% for network in area_config.network if area_config.network is defined %} - network {{ network }} area {{ area_id }} -{% endfor %} -{% if area_config.range is defined and area_config.range is not none %} -{% for range, range_config in area_config.range.items() %} -{% if range_config.cost is defined and range_config.cost is not none %} - area {{ area_id }} range {{ range }} cost {{ range_config.cost }} -{% endif %} -{% if range_config.not_advertise is defined %} - area {{ area_id }} range {{ range }} not-advertise -{% endif %} -{% if range_config.substitute is defined and range_config.substitute is not none %} - area {{ area_id }} range {{ range }} substitute {{ range_config.substitute }} -{% endif %} -{% endfor %} -{% endif %} -{% if area_config.shortcut is defined and area_config.shortcut is not none %} - area {{ area_id }} shortcut {{ area_config.shortcut }} -{% endif %} -{% if area_config.virtual_link is defined and area_config.virtual_link is not none %} -{% for link, link_config in area_config.virtual_link.items() %} -{% if link_config.authentication is defined and link_config.authentication is not none %} -{% if link_config.authentication.plaintext_password is defined and link_config.authentication.plaintext_password is not none %} - area {{ area_id }} virtual-link {{ link }} authentication-key {{ link_config.authentication.plaintext_password }} -{% elif link_config.authentication.md5 is defined and link_config.authentication.md5.key_id is defined and link_config.authentication.md5.key_id is not none %} -{% for key, key_config in link_config.authentication.md5.key_id.items() %} - area {{ area_id }} virtual-link {{ link }} message-digest-key {{ key }} md5 {{ key_config.md5_key }} -{% endfor %} -{% endif %} -{% endif %} -{# The following values are default values #} - area {{ area_id }} virtual-link {{ link }} hello-interval {{ link_config.hello_interval }} retransmit-interval {{ link_config.retransmit_interval }} transmit-delay {{ link_config.transmit_delay }} dead-interval {{ link_config.dead_interval }} -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -{% if auto_cost is defined and auto_cost.reference_bandwidth is defined and auto_cost.reference_bandwidth is not none %} - auto-cost reference-bandwidth {{ auto_cost.reference_bandwidth }} -{% endif %} -{% if default_information is defined and default_information.originate is defined and default_information.originate is not none %} - default-information originate {{ 'always' if default_information.originate.always is defined }} {{ 'metric ' + default_information.originate.metric if default_information.originate.metric is defined }} {{ 'metric-type ' + default_information.originate.metric_type if default_information.originate.metric_type is defined }} {{ 'route-map ' + default_information.originate.route_map if default_information.originate.route_map is defined }} -{% endif %} -{% if default_metric is defined and default_metric is not none %} - default-metric {{ default_metric }} -{% endif %} -{% if distance is defined and distance is not none %} -{% if distance.global is defined and distance.global is not none %} - distance {{ distance.global }} -{% endif %} -{% if distance.ospf is defined and distance.ospf is not none %} - distance ospf {{ 'intra-area ' + distance.ospf.intra_area if distance.ospf.intra_area is defined }} {{ 'inter-area ' + distance.ospf.inter_area if distance.ospf.inter_area is defined }} {{ 'external ' + distance.ospf.external if distance.ospf.external is defined }} -{% endif %} -{% endif %} -{% if log_adjacency_changes is defined %} - log-adjacency-changes {{ "detail" if log_adjacency_changes.detail is defined }} -{% endif %} -{% if max_metric is defined and max_metric.router_lsa is defined and max_metric.router_lsa is not none %} -{% if max_metric.router_lsa.administrative is defined %} - max-metric router-lsa administrative -{% endif %} -{% if max_metric.router_lsa.on_shutdown is defined and max_metric.router_lsa.on_shutdown is not none %} - max-metric router-lsa on-shutdown {{ max_metric.router_lsa.on_shutdown }} -{% endif %} -{% if max_metric.router_lsa.on_startup is defined and max_metric.router_lsa.on_startup is not none %} - max-metric router-lsa on-startup {{ max_metric.router_lsa.on_startup }} -{% endif %} -{% endif %} -{% if mpls_te is defined and mpls_te.enable is defined %} - mpls-te on - mpls-te router-address {{ mpls_te.router_address }} -{% endif %} -{% if neighbor is defined and neighbor is not none%} -{% for address, address_config in neighbor.items() %} - neighbor {{ address }} {{ 'priority ' + address_config.priority if address_config.priority is defined }} {{ 'poll-interval ' + address_config.poll_interval if address_config.poll_interval is defined }} -{% endfor %} -{% endif %} -{% if parameters is defined and parameters is not none %} -{% if parameters.abr_type is defined and parameters.abr_type is not none %} - ospf abr-type {{ parameters.abr_type }} -{% endif %} -{% if parameters.router_id is defined and parameters.router_id is not none %} - ospf router-id {{ parameters.router_id }} -{% endif %} -{% endif %} -{% if passive_interface is defined and passive_interface is not none %} -{% for interface in passive_interface %} - passive-interface {{ interface }} -{% endfor %} -{% endif %} -{% if passive_interface_exclude is defined and passive_interface_exclude is not none %} -{% for interface in passive_interface_exclude if passive_interface_exclude is defined %} -{% if interface.startswith('vlink') %} -{% set interface = interface.upper() %} -{% endif %} - no passive-interface {{ interface }} -{% endfor %} -{% endif %} -{% if redistribute is defined and redistribute is not none %} -{% for protocol, protocols_options in redistribute.items() %} -{% if protocol == 'table' %} -{% for table, table_options in protocols_options.items() %} - redistribute {{ protocol }} {{ table }} {{ 'metric ' + table_options.metric if table_options.metric is defined }} {{ 'metric-type ' + table_options.metric_type if table_options.metric_type is defined }} {{ 'route-map ' + table_options.route_map if table_options.route_map is defined }} -{% endfor %} -{% else %} - redistribute {{ protocol }} {{ 'metric ' + protocols_options.metric if protocols_options.metric is defined }} {{ 'metric-type ' + protocols_options.metric_type if protocols_options.metric_type is defined }} {{ 'route-map ' + protocols_options.route_map if protocols_options.route_map is defined }} -{% endif %} -{% endfor %} -{% endif %} -{% if refresh is defined and refresh.timers is defined and refresh.timers is not none %} - refresh timer {{ refresh.timers }} -{% endif %} -{% if timers is defined and timers.throttle is defined and timers.throttle.spf is defined and timers.throttle.spf is not none %} -{# Timer values have default values #} - timers throttle spf {{ timers.throttle.spf.delay }} {{ timers.throttle.spf.initial_holdtime }} {{ timers.throttle.spf.max_holdtime }} -{% endif %} -! diff --git a/data/templates/frr/pimd.frr.tmpl b/data/templates/frr/pimd.frr.j2 index a5b56223a..cb2f2aa98 100644 --- a/data/templates/frr/pimd.frr.tmpl +++ b/data/templates/frr/pimd.frr.j2 @@ -1,8 +1,8 @@ ! {% for rp_addr in old_pim.rp %} -{% for group in old_pim.rp[rp_addr] %} +{% for group in old_pim.rp[rp_addr] %} no ip pim rp {{ rp_addr }} {{ group }} -{% endfor %} +{% endfor %} {% endfor %} {% if old_pim.rp_keep_alive %} no ip pim rp keep-alive-timer {{ old_pim.rp_keep_alive }} @@ -15,18 +15,18 @@ no ip pim {% for iface in pim.ifaces %} interface {{ iface }} ip pim -{% if pim.ifaces[iface].dr_prio %} +{% if pim.ifaces[iface].dr_prio %} ip pim drpriority {{ pim.ifaces[iface].dr_prio }} -{% endif %} -{% if pim.ifaces[iface].hello %} +{% endif %} +{% if pim.ifaces[iface].hello %} ip pim hello {{ pim.ifaces[iface].hello }} -{% endif %} +{% endif %} ! {% endfor %} {% for rp_addr in pim.rp %} -{% for group in pim.rp[rp_addr] %} +{% for group in pim.rp[rp_addr] %} ip pim rp {{ rp_addr }} {{ group }} -{% endfor %} +{% endfor %} {% endfor %} {% if pim.rp_keep_alive %} ip pim rp keep-alive-timer {{ pim.rp_keep_alive }} diff --git a/data/templates/frr/policy.frr.j2 b/data/templates/frr/policy.frr.j2 new file mode 100644 index 000000000..a42b73e98 --- /dev/null +++ b/data/templates/frr/policy.frr.j2 @@ -0,0 +1,331 @@ +{% if access_list is vyos_defined %} +{% for acl, acl_config in access_list.items() | natural_sort %} +{% if acl_config.description is vyos_defined %} +access-list {{ acl }} remark {{ acl_config.description }} +{% endif %} +{% if acl_config.rule is vyos_defined %} +{% for rule, rule_config in acl_config.rule.items() | natural_sort %} +{% set ip = '' %} +{% set src = '' %} +{% set src_mask = '' %} +{% if rule_config.source.any is vyos_defined %} +{% set src = 'any' %} +{% elif rule_config.source.host is vyos_defined %} +{% set src = 'host ' ~ rule_config.source.host %} +{% elif rule_config.source.network is vyos_defined %} +{% set src = rule_config.source.network %} +{% set src_mask = rule_config.source.inverse_mask %} +{% endif %} +{% set dst = '' %} +{% set dst_mask = '' %} +{% if (acl | int >= 100 and acl | int <= 199) or (acl | int >= 2000 and acl | int <= 2699) %} +{% set ip = 'ip' %} +{% set dst = 'any' %} +{% if rule_config.destination.any is vyos_defined %} +{% set dst = 'any' %} +{% elif rule_config.destination.host is vyos_defined %} +{% set dst = 'host ' ~ rule_config.destination.host %} +{% elif rule_config.destination.network is vyos_defined %} +{% set dst = rule_config.destination.network %} +{% set dst_mask = rule_config.destination.inverse_mask %} +{% endif %} +{% endif %} +access-list {{ acl }} seq {{ rule }} {{ rule_config.action }} {{ ip }} {{ src }} {{ src_mask }} {{ dst }} {{ dst_mask }} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +! +{% if access_list6 is vyos_defined %} +{% for acl, acl_config in access_list6.items() | natural_sort %} +{% if acl_config.description is vyos_defined %} +ipv6 access-list {{ acl }} remark {{ acl_config.description }} +{% endif %} +{% if acl_config.rule is vyos_defined %} +{% for rule, rule_config in acl_config.rule.items() | natural_sort %} +{% set src = '' %} +{% if rule_config.source.any is vyos_defined %} +{% set src = 'any' %} +{% elif rule_config.source.network is vyos_defined %} +{% set src = rule_config.source.network %} +{% endif %} +ipv6 access-list {{ acl }} seq {{ rule }} {{ rule_config.action }} {{ src }} {{ 'exact-match' if rule_config.source.exact_match is vyos_defined }} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +! +{% if as_path_list is vyos_defined %} +{% for acl, acl_config in as_path_list.items() | natural_sort %} +{% if acl_config.rule is vyos_defined %} +{% for rule, rule_config in acl_config.rule.items() | natural_sort %} +bgp as-path access-list {{ acl }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +! +{% if community_list is vyos_defined %} +{% for list, list_config in community_list.items() | natural_sort %} +{% if list_config.rule is vyos_defined %} +{% for rule, rule_config in list_config.rule.items() | natural_sort %} +{# by default, if casting to int fails it returns 0 #} +{% if list | int != 0 %} +bgp community-list {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} +{% else %} +bgp community-list expanded {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} +{% endif %} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +! +{% if extcommunity_list is vyos_defined %} +{% for list, list_config in extcommunity_list.items() | natural_sort %} +{% if list_config.rule is vyos_defined %} +{% for rule, rule_config in list_config.rule.items() | natural_sort %} +{# by default, if casting to int fails it returns 0 #} +{% if list | int != 0 %} +bgp extcommunity-list {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} +{% else %} +bgp extcommunity-list expanded {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} +{% endif %} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +! +{% if large_community_list is vyos_defined %} +{% for list, list_config in large_community_list.items() | natural_sort %} +{% if list_config.rule is vyos_defined %} +{% for rule, rule_config in list_config.rule.items() | natural_sort %} +{# by default, if casting to int fails it returns 0 #} +{% if list | int != 0 %} +bgp large-community-list {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} +{% else %} +bgp large-community-list expanded {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} +{% endif %} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +! +{% if prefix_list is vyos_defined %} +{% for prefix_list, prefix_list_config in prefix_list.items() | natural_sort %} +{% if prefix_list_config.description is vyos_defined %} +ip prefix-list {{ prefix_list }} description {{ prefix_list_config.description }} +{% endif %} +{% if prefix_list_config.rule is vyos_defined %} +{% for rule, rule_config in prefix_list_config.rule.items() | natural_sort %} +{% if rule_config.prefix is vyos_defined %} +ip prefix-list {{ prefix_list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.prefix }} {{ 'ge ' ~ rule_config.ge if rule_config.ge is vyos_defined }} {{ 'le ' ~ rule_config.le if rule_config.le is vyos_defined }} +{% endif %} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +! +{% if prefix_list6 is vyos_defined %} +{% for prefix_list, prefix_list_config in prefix_list6.items() | natural_sort %} +{% if prefix_list_config.description is vyos_defined %} +ipv6 prefix-list {{ prefix_list }} description {{ prefix_list_config.description }} +{% endif %} +{% if prefix_list_config.rule is vyos_defined %} +{% for rule, rule_config in prefix_list_config.rule.items() | natural_sort %} +{% if rule_config.prefix is vyos_defined %} +ipv6 prefix-list {{ prefix_list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.prefix }} {{ 'ge ' ~ rule_config.ge if rule_config.ge is vyos_defined }} {{ 'le ' ~ rule_config.le if rule_config.le is vyos_defined }} +{% endif %} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +! +{% if route_map is vyos_defined %} +{% for route_map, route_map_config in route_map.items() | natural_sort %} +{% if route_map_config.rule is vyos_defined %} +{% for rule, rule_config in route_map_config.rule.items() | natural_sort %} +route-map {{ route_map }} {{ rule_config.action }} {{ rule }} +{% if rule_config.call is vyos_defined %} + call {{ rule_config.call }} +{% endif %} +{% if rule_config.continue is vyos_defined %} + on-match goto {{ rule_config.continue }} +{% endif %} +{% if rule_config.description is vyos_defined %} + description {{ rule_config.description }} +{% endif %} +{% if rule_config.match is vyos_defined %} +{% if rule_config.match.as_path is vyos_defined %} + match as-path {{ rule_config.match.as_path }} +{% endif %} +{% if rule_config.match.community.community_list is vyos_defined %} + match community {{ rule_config.match.community.community_list }} {{ 'exact-match' if rule_config.match.community.exact_match is vyos_defined }} +{% endif %} +{% if rule_config.match.extcommunity is vyos_defined %} + match extcommunity {{ rule_config.match.extcommunity }} +{% endif %} +{% if rule_config.match.evpn.default_route is vyos_defined %} + match evpn default-route +{% endif %} +{% if rule_config.match.evpn.rd is vyos_defined %} + match evpn rd {{ rule_config.match.evpn.rd }} +{% endif %} +{% if rule_config.match.evpn.route_type is vyos_defined %} + match evpn route-type {{ rule_config.match.evpn.route_type }} +{% endif %} +{% if rule_config.match.evpn.vni is vyos_defined %} + match evpn vni {{ rule_config.match.evpn.vni }} +{% endif %} +{% if rule_config.match.interface is vyos_defined %} + match interface {{ rule_config.match.interface }} +{% endif %} +{% if rule_config.match.ip.address.access_list is vyos_defined %} + match ip address {{ rule_config.match.ip.address.access_list }} +{% endif %} +{% if rule_config.match.ip.address.prefix_list is vyos_defined %} + match ip address prefix-list {{ rule_config.match.ip.address.prefix_list }} +{% endif %} +{% if rule_config.match.ip.nexthop.access_list is vyos_defined %} + match ip next-hop {{ rule_config.match.ip.nexthop.access_list }} +{% endif %} +{% if rule_config.match.ip.nexthop.prefix_list is vyos_defined %} + match ip next-hop prefix-list {{ rule_config.match.ip.nexthop.prefix_list }} +{% endif %} +{% if rule_config.match.ip.route_source.access_list is vyos_defined %} + match ip route-source {{ rule_config.match.ip.route_source.access_list }} +{% endif %} +{% if rule_config.match.ip.route_source.prefix_list is vyos_defined %} + match ip route-source prefix-list {{ rule_config.match.ip.route_source.prefix_list }} +{% endif %} +{% if rule_config.match.ipv6.address.access_list is vyos_defined %} + match ipv6 address {{ rule_config.match.ipv6.address.access_list }} +{% endif %} +{% if rule_config.match.ipv6.address.prefix_list is vyos_defined %} + match ipv6 address prefix-list {{ rule_config.match.ipv6.address.prefix_list }} +{% endif %} +{% if rule_config.match.ipv6.nexthop is vyos_defined %} + match ipv6 next-hop address {{ rule_config.match.ipv6.nexthop }} +{% endif %} +{% if rule_config.match.large_community.large_community_list is vyos_defined %} + match large-community {{ rule_config.match.large_community.large_community_list }} +{% endif %} +{% if rule_config.match.local_preference is vyos_defined %} + match local-preference {{ rule_config.match.local_preference }} +{% endif %} +{% if rule_config.match.metric is vyos_defined %} + match metric {{ rule_config.match.metric }} +{% endif %} +{% if rule_config.match.origin is vyos_defined %} + match origin {{ rule_config.match.origin }} +{% endif %} +{% if rule_config.match.peer is vyos_defined %} + match peer {{ rule_config.match.peer }} +{% endif %} +{% if rule_config.match.rpki is vyos_defined %} + match rpki {{ rule_config.match.rpki }} +{% endif %} +{% if rule_config.match.tag is vyos_defined %} + match tag {{ rule_config.match.tag }} +{% endif %} +{% endif %} +{% if rule_config.on_match.next is vyos_defined %} + on-match next +{% endif %} +{% if rule_config.on_match.goto is vyos_defined %} + on-match goto {{ rule_config.on_match.goto }} +{% endif %} +{% if rule_config.set is vyos_defined %} +{% if rule_config.set.aggregator.as is vyos_defined and rule_config.set.aggregator.ip is vyos_defined %} + set aggregator as {{ rule_config.set.aggregator.as }} {{ rule_config.set.aggregator.ip }} +{% endif %} +{% if rule_config.set.as_path.exclude is vyos_defined %} + set as-path exclude {{ rule_config.set.as_path.exclude }} +{% endif %} +{% if rule_config.set.as_path.prepend is vyos_defined %} + set as-path prepend {{ rule_config.set.as_path.prepend }} +{% endif %} +{% if rule_config.set.as_path.prepend_last_as is vyos_defined %} + set as-path prepend last-as {{ rule_config.set.as_path.prepend_last_as }} +{% endif %} +{% if rule_config.set.atomic_aggregate is vyos_defined %} + set atomic-aggregate +{% endif %} +{% if rule_config.set.comm_list.comm_list is vyos_defined %} + set comm-list {{ rule_config.set.comm_list.comm_list }} {{ 'delete' if rule_config.set.comm_list.delete is vyos_defined }} +{% endif %} +{% if rule_config.set.community is vyos_defined %} + set community {{ rule_config.set.community }} +{% endif %} +{% if rule_config.set.distance is vyos_defined %} + set distance {{ rule_config.set.distance }} +{% endif %} +{% if rule_config.set.evpn.gateway.ipv4 is vyos_defined %} + set evpn gateway-ip ipv4 {{ rule_config.set.evpn.gateway.ipv4 }} +{% endif %} +{% if rule_config.set.evpn.gateway.ipv6 is vyos_defined %} + set evpn gateway-ip ipv6 {{ rule_config.set.evpn.gateway.ipv6 }} +{% endif %} +{% if rule_config.set.extcommunity.bandwidth is vyos_defined %} + set extcommunity bandwidth {{ rule_config.set.extcommunity.bandwidth }} +{% endif %} +{% if rule_config.set.extcommunity.rt is vyos_defined %} + set extcommunity rt {{ rule_config.set.extcommunity.rt }} +{% endif %} +{% if rule_config.set.extcommunity.soo is vyos_defined %} + set extcommunity soo {{ rule_config.set.extcommunity.soo }} +{% endif %} +{% if rule_config.set.ip_next_hop is vyos_defined %} + set ip next-hop {{ rule_config.set.ip_next_hop }} +{% endif %} +{% if rule_config.set.ipv6_next_hop.global is vyos_defined %} + set ipv6 next-hop global {{ rule_config.set.ipv6_next_hop.global }} +{% endif %} +{% if rule_config.set.ipv6_next_hop.local is vyos_defined %} + set ipv6 next-hop local {{ rule_config.set.ipv6_next_hop.local }} +{% endif %} +{% if rule_config.set.ipv6_next_hop.peer_address is vyos_defined %} + set ipv6 next-hop peer-address +{% endif %} +{% if rule_config.set.ipv6_next_hop.prefer_global is vyos_defined %} + set ipv6 next-hop prefer-global +{% endif %} +{% if rule_config.set.large_community is vyos_defined %} + set large-community {{ rule_config.set.large_community }} +{% endif %} +{% if rule_config.set.large_comm_list_delete is vyos_defined %} + set large-comm-list {{ rule_config.set.large_comm_list_delete }} delete +{% endif %} +{% if rule_config.set.local_preference is vyos_defined %} + set local-preference {{ rule_config.set.local_preference }} +{% endif %} +{% if rule_config.set.metric is vyos_defined %} + set metric {{ rule_config.set.metric }} +{% endif %} +{% if rule_config.set.metric_type is vyos_defined %} + set metric-type {{ rule_config.set.metric_type }} +{% endif %} +{% if rule_config.set.origin is vyos_defined %} + set origin {{ rule_config.set.origin }} +{% endif %} +{% if rule_config.set.originator_id is vyos_defined %} + set originator-id {{ rule_config.set.originator_id }} +{% endif %} +{% if rule_config.set.src is vyos_defined %} + set src {{ rule_config.set.src }} +{% endif %} +{% if rule_config.set.table is vyos_defined %} + set table {{ rule_config.set.table }} +{% endif %} +{% if rule_config.set.tag is vyos_defined %} + set tag {{ rule_config.set.tag }} +{% endif %} +{% if rule_config.set.weight is vyos_defined %} + set weight {{ rule_config.set.weight }} +{% endif %} +{% endif %} +exit +! +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} diff --git a/data/templates/frr/policy.frr.tmpl b/data/templates/frr/policy.frr.tmpl deleted file mode 100644 index 51adc1902..000000000 --- a/data/templates/frr/policy.frr.tmpl +++ /dev/null @@ -1,322 +0,0 @@ -! -{% if access_list is defined and access_list is not none %} -{% for acl, acl_config in access_list.items() | natural_sort %} -{% if acl_config.description is defined and acl_config.description is not none %} -access-list {{ acl }} remark {{ acl_config.description }} -{% endif %} -{% if acl_config.rule is defined and acl_config.rule is not none %} -{% for rule, rule_config in acl_config.rule.items() | natural_sort %} -{% set ip = '' %} -{% set src = '' %} -{% set src_mask = '' %} -{% if rule_config.source is defined and rule_config.source.any is defined %} -{% set src = 'any' %} -{% elif rule_config.source is defined and rule_config.source.host is defined and rule_config.source.host is not none %} -{% set src = 'host ' + rule_config.source.host %} -{% elif rule_config.source is defined and rule_config.source.network is defined and rule_config.source.network is not none %} -{% set src = rule_config.source.network %} -{% set src_mask = rule_config.source.inverse_mask %} -{% endif %} -{% set dst = '' %} -{% set dst_mask = '' %} -{% if (acl|int >= 100 and acl|int <= 199) or (acl|int >= 2000 and acl|int <= 2699) %} -{% set ip = 'ip' %} -{% set dst = 'any' %} -{% if rule_config.destination is defined and rule_config.destination.any is defined %} -{% set dst = 'any' %} -{% elif rule_config.destination is defined and rule_config.destination.host is defined and rule_config.destination.host is not none %} -{% set dst = 'host ' + rule_config.destination.host %} -{% elif rule_config.destination is defined and rule_config.destination.network is defined and rule_config.destination.network is not none %} -{% set dst = rule_config.destination.network %} -{% set dst_mask = rule_config.destination.inverse_mask %} -{% endif %} -{% endif %} -access-list {{ acl }} seq {{ rule }} {{ rule_config.action }} {{ ip }} {{ src }} {{ src_mask }} {{ dst }} {{ dst_mask }} -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -! -{% if access_list6 is defined and access_list6 is not none %} -{% for acl, acl_config in access_list6.items() | natural_sort %} -{% if acl_config.description is defined and acl_config.description is not none %} -ipv6 access-list {{ acl }} remark {{ acl_config.description }} -{% endif %} -{% if acl_config.rule is defined and acl_config.rule is not none %} -{% for rule, rule_config in acl_config.rule.items() | natural_sort %} -{% set src = '' %} -{% if rule_config.source is defined and rule_config.source.any is defined %} -{% set src = 'any' %} -{% elif rule_config.source is defined and rule_config.source.network is defined and rule_config.source.network is not none %} -{% set src = rule_config.source.network %} -{% endif %} -ipv6 access-list {{ acl }} seq {{ rule }} {{ rule_config.action }} {{ src }} {{ 'exact-match' if rule_config.source.exact_match is defined }} -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -! -{% if as_path_list is defined and as_path_list is not none %} -{% for acl, acl_config in as_path_list.items() | natural_sort %} -{% if acl_config.rule is defined and acl_config.rule is not none %} -{% for rule, rule_config in acl_config.rule.items() | natural_sort %} -bgp as-path access-list {{ acl }} {{ rule_config.action }} {{ rule_config.regex }} -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -! -{% if community_list is defined and community_list is not none %} -{% for list, list_config in community_list.items() | natural_sort %} -{% if list_config.rule is defined and list_config.rule is not none %} -{% for rule, rule_config in list_config.rule.items() | natural_sort %} -{# by default, if casting to int fails it returns 0 #} -{% if list|int != 0 %} -bgp community-list {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} -{% else %} -bgp community-list expanded {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} -{% endif %} -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -! -{% if extcommunity_list is defined and extcommunity_list is not none %} -{% for list, list_config in extcommunity_list.items() | natural_sort %} -{% if list_config.rule is defined and list_config.rule is not none %} -{% for rule, rule_config in list_config.rule.items() | natural_sort %} -{# by default, if casting to int fails it returns 0 #} -{% if list|int != 0 %} -bgp extcommunity-list {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} -{% else %} -bgp extcommunity-list expanded {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} -{% endif %} -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -! -{% if large_community_list is defined and large_community_list is not none %} -{% for list, list_config in large_community_list.items() | natural_sort %} -{% if list_config.rule is defined and list_config.rule is not none %} -{% for rule, rule_config in list_config.rule.items() | natural_sort %} -{# by default, if casting to int fails it returns 0 #} -{% if list|int != 0 %} -bgp large-community-list {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} -{% else %} -bgp large-community-list expanded {{ list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.regex }} -{% endif %} -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -! -{% if prefix_list is defined and prefix_list is not none %} -{% for prefix_list, prefix_list_config in prefix_list.items() | natural_sort %} -{% if prefix_list_config.description is defined and prefix_list_config.description is not none %} -ip prefix-list {{ prefix_list }} description {{ prefix_list_config.description }} -{% endif %} -{% if prefix_list_config.rule is defined and prefix_list_config.rule is not none %} -{% for rule, rule_config in prefix_list_config.rule.items() | natural_sort %} -{% if rule_config.prefix is defined and rule_config.prefix is not none %} -ip prefix-list {{ prefix_list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.prefix }} {{ 'ge ' + rule_config.ge if rule_config.ge is defined }} {{ 'le ' + rule_config.le if rule_config.le is defined }} -{% endif %} -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -! -{% if prefix_list6 is defined and prefix_list6 is not none %} -{% for prefix_list, prefix_list_config in prefix_list6.items() | natural_sort %} -{% if prefix_list_config.description is defined and prefix_list_config.description is not none %} -ipv6 prefix-list {{ prefix_list }} description {{ prefix_list_config.description }} -{% endif %} -{% if prefix_list_config.rule is defined and prefix_list_config.rule is not none %} -{% for rule, rule_config in prefix_list_config.rule.items() | natural_sort %} -{% if rule_config.prefix is defined and rule_config.prefix is not none %} -ipv6 prefix-list {{ prefix_list }} seq {{ rule }} {{ rule_config.action }} {{ rule_config.prefix }} {{ 'ge ' + rule_config.ge if rule_config.ge is defined }} {{ 'le ' + rule_config.le if rule_config.le is defined }} -{% endif %} -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -! -{% if route_map is defined and route_map is not none %} -{% for route_map, route_map_config in route_map.items() | natural_sort %} -{% if route_map_config.rule is defined and route_map_config.rule is not none %} -{% for rule, rule_config in route_map_config.rule.items() | natural_sort %} -route-map {{ route_map }} {{ rule_config.action }} {{ rule }} -{% if rule_config.call is defined and rule_config.call is not none %} - call {{ rule_config.call }} -{% endif %} -{% if rule_config.continue is defined and rule_config.continue is not none %} - on-match goto {{ rule_config.continue }} -{% endif %} -{% if rule_config.description is defined and rule_config.description is not none %} - description {{ rule_config.description }} -{% endif %} -{% if rule_config.match is defined and rule_config.match is not none %} -{% if rule_config.match.as_path is defined and rule_config.match.as_path is not none %} - match as-path {{ rule_config.match.as_path }} -{% endif %} -{% if rule_config.match.community is defined and rule_config.match.community.community_list is defined and rule_config.match.community.community_list is not none %} - match community {{ rule_config.match.community.community_list }} {{ 'exact-match' if rule_config.match.community.exact_match is defined }} -{% endif %} -{% if rule_config.match.extcommunity is defined and rule_config.match.extcommunity is not none %} - match extcommunity {{ rule_config.match.extcommunity }} -{% endif %} -{% if rule_config.match.evpn is defined and rule_config.match.evpn.default_route is defined %} - match evpn default-route -{% endif %} -{% if rule_config.match.evpn is defined and rule_config.match.evpn.rd is defined and rule_config.match.evpn.rd is not none %} - match evpn rd {{ rule_config.match.evpn.rd }} -{% endif %} -{% if rule_config.match.evpn is defined and rule_config.match.evpn.route_type is defined and rule_config.match.evpn.route_type is not none %} - match evpn route-type {{ rule_config.match.evpn.route_type }} -{% endif %} -{% if rule_config.match.evpn is defined and rule_config.match.evpn.vni is defined and rule_config.match.evpn.vni is not none %} - match evpn vni {{ rule_config.match.evpn.vni }} -{% endif %} -{% if rule_config.match.interface is defined and rule_config.match.interface is not none %} - match interface {{ rule_config.match.interface }} -{% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.address is defined and rule_config.match.ip.address.access_list is defined and rule_config.match.ip.address.access_list is not none %} - match ip address {{ rule_config.match.ip.address.access_list }} -{% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.address is defined and rule_config.match.ip.address.prefix_list is defined and rule_config.match.ip.address.prefix_list is not none %} - match ip address prefix-list {{ rule_config.match.ip.address.prefix_list }} -{% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.nexthop is defined and rule_config.match.ip.nexthop.access_list is defined and rule_config.match.ip.nexthop.access_list is not none %} - match ip next-hop {{ rule_config.match.ip.nexthop.access_list }} -{% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.nexthop is defined and rule_config.match.ip.nexthop.prefix_list is defined and rule_config.match.ip.nexthop.prefix_list is not none %} - match ip next-hop prefix-list {{ rule_config.match.ip.nexthop.prefix_list }} -{% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.route_source is defined and rule_config.match.ip.route_source.access_list is defined and rule_config.match.ip.route_source.access_list is not none %} - match ip route-source {{ rule_config.match.ip.route_source.access_list }} -{% endif %} -{% if rule_config.match.ip is defined and rule_config.match.ip.route_source is defined and rule_config.match.ip.route_source.prefix_list is defined and rule_config.match.ip.route_source.prefix_list is not none %} - match ip route-source prefix-list {{ rule_config.match.ip.route_source.prefix_list }} -{% endif %} -{% if rule_config.match.ipv6 is defined and rule_config.match.ipv6.address is defined and rule_config.match.ipv6.address.access_list is defined and rule_config.match.ipv6.address.access_list is not none %} - match ipv6 address {{ rule_config.match.ipv6.address.access_list }} -{% endif %} -{% if rule_config.match.ipv6 is defined and rule_config.match.ipv6.address is defined and rule_config.match.ipv6.address.prefix_list is defined and rule_config.match.ipv6.address.prefix_list is not none %} - match ipv6 address prefix-list {{ rule_config.match.ipv6.address.prefix_list }} -{% endif %} -{% if rule_config.match.ipv6 is defined and rule_config.match.ipv6.nexthop is defined and rule_config.match.ipv6.nexthop is not none %} - match ipv6 next-hop {{ rule_config.match.ipv6.nexthop }} -{% endif %} -{% if rule_config.match.large_community is defined and rule_config.match.large_community.large_community_list is defined and rule_config.match.large_community.large_community_list is not none %} - match large-community {{ rule_config.match.large_community.large_community_list }} -{% endif %} -{% if rule_config.match.local_preference is defined and rule_config.match.local_preference is not none %} - match local-preference {{ rule_config.match.local_preference }} -{% endif %} -{% if rule_config.match.metric is defined and rule_config.match.metric is not none %} - match metric {{ rule_config.match.metric }} -{% endif %} -{% if rule_config.match.origin is defined and rule_config.match.origin is not none %} - match origin {{ rule_config.match.origin }} -{% endif %} -{% if rule_config.match.peer is defined and rule_config.match.peer is not none %} - match peer {{ rule_config.match.peer }} -{% endif %} -{% if rule_config.match.rpki is defined and rule_config.match.rpki is not none %} - match rpki {{ rule_config.match.rpki }} -{% endif %} -{% if rule_config.match.tag is defined and rule_config.match.tag is not none %} - match tag {{ rule_config.match.tag }} -{% endif %} -{% endif %} -{% if rule_config.on_match is defined and rule_config.on_match is not none %} -{% if rule_config.on_match.next is defined %} - on-match next -{% endif %} -{% if rule_config.on_match.goto is defined and rule_config.on_match.goto is not none %} - on-match goto {{ rule_config.on_match.goto }} -{% endif %} -{% endif %} -{% if rule_config.set is defined and rule_config.set is not none %} -{% if rule_config.set.aggregator is defined and rule_config.set.aggregator.as is defined and rule_config.set.aggregator.ip is defined %} - set aggregator as {{ rule_config.set.aggregator.as }} {{ rule_config.set.aggregator.ip }} -{% endif %} -{% if rule_config.set.as_path_exclude is defined and rule_config.set.as_path_exclude is not none %} - set as-path exclude {{ rule_config.set.as_path_exclude }} -{% endif %} -{% if rule_config.set.as_path_prepend is defined and rule_config.set.as_path_prepend is not none %} - set as-path prepend {{ rule_config.set.as_path_prepend }} -{% endif %} -{% if rule_config.set.atomic_aggregate is defined %} - set atomic-aggregate -{% endif %} -{% if rule_config.set.comm_list is defined and rule_config.set.comm_list.comm_list is defined and rule_config.set.comm_list.comm_list is not none %} - set comm-list {{ rule_config.set.comm_list.comm_list }} {{ 'delete' if rule_config.set.comm_list.delete is defined }} -{% endif %} -{% if rule_config.set.community is defined and rule_config.set.community is not none %} - set community {{ rule_config.set.community }} -{% endif %} -{% if rule_config.set.distance is defined and rule_config.set.distance is not none %} - set distance {{ rule_config.set.distance }} -{% endif %} -{% if rule_config.set.extcommunity is defined and rule_config.set.extcommunity.bandwidth is defined and rule_config.set.extcommunity.bandwidth is not none %} - set extcommunity bandwidth {{ rule_config.set.extcommunity.bandwidth }} -{% endif %} -{% if rule_config.set.extcommunity is defined and rule_config.set.extcommunity.rt is defined and rule_config.set.extcommunity.rt is not none %} - set extcommunity rt {{ rule_config.set.extcommunity.rt }} -{% endif %} -{% if rule_config.set.extcommunity is defined and rule_config.set.extcommunity.soo is defined and rule_config.set.extcommunity.soo is not none %} - set extcommunity soo {{ rule_config.set.extcommunity.soo }} -{% endif %} -{% if rule_config.set.ip_next_hop is defined and rule_config.set.ip_next_hop is not none %} - set ip next-hop {{ rule_config.set.ip_next_hop }} -{% endif %} -{% if rule_config.set.ipv6_next_hop is defined and rule_config.set.ipv6_next_hop.global is defined and rule_config.set.ipv6_next_hop.global is not none %} - set ipv6 next-hop global {{ rule_config.set.ipv6_next_hop.global }} -{% endif %} -{% if rule_config.set.ipv6_next_hop is defined and rule_config.set.ipv6_next_hop.local is defined and rule_config.set.ipv6_next_hop.local is not none %} - set ipv6 next-hop local {{ rule_config.set.ipv6_next_hop.local }} -{% endif %} -{% if rule_config.set.ipv6_next_hop is defined and rule_config.set.ipv6_next_hop.prefer_global is defined %} - set ipv6 next-hop prefer-global -{% endif %} -{% if rule_config.set.large_community is defined and rule_config.set.large_community is not none %} - set large-community {{ rule_config.set.large_community }} -{% endif %} -{% if rule_config.set.large_comm_list_delete is defined and rule_config.set.large_comm_list_delete is not none %} - set large-comm-list {{ rule_config.set.large_comm_list_delete }} delete -{% endif %} -{% if rule_config.set.local_preference is defined and rule_config.set.local_preference is not none %} - set local-preference {{ rule_config.set.local_preference }} -{% endif %} -{% if rule_config.set.metric is defined and rule_config.set.metric is not none %} - set metric {{ rule_config.set.metric }} -{% endif %} -{% if rule_config.set.metric_type is defined and rule_config.set.metric_type is not none %} - set metric-type {{ rule_config.set.metric_type }} -{% endif %} -{% if rule_config.set.origin is defined and rule_config.set.origin is not none %} - set origin {{ rule_config.set.origin }} -{% endif %} -{% if rule_config.set.originator_id is defined and rule_config.set.originator_id is not none %} - set originator-id {{ rule_config.set.originator_id }} -{% endif %} -{% if rule_config.set.src is defined and rule_config.set.src is not none %} - set src {{ rule_config.set.src }} -{% endif %} -{% if rule_config.set.table is defined and rule_config.set.table is not none %} - set table {{ rule_config.set.table }} -{% endif %} -{% if rule_config.set.tag is defined and rule_config.set.tag is not none %} - set tag {{ rule_config.set.tag }} -{% endif %} -{% if rule_config.set.weight is defined and rule_config.set.weight is not none %} - set weight {{ rule_config.set.weight }} -{% endif %} -{% endif %} -{% endfor %} -! -{% endif %} -{% endfor %} -{% endif %} -! diff --git a/data/templates/frr/rip_ripng.frr.j2 b/data/templates/frr/rip_ripng.frr.j2 index de180ee6b..dd547bb3e 100644 --- a/data/templates/frr/rip_ripng.frr.j2 +++ b/data/templates/frr/rip_ripng.frr.j2 @@ -1,36 +1,36 @@ -{% if default_information is defined and default_information.originate is defined %} +{% if default_information is vyos_defined %} default-information originate {% endif %} -{% if default_metric is defined and default_metric is not none %} +{% if default_metric is vyos_defined %} default-metric {{ default_metric }} {% endif %} -{% if passive_interface is defined and passive_interface is not none %} -{% for interface in passive_interface %} +{% if passive_interface is vyos_defined %} +{% for interface in passive_interface %} passive-interface {{ interface }} -{% endfor %} +{% endfor %} {% endif %} -{% if network is defined and network is not none %} -{% for prefix in network %} +{% if network is vyos_defined %} +{% for prefix in network %} network {{ prefix }} -{% endfor %} +{% endfor %} {% endif %} -{% if interface is defined and interface is not none %} -{% for ifname in interface %} +{% if interface is vyos_defined %} +{% for ifname in interface %} network {{ ifname }} -{% endfor %} +{% endfor %} {% endif %} -{% if route is defined and route is not none %} -{% for prefix in route %} +{% if route is vyos_defined %} +{% for prefix in route %} route {{ prefix }} -{% endfor %} +{% endfor %} {% endif %} {# timers have default values #} timers basic {{ timers['update'] }} {{ timers.timeout }} {{ timers.garbage_collection }} -{% if redistribute is defined and redistribute is not none %} -{% for protocol, protocol_config in redistribute.items() %} -{% if protocol == 'ospfv3' %} -{% set protocol = 'ospf6' %} -{% endif %} - redistribute {{ protocol }} {{ 'metric ' + protocol_config.metric if protocol_config.metric is defined }} {{ 'route-map ' + protocol_config.route_map if protocol_config.route_map is defined }} -{% endfor %} +{% if redistribute is vyos_defined %} +{% for protocol, protocol_config in redistribute.items() %} +{% if protocol is vyos_defined('ospfv3') %} +{% set protocol = 'ospf6' %} +{% endif %} + redistribute {{ protocol }} {{ 'metric ' ~ protocol_config.metric if protocol_config.metric is vyos_defined }} {{ 'route-map ' ~ protocol_config.route_map if protocol_config.route_map is vyos_defined }} +{% endfor %} {% endif %} diff --git a/data/templates/frr/ripd.frr.j2 b/data/templates/frr/ripd.frr.j2 new file mode 100644 index 000000000..df35150ca --- /dev/null +++ b/data/templates/frr/ripd.frr.j2 @@ -0,0 +1,92 @@ +{# RIP key-chain definition #} +{% if interface is vyos_defined %} +{% for iface, iface_config in interface.items() %} +{% if iface_config.authentication.md5 is vyos_defined %} +key chain {{ iface }}-rip +{% for key_id, key_options in iface_config.authentication.md5.items() %} + key {{ key_id }} +{% if key_options.password is vyos_defined %} + key-string {{ key_options.password }} +{% endif %} + exit +{% endfor %} +exit +{% endif %} +{% endfor %} +{% endif %} +! +{# Interface specific configuration #} +{% if interface is vyos_defined %} +{% for iface, iface_config in interface.items() %} +interface {{ iface }} +{% if iface_config.authentication.plaintext_password is vyos_defined %} + ip rip authentication mode text + ip rip authentication string {{ iface_config.authentication.plaintext_password }} +{% elif iface_config.authentication.md5 is vyos_defined %} + ip rip authentication key-chain {{ iface }}-rip + ip rip authentication mode md5 +{% endif %} +{% if iface_config.split_horizon.disable is vyos_defined %} + no ip rip split-horizon +{% endif %} +{% if iface_config.split_horizon.poison_reverse is vyos_defined %} + ip rip split-horizon poisoned-reverse +{% endif %} +exit +! +{% endfor %} +{% endif %} +! +router rip +{% if default_distance is vyos_defined %} + distance {{ default_distance }} +{% endif %} +{% if network_distance is vyos_defined %} +{% for network, network_config in network_distance.items() %} +{% if network_config.distance is vyos_defined %} + distance {{ network_config.distance }} {{ network }} +{% endif %} +{% endfor %} +{% endif %} +{% if neighbor is vyos_defined %} +{% for address in neighbor %} + neighbor {{ address }} +{% endfor %} +{% endif %} +{% if distribute_list is vyos_defined %} +{% if distribute_list.access_list.in is vyos_defined %} + distribute-list {{ distribute_list.access_list.in }} in +{% endif %} +{% if distribute_list.access_list.out is vyos_defined %} + distribute-list {{ distribute_list.access_list.out }} out +{% endif %} +{% if distribute_list.interface is vyos_defined %} +{% for interface, interface_config in distribute_list.interface.items() %} +{% if interface_config.access_list.in is vyos_defined %} + distribute-list {{ interface_config.access_list.in }} in {{ interface }} +{% endif %} +{% if interface_config.access_list.out is vyos_defined %} + distribute-list {{ interface_config.access_list.out }} out {{ interface }} +{% endif %} +{% if interface_config.prefix_list.in is vyos_defined %} + distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }} +{% endif %} +{% if interface_config.prefix_list.out is vyos_defined %} + distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }} +{% endif %} +{% endfor %} +{% endif %} +{% if distribute_list.prefix_list.in is vyos_defined %} + distribute-list prefix {{ distribute_list.prefix_list.in }} in +{% endif %} +{% if distribute_list.prefix_list.out is vyos_defined %} + distribute-list prefix {{ distribute_list.prefix_list.out }} out +{% endif %} +{% endif %} +{% include 'frr/rip_ripng.frr.j2' %} +exit +! +{% if route_map is vyos_defined %} +ip protocol rip route-map {{ route_map }} +{% endif %} +! diff --git a/data/templates/frr/ripd.frr.tmpl b/data/templates/frr/ripd.frr.tmpl deleted file mode 100644 index cabc236f0..000000000 --- a/data/templates/frr/ripd.frr.tmpl +++ /dev/null @@ -1,96 +0,0 @@ -! -{# RIP key-chain definition #} -{% if interface is defined and interface is not none %} -{% for iface, iface_config in interface.items() %} -{% if iface_config.authentication is defined and iface_config.authentication.md5 is defined and iface_config.authentication.md5 is not none %} -key chain {{ iface }}-rip -{% for key_id, key_options in iface_config.authentication.md5.items() %} - key {{ key_id }} -{% if key_options.password is defined and key_options.password is not none %} - key-string {{ key_options.password }} -{% endif %} -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -! -{# Interface specific configuration #} -{% if interface is defined and interface is not none %} -{% for iface, iface_config in interface.items() %} -interface {{ iface }} -{% if iface_config.authentication is defined and iface_config.authentication.plaintext_password is defined and iface_config.authentication.plaintext_password is not none %} - ip rip authentication mode text - ip rip authentication string {{ iface_config.authentication.plaintext_password }} -{% elif iface_config.authentication is defined and iface_config.authentication.md5 is defined and iface_config.authentication.md5 is not none %} - ip rip authentication key-chain {{ iface }}-rip - ip rip authentication mode md5 -{% endif %} -{% if iface_config.split_horizon is defined and iface_config.split_horizon.disable is defined %} - no ip rip split-horizon -{% endif %} -{% if iface_config.split_horizon is defined and iface_config.split_horizon.poison_reverse is defined %} - ip rip split-horizon poisoned-reverse -{% endif %} -{% endfor %} -{% endif %} -! -router rip -{% if default_distance is defined and default_distance is not none %} - distance {{ default_distance }} -{% endif %} -{% if network_distance is defined and network_distance is not none %} -{% for network, network_config in network_distance.items() %} -{% if network_config.distance is defined and network_config.distance is not none %} - distance {{ network_config.distance }} {{ network }} -{% endif %} -{% endfor %} -{% endif %} -{% if neighbor is defined and neighbor is not none %} -{% for address in neighbor %} - neighbor {{ address }} -{% endfor %} -{% endif %} -{% if distribute_list is defined and distribute_list is not none %} -{% if distribute_list.access_list is defined and distribute_list.access_list is not none %} -{% if distribute_list.access_list.in is defined and distribute_list.access_list.in is not none %} - distribute-list {{ distribute_list.access_list.in }} in -{% endif %} -{% if distribute_list.access_list.out is defined and distribute_list.access_list.out is not none %} - distribute-list {{ distribute_list.access_list.out }} out -{% endif %} -{% endif %} -{% if distribute_list.interface is defined and distribute_list.interface is not none %} -{% for interface, interface_config in distribute_list.interface.items() %} -{% if interface_config.access_list is defined and interface_config.access_list is not none %} -{% if interface_config.access_list.in is defined and interface_config.access_list.in is not none %} - distribute-list {{ interface_config.access_list.in }} in {{ interface }} -{% endif %} -{% if interface_config.access_list.out is defined and interface_config.access_list.out is not none %} - distribute-list {{ interface_config.access_list.out }} out {{ interface }} -{% endif %} -{% endif %} -{% if interface_config.prefix_list is defined and interface_config.prefix_list is not none %} -{% if interface_config.prefix_list.in is defined and interface_config.prefix_list.in is not none %} - distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }} -{% endif %} -{% if interface_config.prefix_list.out is defined and interface_config.prefix_list.out is not none %} - distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }} -{% endif %} -{% endif %} -{% endfor %} -{% endif %} -{% if distribute_list.prefix_list is defined and distribute_list.prefix_list is not none %} -{% if distribute_list.prefix_list.in is defined and distribute_list.prefix_list.in is not none %} - distribute-list prefix {{ distribute_list.prefix_list.in }} in -{% endif %} -{% if distribute_list.prefix_list.out is defined and distribute_list.prefix_list.out is not none %} - distribute-list prefix {{ distribute_list.prefix_list.out }} out -{% endif %} -{% endif %} -{% endif %} -{% include 'frr/rip_ripng.frr.j2' %} -! -{% if route_map is defined and route_map is not none %} -ip protocol rip route-map {{ route_map }} -{% endif %} -! diff --git a/data/templates/frr/ripngd.frr.j2 b/data/templates/frr/ripngd.frr.j2 new file mode 100644 index 000000000..7919b1bad --- /dev/null +++ b/data/templates/frr/ripngd.frr.j2 @@ -0,0 +1,57 @@ +{# Interface specific configuration #} +{% if interface is vyos_defined %} +{% for iface, iface_config in interface.items() %} +interface {{ iface }} +{% if iface_config.split_horizon.disable is vyos_defined %} + no ipv6 rip split-horizon +{% endif %} +{% if iface_config.split_horizon.poison_reverse is vyos_defined %} + ipv6 rip split-horizon poisoned-reverse +{% endif %} +exit +{% endfor %} +{% endif %} +! +router ripng +{% if aggregate_address is vyos_defined %} +{% for prefix in aggregate_address %} + aggregate-address {{ prefix }} +{% endfor %} +{% endif %} +{% if distribute_list is vyos_defined %} +{% if distribute_list.access_list.in is vyos_defined %} + ipv6 distribute-list {{ distribute_list.access_list.in }} in +{% endif %} +{% if distribute_list.access_list.out is vyos_defined %} + ipv6 distribute-list {{ distribute_list.access_list.out }} out +{% endif %} +{% if distribute_list.interface is vyos_defined %} +{% for interface, interface_config in distribute_list.interface.items() %} +{% if interface_config.access_list.in is vyos_defined %} + ipv6 distribute-list {{ interface_config.access_list.in }} in {{ interface }} +{% endif %} +{% if interface_config.access_list.out is vyos_defined %} + ipv6 distribute-list {{ interface_config.access_list.out }} out {{ interface }} +{% endif %} +{% if interface_config.prefix_list.in is vyos_defined %} + ipv6 distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }} +{% endif %} +{% if interface_config.prefix_list.out is vyos_defined %} + ipv6 distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }} +{% endif %} +{% endfor %} +{% endif %} +{% if distribute_list.prefix_list.in is vyos_defined %} + ipv6 distribute-list prefix {{ distribute_list.prefix_list.in }} in +{% endif %} +{% if distribute_list.prefix_list.out is vyos_defined %} + ipv6 distribute-list prefix {{ distribute_list.prefix_list.out }} out +{% endif %} +{% endif %} +{% include 'frr/rip_ripng.frr.j2' %} +exit +! +{% if route_map is vyos_defined %} +ipv6 protocol ripng route-map {{ route_map }} +{% endif %} +! diff --git a/data/templates/frr/ripngd.frr.tmpl b/data/templates/frr/ripngd.frr.tmpl deleted file mode 100644 index 25df15121..000000000 --- a/data/templates/frr/ripngd.frr.tmpl +++ /dev/null @@ -1,60 +0,0 @@ -! -{# Interface specific configuration #} -{% if interface is defined and interface is not none %} -{% for iface, iface_config in interface.items() %} -interface {{ iface }} -{% if iface_config.split_horizon is defined and iface_config.split_horizon.disable is defined %} - no ipv6 rip split-horizon -{% endif %} -{% if iface_config.split_horizon is defined and iface_config.split_horizon.poison_reverse is defined %} - ipv6 rip split-horizon poisoned-reverse -{% endif %} -{% endfor %} -{% endif %} -! -router ripng -{% if aggregate_address is defined and aggregate_address is not none %} -{% for prefix in aggregate_address %} - aggregate-address {{ prefix }} -{% endfor %} -{% endif %} -{% if distribute_list is defined and distribute_list is not none %} -{% if distribute_list.access_list is defined and distribute_list.access_list is not none %} -{% if distribute_list.access_list.in is defined and distribute_list.access_list.in is not none %} - ipv6 distribute-list {{ distribute_list.access_list.in }} in -{% endif %} -{% if distribute_list.access_list.out is defined and distribute_list.access_list.out is not none %} - ipv6 distribute-list {{ distribute_list.access_list.out }} out -{% endif %} -{% endif %} -{% if distribute_list.interface is defined and distribute_list.interface is not none %} -{% for interface, interface_config in distribute_list.interface.items() %} -{% if interface_config.access_list is defined and interface_config.access_list is not none %} -{% if interface_config.access_list.in is defined and interface_config.access_list.in is not none %} - ipv6 distribute-list {{ interface_config.access_list.in }} in {{ interface }} -{% endif %} -{% if interface_config.access_list.out is defined and interface_config.access_list.out is not none %} - ipv6 distribute-list {{ interface_config.access_list.out }} out {{ interface }} -{% endif %} -{% endif %} -{% if interface_config.prefix_list is defined and interface_config.prefix_list is not none %} -{% if interface_config.prefix_list.in is defined and interface_config.prefix_list.in is not none %} - ipv6 distribute-list prefix {{ interface_config.prefix_list.in }} in {{ interface }} -{% endif %} -{% if interface_config.prefix_list.out is defined and interface_config.prefix_list.out is not none %} - ipv6 distribute-list prefix {{ interface_config.prefix_list.out }} out {{ interface }} -{% endif %} -{% endif %} -{% endfor %} -{% endif %} -{% if distribute_list.prefix_list is defined and distribute_list.prefix_list is not none %} -{% if distribute_list.prefix_list.in is defined and distribute_list.prefix_list.in is not none %} - ipv6 distribute-list prefix {{ distribute_list.prefix_list.in }} in -{% endif %} -{% if distribute_list.prefix_list.out is defined and distribute_list.prefix_list.out is not none %} - ipv6 distribute-list prefix {{ distribute_list.prefix_list.out }} out -{% endif %} -{% endif %} -{% endif %} -{% include 'frr/rip_ripng.frr.j2' %} -! diff --git a/data/templates/frr/rpki.frr.tmpl b/data/templates/frr/rpki.frr.j2 index fbdfa27c3..9a549d6de 100644 --- a/data/templates/frr/rpki.frr.tmpl +++ b/data/templates/frr/rpki.frr.j2 @@ -1,17 +1,18 @@ ! {# as FRR does not support deleting the entire rpki section we leave it in place even when it's empty #} rpki -{% if cache is defined and cache is not none %} -{% for peer, peer_config in cache.items() %} -{# port is mandatory and preference uses a default value #} -{% if peer_config.ssh is defined and peer_config.ssh.username is defined and peer_config.ssh.username is not none %} +{% if cache is vyos_defined %} +{% for peer, peer_config in cache.items() %} +{# port is mandatory and preference uses a default value #} +{% if peer_config.ssh.username is vyos_defined %} rpki cache {{ peer | replace('_', '-') }} {{ peer_config.port }} {{ peer_config.ssh.username }} {{ peer_config.ssh.private_key_file }} {{ peer_config.ssh.public_key_file }} {{ peer_config.ssh.known_hosts_file }} preference {{ peer_config.preference }} -{% else %} +{% else %} rpki cache {{ peer | replace('_', '-') }} {{ peer_config.port }} preference {{ peer_config.preference }} -{% endif %} -{% endfor %} +{% endif %} +{% endfor %} {% endif %} -{% if polling_period is defined and polling_period is not none %} +{% if polling_period is vyos_defined %} rpki polling_period {{ polling_period }} {% endif %} +exit ! diff --git a/data/templates/frr/static_mcast.frr.tmpl b/data/templates/frr/static_mcast.frr.j2 index 4f114109a..491d4b54a 100644 --- a/data/templates/frr/static_mcast.frr.tmpl +++ b/data/templates/frr/static_mcast.frr.j2 @@ -1,20 +1,20 @@ ! {% for route_gr in old_mroute %} -{% for nh in old_mroute[route_gr] %} -{% if old_mroute[route_gr][nh] %} +{% for nh in old_mroute[route_gr] %} +{% if old_mroute[route_gr][nh] %} no ip mroute {{ route_gr }} {{ nh }} {{ old_mroute[route_gr][nh] }} -{% else %} +{% else %} no ip mroute {{ route_gr }} {{ nh }} -{% endif %} -{% endfor %} +{% endif %} +{% endfor %} {% endfor %} {% for route_gr in mroute %} -{% for nh in mroute[route_gr] %} -{% if mroute[route_gr][nh] %} +{% for nh in mroute[route_gr] %} +{% if mroute[route_gr][nh] %} ip mroute {{ route_gr }} {{ nh }} {{ mroute[route_gr][nh] }} -{% else %} +{% else %} ip mroute {{ route_gr }} {{ nh }} -{% endif %} -{% endfor %} +{% endif %} +{% endfor %} {% endfor %} ! diff --git a/data/templates/frr/static_routes_macro.j2 b/data/templates/frr/static_routes_macro.j2 index 3b432b49b..1c64ac58b 100644 --- a/data/templates/frr/static_routes_macro.j2 +++ b/data/templates/frr/static_routes_macro.j2 @@ -1,21 +1,24 @@ {% macro static_routes(ip_ipv6, prefix, prefix_config, table=None) %} -{% if prefix_config.blackhole is defined %} -{{ ip_ipv6 }} route {{ prefix }} blackhole {{ prefix_config.blackhole.distance if prefix_config.blackhole.distance is defined }} {{ 'tag ' + prefix_config.blackhole.tag if prefix_config.blackhole.tag is defined }} {{ 'table ' + table if table is defined and table is not none }} -{% endif %} -{% if prefix_config.dhcp_interface is defined and prefix_config.dhcp_interface is not none %} +{% if prefix_config.blackhole is vyos_defined %} +{{ ip_ipv6 }} route {{ prefix }} blackhole {{ prefix_config.blackhole.distance if prefix_config.blackhole.distance is vyos_defined }} {{ 'tag ' ~ prefix_config.blackhole.tag if prefix_config.blackhole.tag is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined and table is not none }} +{% endif %} +{% if prefix_config.reject is vyos_defined %} +{{ ip_ipv6 }} route {{ prefix }} reject {{ prefix_config.reject.distance if prefix_config.reject.distance is vyos_defined }} {{ 'tag ' ~ prefix_config.reject.tag if prefix_config.reject.tag is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }} +{% endif %} +{% if prefix_config.dhcp_interface is vyos_defined %} {% set next_hop = prefix_config.dhcp_interface | get_dhcp_router %} -{% if next_hop is defined and next_hop is not none %} -{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ prefix_config.dhcp_interface }} +{% if next_hop is vyos_defined %} +{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ prefix_config.dhcp_interface }} {{ 'table ' ~ table if table is vyos_defined }} {% endif %} -{% endif %} -{% if prefix_config.interface is defined and prefix_config.interface is not none %} +{% endif %} +{% if prefix_config.interface is vyos_defined %} {% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %} -{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is defined }} {{ 'nexthop-vrf ' + interface_config.vrf if interface_config.vrf is defined }} {{ 'table ' + table if table is defined and table is not none }} +{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ interface_config.vrf if interface_config.vrf is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }} {% endfor %} -{% endif %} -{% if prefix_config.next_hop is defined and prefix_config.next_hop is not none %} +{% endif %} +{% if prefix_config.next_hop is vyos_defined and prefix_config.next_hop is not none %} {% for next_hop, next_hop_config in prefix_config.next_hop.items() if next_hop_config.disable is not defined %} -{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is defined }} {{ next_hop_config.distance if next_hop_config.distance is defined }} {{ 'nexthop-vrf ' + next_hop_config.vrf if next_hop_config.vrf is defined }} {{ 'table ' + table if table is defined and table is not none }} +{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is vyos_defined }} {{ next_hop_config.distance if next_hop_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ next_hop_config.vrf if next_hop_config.vrf is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }} {% endfor %} -{% endif %} +{% endif %} {% endmacro %} diff --git a/data/templates/frr/staticd.frr.j2 b/data/templates/frr/staticd.frr.j2 new file mode 100644 index 000000000..589f03c2c --- /dev/null +++ b/data/templates/frr/staticd.frr.j2 @@ -0,0 +1,64 @@ +{% from 'frr/static_routes_macro.j2' import static_routes %} +! +{% set ip_prefix = 'ip' %} +{% set ipv6_prefix = 'ipv6' %} +{% if vrf is vyos_defined %} +{# We need to add an additional whitespace in front of the prefix #} +{# when VRFs are in use, thus we use a variable for prefix handling #} +{% set ip_prefix = ' ip' %} +{% set ipv6_prefix = ' ipv6' %} +vrf {{ vrf }} +{% endif %} +{# IPv4 routing #} +{% if route is vyos_defined %} +{% for prefix, prefix_config in route.items() %} +{{ static_routes(ip_prefix, prefix, prefix_config) }} +{% endfor %} +{% endif %} +{# IPv4 default routes from DHCP interfaces #} +{% if dhcp is vyos_defined %} +{% for interface, interface_config in dhcp.items() %} +{% set next_hop = interface | get_dhcp_router %} +{% if next_hop is vyos_defined %} +{{ ip_prefix }} route 0.0.0.0/0 {{ next_hop }} {{ interface }} tag 210 {{ interface_config.dhcp_options.default_route_distance if interface_config.dhcp_options.default_route_distance is vyos_defined }} +{% endif %} +{% endfor %} +{% endif %} +{# IPv4 default routes from PPPoE interfaces #} +{% if pppoe is vyos_defined %} +{% for interface, interface_config in pppoe.items() %} +{{ ip_prefix }} route 0.0.0.0/0 {{ interface }} tag 210 {{ interface_config.default_route_distance if interface_config.default_route_distance is vyos_defined }} +{% endfor %} +{% endif %} +{# IPv6 routing #} +{% if route6 is vyos_defined %} +{% for prefix, prefix_config in route6.items() %} +{{ static_routes(ipv6_prefix, prefix, prefix_config) }} +{% endfor %} +{% endif %} +{% if vrf is vyos_defined %} + exit-vrf +{% endif %} +! +{# Policy route tables #} +{% if table is vyos_defined %} +{% for table_id, table_config in table.items() %} +{% if table_config.route is vyos_defined %} +{% for prefix, prefix_config in table_config.route.items() %} +{{ static_routes('ip', prefix, prefix_config, table_id) }} +{% endfor %} +{% endif %} +! +{% if table_config.route6 is vyos_defined %} +{% for prefix, prefix_config in table_config.route6.items() %} +{{ static_routes('ipv6', prefix, prefix_config, table_id) }} +{% endfor %} +{% endif %} +! +{% endfor %} +{% endif %} +! +{% if route_map is vyos_defined %} +ip protocol static route-map {{ route_map }} +! +{% endif %} diff --git a/data/templates/frr/staticd.frr.tmpl b/data/templates/frr/staticd.frr.tmpl deleted file mode 100644 index bfe959c1d..000000000 --- a/data/templates/frr/staticd.frr.tmpl +++ /dev/null @@ -1,58 +0,0 @@ -{% from 'frr/static_routes_macro.j2' import static_routes %} -! -{% set ip_prefix = 'ip' %} -{% set ipv6_prefix = 'ipv6' %} -{% if vrf is defined and vrf is not none %} -{# We need to add an additional whitespace in front of the prefix #} -{# when VRFs are in use, thus we use a variable for prefix handling #} -{% set ip_prefix = ' ip' %} -{% set ipv6_prefix = ' ipv6' %} -vrf {{ vrf }} -{% endif %} -{# IPv4 routing #} -{% if route is defined and route is not none %} -{% for prefix, prefix_config in route.items() %} -{{ static_routes(ip_prefix, prefix, prefix_config) }} -{%- endfor -%} -{% endif %} -{# IPv4 default routes from DHCP interfaces #} -{% if dhcp is defined and dhcp is not none %} -{% for interface in dhcp %} -{% set next_hop = interface | get_dhcp_router %} -{% if next_hop is defined and next_hop is not none %} -{{ ip_prefix }} route 0.0.0.0/0 {{ next_hop }} {{ interface }} tag 210 210 -{% endif %} -{% endfor %} -{% endif %} -{# IPv6 routing #} -{% if route6 is defined and route6 is not none %} -{% for prefix, prefix_config in route6.items() %} -{{ static_routes(ipv6_prefix, prefix, prefix_config) }} -{%- endfor -%} -{% endif %} -{% if vrf is defined and vrf is not none %} - exit-vrf -{% endif %} -! -{# Policy route tables #} -{% if table is defined and table is not none %} -{% for table_id, table_config in table.items() %} -{% if table_config.route is defined and table_config.route is not none %} -{% for prefix, prefix_config in table_config.route.items() %} -{{ static_routes('ip', prefix, prefix_config, table_id) }} -{%- endfor -%} -{% endif %} -! -{% if table_config.route6 is defined and table_config.route6 is not none %} -{% for prefix, prefix_config in table_config.route6.items() %} -{{ static_routes('ipv6', prefix, prefix_config, table_id) }} -{%- endfor -%} -{% endif %} -! -{% endfor %} -{% endif %} -! -{% if route_map is defined and route_map is not none %} -ip protocol static route-map {{ route_map }} -! -{% endif %} diff --git a/data/templates/frr/vrf-vni.frr.j2 b/data/templates/frr/vrf-vni.frr.j2 new file mode 100644 index 000000000..e5f4810a1 --- /dev/null +++ b/data/templates/frr/vrf-vni.frr.j2 @@ -0,0 +1,9 @@ +{% if name is vyos_defined %} +{% for vrf, vrf_config in name.items() %} +vrf {{ vrf }} +{% if vrf_config.vni is vyos_defined %} + vni {{ vrf_config.vni }} +{% endif %} + exit-vrf +{% endfor %} +{% endif %} diff --git a/data/templates/frr/vrf-vni.frr.tmpl b/data/templates/frr/vrf-vni.frr.tmpl deleted file mode 100644 index 299c9719e..000000000 --- a/data/templates/frr/vrf-vni.frr.tmpl +++ /dev/null @@ -1,9 +0,0 @@ -{% if name is defined and name is not none %} -{% for vrf, vrf_config in name.items() %} -vrf {{ vrf }} -{% if vrf_config.vni is defined and vrf_config.vni is not none %} - vni {{ vrf_config.vni }} -{% endif %} - exit-vrf -{% endfor %} -{% endif %} diff --git a/data/templates/frr/vrf.route-map.frr.j2 b/data/templates/frr/vrf.route-map.frr.j2 new file mode 100644 index 000000000..5e0c56a7b --- /dev/null +++ b/data/templates/frr/vrf.route-map.frr.j2 @@ -0,0 +1,10 @@ +! +{% if vrf is vyos_defined and route_map is vyos_defined %} +vrf {{ vrf }} + ip protocol {{ protocol }} route-map {{ route_map }} + exit-vrf +! +{% elif route_map is vyos_defined %} +ip protocol {{ protocol }} route-map {{ route_map }} +{% endif %} +! diff --git a/data/templates/frr/vrf.route-map.frr.tmpl b/data/templates/frr/vrf.route-map.frr.tmpl deleted file mode 100644 index cb0e07616..000000000 --- a/data/templates/frr/vrf.route-map.frr.tmpl +++ /dev/null @@ -1,10 +0,0 @@ -! -{% if vrf is defined and vrf is not none and route_map is defined and route_map is not none %} -vrf {{ vrf }} - ip protocol {{ protocol }} route-map {{ route_map }} - exit-vrf -! -{% elif route_map is defined and route_map is not none %} -ip protocol {{ protocol }} route-map {{ route_map }} -{% endif %} -! diff --git a/data/templates/getty/serial-getty.service.tmpl b/data/templates/getty/serial-getty.service.j2 index 0183eae7d..0183eae7d 100644 --- a/data/templates/getty/serial-getty.service.tmpl +++ b/data/templates/getty/serial-getty.service.j2 diff --git a/data/templates/high-availability/keepalived.conf.j2 b/data/templates/high-availability/keepalived.conf.j2 new file mode 100644 index 000000000..6684dbc2c --- /dev/null +++ b/data/templates/high-availability/keepalived.conf.j2 @@ -0,0 +1,169 @@ +# Autogenerated by VyOS +# Do not edit this file, all your changes will be lost +# on next commit or reboot + +global_defs { + dynamic_interfaces + script_user root + notify_fifo /run/keepalived/keepalived_notify_fifo + notify_fifo_script /usr/libexec/vyos/system/keepalived-fifo.py +} + +{% if vrrp.group is vyos_defined %} +{% for name, group_config in vrrp.group.items() if group_config.disable is not vyos_defined %} +{% if group_config.health_check.script is vyos_defined %} +vrrp_script healthcheck_{{ name }} { + script "{{ group_config.health_check.script }}" + interval {{ group_config.health_check.interval }} + fall {{ group_config.health_check.failure_count }} + rise 1 +} +{% endif %} +vrrp_instance {{ name }} { +{% if group_config.description is vyos_defined %} + # {{ group_config.description }} +{% endif %} + state BACKUP + interface {{ group_config.interface }} + virtual_router_id {{ group_config.vrid }} + priority {{ group_config.priority }} + advert_int {{ group_config.advertise_interval }} +{% if group_config.track.exclude_vrrp_interface is vyos_defined %} + dont_track_primary +{% endif %} +{% if group_config.no_preempt is not vyos_defined and group_config.preempt_delay is vyos_defined %} + preempt_delay {{ group_config.preempt_delay }} +{% elif group_config.no_preempt is vyos_defined %} + nopreempt +{% endif %} +{% if group_config.peer_address is vyos_defined %} + unicast_peer { {{ group_config.peer_address }} } +{% endif %} +{% if group_config.hello_source_address is vyos_defined %} +{% if group_config.peer_address is vyos_defined %} + unicast_src_ip {{ group_config.hello_source_address }} +{% else %} + mcast_src_ip {{ group_config.hello_source_address }} +{% endif %} +{% endif %} +{% if group_config.rfc3768_compatibility is vyos_defined and group_config.peer_address is vyos_defined %} + use_vmac {{ group_config.interface }}v{{ group_config.vrid }} + vmac_xmit_base +{% elif group_config.rfc3768_compatibility is vyos_defined %} + use_vmac {{ group_config.interface }}v{{ group_config.vrid }} +{% endif %} +{% if group_config.authentication is vyos_defined %} + authentication { + auth_pass "{{ group_config.authentication.password }}" +{% if group_config.authentication.type is vyos_defined('plaintext-password') %} + auth_type PASS +{% else %} + auth_type {{ group_config.authentication.type | upper }} +{% endif %} + } +{% endif %} +{% if group_config.address is vyos_defined %} + virtual_ipaddress { +{% for addr, addr_config in group_config.address.items() %} + {{ addr }}{{ ' dev ' + addr_config.interface if addr_config.interface is vyos_defined }} +{% endfor %} + } +{% endif %} +{% if group_config.excluded_address is vyos_defined %} + virtual_ipaddress_excluded { +{% for addr in group_config.excluded_address %} + {{ addr }} +{% endfor %} + } +{% endif %} +{% if group_config.track.interface is vyos_defined %} + track_interface { +{% for interface in group_config.track.interface %} + {{ interface }} +{% endfor %} + } +{% endif %} +{% if group_config.health_check.script is vyos_defined %} + track_script { + healthcheck_{{ name }} + } +{% endif %} +} +{% endfor %} +{% endif %} + +{% if vrrp.sync_group is vyos_defined %} +{% for name, sync_group_config in vrrp.sync_group.items() if sync_group_config.disable is not vyos_defined %} +vrrp_sync_group {{ name }} { + group { +{% if sync_group_config.member is vyos_defined %} +{% for member in sync_group_config.member %} + {{ member }} +{% endfor %} +{% endif %} + } + +{# Health-check scripts should be in section sync-group if member is part of the sync-group T4081 #} +{% if vrrp.group is vyos_defined %} +{% for name, group_config in vrrp.group.items() if group_config.disable is not vyos_defined %} +{% if group_config.health_check.script is vyos_defined and name in sync_group_config.member %} + track_script { + healthcheck_{{ name }} + } +{% endif %} +{% endfor %} +{% endif %} +{% if conntrack_sync_group is vyos_defined(name) %} +{% set vyos_helper = "/usr/libexec/vyos/vyos-vrrp-conntracksync.sh" %} + notify_master "{{ vyos_helper }} master {{ name }}" + notify_backup "{{ vyos_helper }} backup {{ name }}" + notify_fault "{{ vyos_helper }} fault {{ name }}" +{% endif %} +} +{% endfor %} +{% endif %} + +{% if virtual_server is vyos_defined %} +# Virtual-server configuration +{% for vserver, vserver_config in virtual_server.items() %} +virtual_server {{ vserver }} {{ vserver_config.port }} { + delay_loop {{ vserver_config.delay_loop }} +{% if vserver_config.algorithm is vyos_defined('round-robin') %} + lb_algo rr +{% elif vserver_config.algorithm is vyos_defined('weighted-round-robin') %} + lb_algo wrr +{% elif vserver_config.algorithm is vyos_defined('least-connection') %} + lb_algo lc +{% elif vserver_config.algorithm is vyos_defined('weighted-least-connection') %} + lb_algo wlc +{% elif vserver_config.algorithm is vyos_defined('source-hashing') %} + lb_algo sh +{% elif vserver_config.algorithm is vyos_defined('destination-hashing') %} + lb_algo dh +{% elif vserver_config.algorithm is vyos_defined('locality-based-least-connection') %} + lb_algo lblc +{% endif %} +{% if vserver_config.forward_method is vyos_defined('nat') %} + lb_kind NAT +{% elif vserver_config.forward_method is vyos_defined('direct') %} + lb_kind DR +{% elif vserver_config.forward_method is vyos_defined('tunnel') %} + lb_kind TUN +{% endif %} + persistence_timeout {{ vserver_config.persistence_timeout }} + protocol {{ vserver_config.protocol | upper }} +{% if vserver_config.real_server is vyos_defined %} +{% for rserver, rserver_config in vserver_config.real_server.items() %} + real_server {{ rserver }} {{ rserver_config.port }} { + weight 1 + {{ vserver_config.protocol | upper }}_CHECK { +{% if rserver_config.connection_timeout is vyos_defined %} + connect_timeout {{ rserver_config.connection_timeout }} +{% endif %} + } + } +{% endfor %} +{% endif %} +} +{% endfor %} +{% endif %} diff --git a/data/templates/https/nginx.default.tmpl b/data/templates/https/nginx.default.j2 index 9d73baeee..70e62ae7a 100644 --- a/data/templates/https/nginx.default.tmpl +++ b/data/templates/https/nginx.default.j2 @@ -1,74 +1,56 @@ ### Autogenerated by https.py ### # Default server configuration -# -server { - listen 80 default_server; - listen [::]:80 default_server; - server_name _; - return 301 https://$host$request_uri; -} {% for server in server_block_list %} server { - # SSL configuration # -{% if server.address == '*' %} +{% if server.address == '*' %} listen {{ server.port }} ssl; listen [::]:{{ server.port }} ssl; -{% else %} +{% else %} listen {{ server.address | bracketize_ipv6 }}:{{ server.port }} ssl; -{% endif %} +{% endif %} -{% for name in server.name %} +{% for name in server.name %} server_name {{ name }}; -{% endfor %} +{% endfor %} -{% if server.certbot %} +{% if server.certbot %} ssl_certificate {{ server.certbot_dir }}/live/{{ server.certbot_domain_dir }}/fullchain.pem; ssl_certificate_key {{ server.certbot_dir }}/live/{{ server.certbot_domain_dir }}/privkey.pem; include {{ server.certbot_dir }}/options-ssl-nginx.conf; ssl_dhparam {{ server.certbot_dir }}/ssl-dhparams.pem; -{% elif server.vyos_cert %} +{% elif server.vyos_cert %} ssl_certificate {{ server.vyos_cert.crt }}; ssl_certificate_key {{ server.vyos_cert.key }}; -{% else %} +{% else %} # # Self signed certs generated by the ssl-cert package # Don't use them in a production server! # include snippets/snakeoil.conf; -{% endif %} +{% endif %} ssl_protocols TLSv1.2 TLSv1.3; # proxy settings for HTTP API, if enabled; 503, if not location ~ /(retrieve|configure|config-file|image|generate|show|docs|openapi.json|redoc|graphql) { -{% if server.api %} +{% if server.api %} +{% if server.api.socket %} + proxy_pass http://unix:/run/api.sock; +{% else %} proxy_pass http://localhost:{{ server.api.port }}; +{% endif %} proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 600; proxy_buffering off; -{% else %} +{% else %} return 503; -{% endif %} +{% endif %} } error_page 497 =301 https://$host:{{ server.port }}$request_uri; - error_page 501 502 503 =200 @50*_json; - -{% if api_set %} - location @50*_json { - default_type application/json; - return 200 '{"error": "service https api unavailable at this proxy address: set service https api-restrict virtual-host"}'; - } -{% else %} - location @50*_json { - default_type application/json; - return 200 '{"error": "Start service in configuration mode: set service https api"}'; - } -{% endif %} - } {% endfor %} diff --git a/data/templates/https/override.conf.j2 b/data/templates/https/override.conf.j2 new file mode 100644 index 000000000..c2c191b06 --- /dev/null +++ b/data/templates/https/override.conf.j2 @@ -0,0 +1,15 @@ +{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %} +[Unit] +StartLimitIntervalSec=0 +After=vyos-router.service + +[Service] +ExecStartPre= +ExecStartPre={{ vrf_command }}/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' +ExecStart= +ExecStart={{ vrf_command }}/usr/sbin/nginx -g 'daemon on; master_process on;' +ExecReload= +ExecReload={{ vrf_command }}/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload +Restart=always +RestartPreventExitStatus= +RestartSec=10 diff --git a/data/templates/https/vyos-http-api.service.j2 b/data/templates/https/vyos-http-api.service.j2 new file mode 100644 index 000000000..fb424e06c --- /dev/null +++ b/data/templates/https/vyos-http-api.service.j2 @@ -0,0 +1,22 @@ +{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %} +[Unit] +Description=VyOS HTTP API service +After=vyos-router.service +Requires=vyos-router.service + +[Service] +ExecStart={{ vrf_command }}/usr/libexec/vyos/services/vyos-http-api-server +Type=idle + +SyslogIdentifier=vyos-http-api +SyslogFacility=daemon + +Restart=on-failure + +# Does't work but leave it here +User=root +Group=vyattacfg + +[Install] +WantedBy=vyos.target + diff --git a/data/templates/ids/fastnetmon.tmpl b/data/templates/ids/fastnetmon.j2 index 1f6a1c808..c482002fa 100644 --- a/data/templates/ids/fastnetmon.tmpl +++ b/data/templates/ids/fastnetmon.j2 @@ -25,36 +25,32 @@ unban_only_if_attack_finished = on # For each subnet, list track speed in bps and pps for both directions enable_subnet_counters = off -{% if "mirror" in mode %} +{% if mode.mirror is vyos_defined %} mirror_afpacket = on {% endif %} -{% if "in" in direction %} -process_incoming_traffic = on -{% endif %} -{% if "out" in direction %} -process_outgoing_traffic = on -{% endif %} -{% for th in threshold %} -{% if th == "fps" %} +process_incoming_traffic = {{ 'on' if direction is vyos_defined and 'in' in direction else 'off' }} +process_outgoing_traffic = {{ 'on' if direction is vyos_defined and 'out' in direction else 'off' }} + +{% if threshold is vyos_defined %} +{% for thr, thr_value in threshold.items() %} +{% if thr is vyos_defined('fps') %} ban_for_flows = on -threshold_flows = {{ threshold[th] }} -{% endif %} -{% if th == "mbps" %} +threshold_flows = {{ thr_value }} +{% elif thr is vyos_defined('mbps') %} ban_for_bandwidth = on -threshold_mbps = {{ threshold[th] }} -{% endif %} -{% if th == "pps" %} +threshold_mbps = {{ thr_value }} +{% elif thr is vyos_defined('pps') %} ban_for_pps = on -threshold_pps = {{ threshold[th] }} +threshold_pps = {{ thr_value }} +{% endif %} +{% endfor %} {% endif %} -{% endfor %} -{% if listen_interface %} -{% set value = listen_interface if listen_interface is string else listen_interface | join(',') %} -interfaces = {{ value }} +{% if listen_interface is vyos_defined %} +interfaces = {{ listen_interface | join(',') }} {% endif %} -{% if alert_script %} +{% if alert_script is vyos_defined %} notify_script_path = {{ alert_script }} {% endif %} diff --git a/data/templates/ids/fastnetmon_networks_list.j2 b/data/templates/ids/fastnetmon_networks_list.j2 new file mode 100644 index 000000000..1c81180be --- /dev/null +++ b/data/templates/ids/fastnetmon_networks_list.j2 @@ -0,0 +1,7 @@ +{% if network is vyos_defined(var_type=str) %} +{{ network }} +{% else %} +{% for net in network %} +{{ net }} +{% endfor %} +{% endif %} diff --git a/data/templates/ids/fastnetmon_networks_list.tmpl b/data/templates/ids/fastnetmon_networks_list.tmpl deleted file mode 100644 index d58990053..000000000 --- a/data/templates/ids/fastnetmon_networks_list.tmpl +++ /dev/null @@ -1,7 +0,0 @@ -{% if network is string %} -{{ network }} -{% else %} -{% for net in network %} -{{ net }} -{% endfor %} -{% endif %} diff --git a/data/templates/igmp-proxy/igmpproxy.conf.tmpl b/data/templates/igmp-proxy/igmpproxy.conf.j2 index e3966def3..ab3c9fd31 100644 --- a/data/templates/igmp-proxy/igmpproxy.conf.tmpl +++ b/data/templates/igmp-proxy/igmpproxy.conf.j2 @@ -14,27 +14,27 @@ # ######################################################## -{% if disable_quickleave is not defined %} +{% if disable_quickleave is not vyos_defined %} quickleave {% endif %} -{% if interface is defined and interface is not none %} -{% for iface, config in interface.items() %} +{% if interface is vyos_defined %} +{% for iface, config in interface.items() %} # Configuration for {{ iface }} ({{ config.role }} interface) -{% if config.role == 'disabled' %} +{% if config.role is vyos_defined('disabled') %} phyint {{ iface }} disabled -{% else %} +{% else %} phyint {{ iface }} {{ config.role }} ratelimit 0 threshold {{ config.threshold }} -{% endif %} -{% if config.alt_subnet is defined and config.alt_subnet is not none %} -{% for subnet in config.alt_subnet %} +{% endif %} +{% if config.alt_subnet is vyos_defined %} +{% for subnet in config.alt_subnet %} altnet {{ subnet }} -{% endfor %} -{% endif %} -{% if config.whitelist is defined and config.whitelist is not none %} -{% for subnet in config.whitelist %} +{% endfor %} +{% endif %} +{% if config.whitelist is vyos_defined %} +{% for subnet in config.whitelist %} whitelist {{ subnet }} -{% endfor %} -{% endif %} -{% endfor %} +{% endfor %} +{% endif %} +{% endfor %} {% endif %} diff --git a/data/templates/ipsec/charon.tmpl b/data/templates/ipsec/charon.j2 index 4d710921e..388559af8 100644 --- a/data/templates/ipsec/charon.tmpl +++ b/data/templates/ipsec/charon.j2 @@ -1,6 +1,5 @@ # Options for the charon IKE daemon. charon { - # Accept unencrypted ID and HASH payloads in IKEv1 Main Mode. # accept_unencrypted_mainmode_messages = no @@ -20,6 +19,17 @@ charon { # Send Cisco Unity vendor ID payload (IKEv1 only). # cisco_unity = no + # Cisco FlexVPN +{% if options is vyos_defined %} + cisco_flexvpn = {{ 'yes' if options.flexvpn is vyos_defined else 'no' }} +{% if options.virtual_ip is vyos_defined %} + install_virtual_ip = yes +{% endif %} +{% if options.interface is vyos_defined %} + install_virtual_ip_on = {{ options.interface }} +{% endif %} +{% endif %} + # Close the IKE_SA if setup of the CHILD_SA along with IKE_AUTH failed. # close_ike_on_child_failure = no diff --git a/data/templates/ipsec/charon/dhcp.conf.tmpl b/data/templates/ipsec/charon/dhcp.conf.j2 index 92774b275..aaa5613fb 100644 --- a/data/templates/ipsec/charon/dhcp.conf.tmpl +++ b/data/templates/ipsec/charon/dhcp.conf.j2 @@ -1,12 +1,10 @@ dhcp { load = yes -{% if remote_access is defined and remote_access.dhcp is defined %} -{% if remote_access.dhcp.interface is defined %} +{% if remote_access.dhcp.interface is vyos_defined %} interface = {{ remote_access.dhcp.interface }} -{% endif %} -{% if remote_access.dhcp.server is defined %} +{% endif %} +{% if remote_access.dhcp.server is vyos_defined %} server = {{ remote_access.dhcp.server }} -{% endif %} {% endif %} # Always use the configured server address. diff --git a/data/templates/ipsec/charon/eap-radius.conf.tmpl b/data/templates/ipsec/charon/eap-radius.conf.j2 index 5ec35c988..8495011fe 100644 --- a/data/templates/ipsec/charon/eap-radius.conf.tmpl +++ b/data/templates/ipsec/charon/eap-radius.conf.j2 @@ -41,7 +41,7 @@ eap-radius { load = yes # NAS-Identifier to include in RADIUS messages. - nas_identifier = {{ remote_access.radius.nas_identifier if remote_access is defined and remote_access.radius is defined and remote_access.radius.nas_identifier is defined else 'strongSwan' }} + nas_identifier = {{ remote_access.radius.nas_identifier if remote_access.radius.nas_identifier is vyos_defined else 'strongSwan' }} # Port of RADIUS server (authentication). # port = 1812 @@ -94,19 +94,19 @@ eap-radius { # Section to specify multiple RADIUS servers. servers { -{% if remote_access is defined and remote_access.radius is defined and remote_access.radius.server is defined %} -{% for server, server_options in remote_access.radius.server.items() if server_options.disable is not defined %} +{% if remote_access.radius.server is vyos_defined %} +{% for server, server_options in remote_access.radius.server.items() if server_options.disable is not vyos_defined %} {{ server | replace('.', '-') }} { address = {{ server }} secret = {{ server_options.key }} auth_port = {{ server_options.port }} -{% if server_options.disable_accounting is not defined %} - acct_port = {{ server_options.port | int +1 }} -{% endif %} +{% if server_options.disable_accounting is not vyos_defined %} + acct_port = {{ server_options.port | int + 1 }} +{% endif %} sockets = 20 } -{% endfor %} -{% endif %} +{% endfor %} +{% endif %} } # Section to configure multiple XAuth authentication rounds via RADIUS. diff --git a/data/templates/ipsec/interfaces_use.conf.tmpl b/data/templates/ipsec/interfaces_use.conf.j2 index a77102396..c1bf8270d 100644 --- a/data/templates/ipsec/interfaces_use.conf.tmpl +++ b/data/templates/ipsec/interfaces_use.conf.j2 @@ -1,5 +1,5 @@ -{% if interface is defined %} +{% if interface is vyos_defined %} charon { interfaces_use = {{ ', '.join(interface) }} } -{% endif %}
\ No newline at end of file +{% endif %}
\ No newline at end of file diff --git a/data/templates/ipsec/ios_profile.tmpl b/data/templates/ipsec/ios_profile.j2 index af6c79d6e..c8e17729a 100644 --- a/data/templates/ipsec/ios_profile.tmpl +++ b/data/templates/ipsec/ios_profile.j2 @@ -41,7 +41,7 @@ <!-- Remote identity, can be a FQDN, a userFQDN, an IP or (theoretically) a certificate's subject DN. Can't be empty. IMPORTANT: DNs are currently not handled correctly, they are always sent as identities of type FQDN --> <key>RemoteIdentifier</key> - <string>{{ authentication.id if authentication.id is defined else 'fooo' }}</string> + <string>{{ authentication.id if authentication.id is vyos_defined else 'VyOS' }}</string> <!-- Local IKE identity, same restrictions as above. If it is empty the client's IP address will be used --> <key>LocalIdentifier</key> <string></string> diff --git a/data/templates/ipsec/ipsec.conf.j2 b/data/templates/ipsec/ipsec.conf.j2 new file mode 100644 index 000000000..f63995b38 --- /dev/null +++ b/data/templates/ipsec/ipsec.conf.j2 @@ -0,0 +1,19 @@ +# Created by VyOS - manual changes will be overwritten + +config setup +{% set charondebug = '' %} +{% if log.subsystem is vyos_defined %} +{% set subsystem = log.subsystem %} +{% if 'any' in log.subsystem %} +{% set subsystem = ['dmn', 'mgr', 'ike', 'chd','job', 'cfg', 'knl', + 'net', 'asn', 'enc', 'lib', 'esp', 'tls', 'tnc', + 'imc', 'imv', 'pts'] %} +{% endif %} +{% set charondebug = subsystem | join (' ' ~ log.level ~ ', ') ~ ' ' ~ log.level %} +{% endif %} + charondebug = "{{ charondebug }}" + uniqueids = {{ "no" if disable_uniqreqids is vyos_defined else "yes" }} + +{% if include_ipsec_conf is vyos_defined %} +include {{ include_ipsec_conf }} +{% endif %} diff --git a/data/templates/ipsec/ipsec.conf.tmpl b/data/templates/ipsec/ipsec.conf.tmpl deleted file mode 100644 index 1cb531e76..000000000 --- a/data/templates/ipsec/ipsec.conf.tmpl +++ /dev/null @@ -1,18 +0,0 @@ -# Created by VyOS - manual changes will be overwritten - -config setup -{% set charondebug = '' %} -{% if log is defined and log.subsystem is defined and log.subsystem is not none %} -{% set subsystem = log.subsystem %} -{% if 'any' in log.subsystem %} -{% set subsystem = ['dmn', 'mgr', 'ike', 'chd','job', 'cfg', 'knl', 'net', 'asn', - 'enc', 'lib', 'esp', 'tls', 'tnc', 'imc', 'imv', 'pts'] %} -{% endif %} -{% set charondebug = subsystem | join (' ' ~ log.level ~ ', ') ~ ' ' ~ log.level %} -{% endif %} - charondebug = "{{ charondebug }}" - uniqueids = {{ "no" if disable_uniqreqids is defined else "yes" }} - -{% if include_ipsec_conf is defined %} -include {{ include_ipsec_conf }} -{% endif %} diff --git a/data/templates/ipsec/ipsec.secrets.tmpl b/data/templates/ipsec/ipsec.secrets.j2 index 057e291ed..a87ac9bc7 100644 --- a/data/templates/ipsec/ipsec.secrets.tmpl +++ b/data/templates/ipsec/ipsec.secrets.j2 @@ -1,5 +1,5 @@ # Created by VyOS - manual changes will be overwritten -{% if include_ipsec_secrets is defined %} +{% if include_ipsec_secrets is vyos_defined %} include {{ include_ipsec_secrets }} -{% endif %} +{% endif %} diff --git a/data/templates/ipsec/swanctl.conf.j2 b/data/templates/ipsec/swanctl.conf.j2 new file mode 100644 index 000000000..bf6b8259c --- /dev/null +++ b/data/templates/ipsec/swanctl.conf.j2 @@ -0,0 +1,131 @@ +### Autogenerated by vpn_ipsec.py ### +{% import 'ipsec/swanctl/l2tp.j2' as l2tp_tmpl %} +{% import 'ipsec/swanctl/profile.j2' as profile_tmpl %} +{% import 'ipsec/swanctl/peer.j2' as peer_tmpl %} +{% import 'ipsec/swanctl/remote_access.j2' as remote_access_tmpl %} + +connections { +{% if profile is vyos_defined %} +{% for name, profile_conf in profile.items() if profile_conf.disable is not vyos_defined and profile_conf.bind.tunnel is vyos_defined %} +{{ profile_tmpl.conn(name, profile_conf, ike_group, esp_group) }} +{% endfor %} +{% endif %} +{% if site_to_site.peer is vyos_defined %} +{% for peer, peer_conf in site_to_site.peer.items() if peer not in dhcp_no_address and peer_conf.disable is not vyos_defined %} +{{ peer_tmpl.conn(peer, peer_conf, ike_group, esp_group) }} +{% endfor %} +{% endif %} +{% if remote_access.connection is vyos_defined %} +{% for rw, rw_conf in remote_access.connection.items() if rw_conf.disable is not vyos_defined %} +{{ remote_access_tmpl.conn(rw, rw_conf, ike_group, esp_group) }} +{% endfor %} +{% endif %} +{% if l2tp %} +{{ l2tp_tmpl.conn(l2tp, l2tp_outside_address, l2tp_ike_default, l2tp_esp_default, ike_group, esp_group) }} +{% endif %} +} + +pools { +{% if remote_access.pool is vyos_defined %} +{% for pool, pool_config in remote_access.pool.items() %} + {{ pool }} { +{% if pool_config.prefix is vyos_defined %} + addrs = {{ pool_config.prefix }} +{% endif %} +{% if pool_config.name_server is vyos_defined %} + dns = {{ pool_config.name_server | join(',') }} +{% endif %} +{% if pool_config.exclude is vyos_defined %} + split_exclude = {{ pool_config.exclude | join(',') }} +{% endif %} + } +{% endfor %} +{% endif %} +} + +secrets { +{% if profile is vyos_defined %} +{% for name, profile_conf in profile.items() if profile_conf.disable is not vyos_defined and profile_conf.bind.tunnel is vyos_defined %} +{% if profile_conf.authentication.mode is vyos_defined('pre-shared-secret') %} +{% for interface in profile_conf.bind.tunnel %} + ike-dmvpn-{{ interface }} { + secret = {{ profile_conf.authentication.pre_shared_secret }} + } +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +{% if site_to_site.peer is vyos_defined %} +{% for peer, peer_conf in site_to_site.peer.items() if peer not in dhcp_no_address and peer_conf.disable is not vyos_defined %} +{% set peer_name = peer.replace("@", "") | dot_colon_to_dash %} +{% if peer_conf.authentication.mode is vyos_defined('pre-shared-secret') %} + ike_{{ peer_name }} { +{% if peer_conf.local_address is vyos_defined %} + id-local = {{ peer_conf.local_address }} # dhcp:{{ peer_conf.dhcp_interface if 'dhcp_interface' in peer_conf else 'no' }} +{% endif %} + id-remote = {{ peer }} +{% if peer_conf.authentication.id is vyos_defined %} + id-localid = {{ peer_conf.authentication.id }} +{% endif %} +{% if peer_conf.authentication.remote_id is vyos_defined %} + id-remoteid = {{ peer_conf.authentication.remote_id }} +{% endif %} + secret = "{{ peer_conf.authentication.pre_shared_secret }}" + } +{% elif peer_conf.authentication.mode is vyos_defined('x509') %} + private_{{ peer_name }} { + file = {{ peer_conf.authentication.x509.certificate }}.pem +{% if peer_conf.authentication.x509.passphrase is vyos_defined %} + secret = "{{ peer_conf.authentication.x509.passphrase }}" +{% endif %} + } +{% elif peer_conf.authentication.mode is vyos_defined('rsa') %} + rsa_{{ peer_name }}_local { + file = {{ peer_conf.authentication.rsa.local_key }}.pem +{% if peer_conf.authentication.rsa.passphrase is vyos_defined %} + secret = "{{ peer_conf.authentication.rsa.passphrase }}" +{% endif %} + } +{% endif %} +{% endfor %} +{% endif %} +{% if remote_access.connection is vyos_defined %} +{% for ra, ra_conf in remote_access.connection.items() if ra_conf.disable is not vyos_defined %} +{% if ra_conf.authentication.server_mode is vyos_defined('pre-shared-secret') %} + ike_{{ ra }} { +{% if ra_conf.authentication.id is vyos_defined %} + id = "{{ ra_conf.authentication.id }}" +{% elif ra_conf.local_address is vyos_defined %} + id = "{{ ra_conf.local_address }}" +{% endif %} + secret = "{{ ra_conf.authentication.pre_shared_secret }}" + } +{% endif %} +{% if ra_conf.authentication.client_mode is vyos_defined('eap-mschapv2') and ra_conf.authentication.local_users.username is vyos_defined %} +{% for user, user_conf in ra_conf.authentication.local_users.username.items() if user_conf.disable is not vyos_defined %} + eap-{{ ra }}-{{ user }} { + secret = "{{ user_conf.password }}" + id-{{ ra }}-{{ user }} = "{{ user }}" + } +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} +{% if l2tp %} +{% if l2tp.authentication.mode is vyos_defined('pre-shared-secret') %} + ike_l2tp_remote_access { + id = "{{ l2tp_outside_address }}" + secret = "{{ l2tp.authentication.pre_shared_secret }}" + } +{% elif l2tp.authentication.mode is vyos_defined('x509') %} + private_l2tp_remote_access { + id = "{{ l2tp_outside_address }}" + file = {{ l2tp.authentication.x509.certificate }}.pem +{% if l2tp.authentication.x509.passphrase is vyos_defined %} + secret = "{{ l2tp.authentication.x509.passphrase }}" +{% endif %} + } +{% endif %} +{% endif %} +} + diff --git a/data/templates/ipsec/swanctl.conf.tmpl b/data/templates/ipsec/swanctl.conf.tmpl deleted file mode 100644 index 161f19f95..000000000 --- a/data/templates/ipsec/swanctl.conf.tmpl +++ /dev/null @@ -1,131 +0,0 @@ -### Autogenerated by vpn_ipsec.py ### -{% import 'ipsec/swanctl/l2tp.tmpl' as l2tp_tmpl %} -{% import 'ipsec/swanctl/profile.tmpl' as profile_tmpl %} -{% import 'ipsec/swanctl/peer.tmpl' as peer_tmpl %} -{% import 'ipsec/swanctl/remote_access.tmpl' as remote_access_tmpl %} - -connections { -{% if profile is defined %} -{% for name, profile_conf in profile.items() if profile_conf.disable is not defined and profile_conf.bind is defined and profile_conf.bind.tunnel is defined %} -{{ profile_tmpl.conn(name, profile_conf, ike_group, esp_group) }} -{% endfor %} -{% endif %} -{% if site_to_site is defined and site_to_site.peer is defined %} -{% for peer, peer_conf in site_to_site.peer.items() if peer not in dhcp_no_address and peer_conf.disable is not defined %} -{{ peer_tmpl.conn(peer, peer_conf, ike_group, esp_group) }} -{% endfor %} -{% endif %} -{% if remote_access is defined and remote_access.connection is defined and remote_access.connection is not none %} -{% for rw, rw_conf in remote_access.connection.items() if rw_conf.disable is not defined %} -{{ remote_access_tmpl.conn(rw, rw_conf, ike_group, esp_group) }} -{% endfor %} -{% endif %} -{% if l2tp %} -{{ l2tp_tmpl.conn(l2tp, l2tp_outside_address, l2tp_ike_default, l2tp_esp_default, ike_group, esp_group) }} -{% endif %} -} - -pools { -{% if remote_access is defined and remote_access.pool is defined and remote_access.pool is not none %} -{% for pool, pool_config in remote_access.pool.items() %} - {{ pool }} { -{% if pool_config.prefix is defined and pool_config.prefix is not none %} - addrs = {{ pool_config.prefix }} -{% endif %} -{% if pool_config.name_server is defined and pool_config.name_server is not none %} - dns = {{ pool_config.name_server | join(',') }} -{% endif %} -{% if pool_config.exclude is defined and pool_config.exclude is not none %} - split_exclude = {{ pool_config.exclude | join(',') }} -{% endif %} - } -{% endfor %} -{% endif %} -} - -secrets { -{% if profile is defined %} -{% for name, profile_conf in profile.items() if profile_conf.disable is not defined and profile_conf.bind is defined and profile_conf.bind.tunnel is defined %} -{% if profile_conf.authentication.mode == 'pre-shared-secret' %} -{% for interface in profile_conf.bind.tunnel %} - ike-dmvpn-{{ interface }} { - secret = {{ profile_conf.authentication.pre_shared_secret }} - } -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -{% if site_to_site is defined and site_to_site.peer is defined %} -{% for peer, peer_conf in site_to_site.peer.items() if peer not in dhcp_no_address and peer_conf.disable is not defined %} -{% set peer_name = peer.replace(".", "-").replace("@", "") %} -{% if peer_conf.authentication.mode == 'pre-shared-secret' %} - ike_{{ peer_name }} { -{% if peer_conf.local_address is defined %} - id-local = {{ peer_conf.local_address }} # dhcp:{{ peer_conf.dhcp_interface if 'dhcp_interface' in peer_conf else 'no' }} -{% endif %} - id-remote = {{ peer }} -{% if peer_conf.authentication.id is defined %} - id-localid = {{ peer_conf.authentication.id }} -{% endif %} -{% if peer_conf.authentication.remote_id is defined %} - id-remoteid = {{ peer_conf.authentication.remote_id }} -{% endif %} - secret = "{{ peer_conf.authentication.pre_shared_secret }}" - } -{% elif peer_conf.authentication.mode == 'x509' %} - private_{{ peer_name }} { - file = {{ peer_conf.authentication.x509.certificate }}.pem -{% if peer_conf.authentication.x509.passphrase is defined %} - secret = "{{ peer_conf.authentication.x509.passphrase }}" -{% endif %} - } -{% elif peer_conf.authentication.mode == 'rsa' %} - rsa_{{ peer_name }}_local { - file = {{ peer_conf.authentication.rsa.local_key }}.pem -{% if peer_conf.authentication.rsa.passphrase is defined %} - secret = "{{ peer_conf.authentication.rsa.passphrase }}" -{% endif %} - } -{% endif %} -{% endfor %} -{% endif %} -{% if remote_access is defined and remote_access.connection is defined and remote_access.connection is not none %} -{% for ra, ra_conf in remote_access.connection.items() if ra_conf.disable is not defined %} -{% if ra_conf.authentication.server_mode == 'pre-shared-secret' %} - ike_{{ ra }} { -{% if ra_conf.authentication.id is defined %} - id = "{{ ra_conf.authentication.id }}" -{% elif ra_conf.local_address is defined %} - id = "{{ ra_conf.local_address }}" -{% endif %} - secret = "{{ ra_conf.authentication.pre_shared_secret }}" - } -{% endif %} -{% if ra_conf.authentication.client_mode == 'eap-mschapv2' and ra_conf.authentication.local_users is defined and ra_conf.authentication.local_users.username is defined %} -{% for user, user_conf in ra_conf.authentication.local_users.username.items() if user_conf.disable is not defined %} - eap-{{ ra }}-{{ user }} { - secret = "{{ user_conf.password }}" - id-{{ ra }}-{{ user }} = "{{ user }}" - } -{% endfor %} -{% endif %} -{% endfor %} -{% endif %} -{% if l2tp %} -{% if l2tp.authentication.mode == 'pre-shared-secret' %} - ike_l2tp_remote_access { - id = "{{ l2tp_outside_address }}" - secret = "{{ l2tp.authentication.pre_shared_secret }}" - } -{% elif l2tp.authentication.mode == 'x509' %} - private_l2tp_remote_access { - id = "{{ l2tp_outside_address }}" - file = {{ l2tp.authentication.x509.certificate }}.pem -{% if l2tp.authentication.x509.passphrase is defined %} - secret = "{{ l2tp.authentication.x509.passphrase }}" -{% endif %} - } -{% endif %} -{% endif %} -} - diff --git a/data/templates/ipsec/swanctl/l2tp.tmpl b/data/templates/ipsec/swanctl/l2tp.j2 index 4cd1b4af3..7e63865cc 100644 --- a/data/templates/ipsec/swanctl/l2tp.tmpl +++ b/data/templates/ipsec/swanctl/l2tp.j2 @@ -1,6 +1,6 @@ {% macro conn(l2tp, l2tp_outside_address, l2tp_ike_default, l2tp_esp_default, ike_group, esp_group) %} -{% set l2tp_ike = ike_group[l2tp.ike_group] if l2tp.ike_group is defined else None %} -{% set l2tp_esp = esp_group[l2tp.esp_group] if l2tp.esp_group is defined else None %} +{% set l2tp_ike = ike_group[l2tp.ike_group] if l2tp.ike_group is vyos_defined else None %} +{% set l2tp_esp = esp_group[l2tp.esp_group] if l2tp.esp_group is vyos_defined else None %} l2tp_remote_access { proposals = {{ l2tp_ike | get_esp_ike_cipher | join(',') if l2tp_ike else l2tp_ike_default }} local_addrs = {{ l2tp_outside_address }} @@ -10,9 +10,9 @@ reauth_time = 0 local { auth = {{ 'psk' if l2tp.authentication.mode == 'pre-shared-secret' else 'pubkey' }} -{% if l2tp.authentication.mode == 'x509' %} +{% if l2tp.authentication.mode == 'x509' %} certs = {{ l2tp.authentication.x509.certificate }}.pem -{% endif %} +{% endif %} } remote { auth = {{ 'psk' if l2tp.authentication.mode == 'pre-shared-secret' else 'pubkey' }} diff --git a/data/templates/ipsec/swanctl/peer.j2 b/data/templates/ipsec/swanctl/peer.j2 new file mode 100644 index 000000000..90d2c774f --- /dev/null +++ b/data/templates/ipsec/swanctl/peer.j2 @@ -0,0 +1,166 @@ +{% macro conn(peer, peer_conf, ike_group, esp_group) %} +{% set name = peer.replace("@", "") | dot_colon_to_dash %} +{# peer needs to reference the global IKE configuration for certain values #} +{% set ike = ike_group[peer_conf.ike_group] %} + peer_{{ name }} { + proposals = {{ ike | get_esp_ike_cipher | join(',') }} + version = {{ ike.key_exchange[4:] if ike.key_exchange is vyos_defined else "0" }} +{% if peer_conf.virtual_address is vyos_defined %} + vips = {{ peer_conf.virtual_address | join(', ') }} +{% endif %} + local_addrs = {{ peer_conf.local_address if peer_conf.local_address != 'any' else '0.0.0.0/0' }} # dhcp:{{ peer_conf.dhcp_interface if 'dhcp_interface' in peer_conf else 'no' }} + remote_addrs = {{ peer if peer not in ['any', '0.0.0.0'] and peer[0:1] != '@' else '0.0.0.0/0' }} +{% if peer_conf.authentication.mode is vyos_defined('x509') %} + send_cert = always +{% endif %} +{% if ike.dead_peer_detection is vyos_defined %} + dpd_timeout = {{ ike.dead_peer_detection.timeout }} + dpd_delay = {{ ike.dead_peer_detection.interval }} +{% endif %} +{% if ike.key_exchange is vyos_defined('ikev1') and ike.mode is vyos_defined('aggressive') %} + aggressive = yes +{% endif %} + rekey_time = {{ ike.lifetime }}s + mobike = {{ "yes" if ike.mobike is not defined or ike.mobike == "enable" else "no" }} +{% if peer[0:1] == '@' %} + keyingtries = 0 + reauth_time = 0 +{% elif peer_conf.connection_type is not vyos_defined or peer_conf.connection_type is vyos_defined('initiate') %} + keyingtries = 0 +{% elif peer_conf.connection_type is vyos_defined('respond') %} + keyingtries = 1 +{% endif %} +{% if peer_conf.force_encapsulation is vyos_defined('enable') %} + encap = yes +{% endif %} + local { +{% if peer_conf.authentication.id is vyos_defined %} + id = "{{ peer_conf.authentication.id }}" +{% endif %} + auth = {{ 'psk' if peer_conf.authentication.mode == 'pre-shared-secret' else 'pubkey' }} +{% if peer_conf.authentication.mode == 'x509' %} + certs = {{ peer_conf.authentication.x509.certificate }}.pem +{% elif peer_conf.authentication.mode == 'rsa' %} + pubkeys = {{ peer_conf.authentication.rsa.local_key }}.pem +{% 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 +{% endif %} + } + children { +{% if peer_conf.vti.bind is vyos_defined and peer_conf.tunnel is not vyos_defined %} +{% set vti_esp = esp_group[ peer_conf.vti.esp_group ] if peer_conf.vti.esp_group is vyos_defined else esp_group[ peer_conf.default_esp_group ] %} + peer_{{ name }}_vti { + esp_proposals = {{ vti_esp | get_esp_ike_cipher(ike) | join(',') }} +{% if vti_esp.life_bytes is vyos_defined %} + life_bytes = {{ vti_esp.life_bytes }} +{% endif %} +{% if vti_esp.life_packets is vyos_defined %} + life_packets = {{ vti_esp.life_packets }} +{% endif %} + life_time = {{ vti_esp.lifetime }}s + local_ts = 0.0.0.0/0,::/0 + remote_ts = 0.0.0.0/0,::/0 + updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }}" +{# The key defaults to 0 and will match any policies which similarly do not have a lookup key configuration. #} +{# Thus we simply shift the key by one to also support a vti0 interface #} +{% set if_id = peer_conf.vti.bind | replace('vti', '') | int + 1 %} + if_id_in = {{ if_id }} + if_id_out = {{ if_id }} + ipcomp = {{ 'yes' if vti_esp.compression is vyos_defined('enable') else 'no' }} + mode = {{ vti_esp.mode }} +{% if peer[0:1] == '@' %} + start_action = none +{% elif peer_conf.connection_type is not vyos_defined or peer_conf.connection_type is vyos_defined('initiate') %} + start_action = start +{% elif peer_conf.connection_type is vyos_defined('respond') %} + start_action = trap +{% elif peer_conf.connection_type is vyos_defined('none') %} + start_action = none +{% endif %} +{% if ike.dead_peer_detection is vyos_defined %} +{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'restart'} %} + dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }} +{% endif %} + close_action = {{ {'none': 'none', 'hold': 'trap', 'restart': 'start'}[ike.close_action] }} + } +{% elif peer_conf.tunnel is vyos_defined %} +{% for tunnel_id, tunnel_conf in peer_conf.tunnel.items() if tunnel_conf.disable is not defined %} +{% set tunnel_esp_name = tunnel_conf.esp_group if tunnel_conf.esp_group is vyos_defined else peer_conf.default_esp_group %} +{% set tunnel_esp = esp_group[tunnel_esp_name] %} +{% set proto = tunnel_conf.protocol if tunnel_conf.protocol is vyos_defined else '' %} +{% set local_port = tunnel_conf.local.port if tunnel_conf.local.port is vyos_defined else '' %} +{% set local_suffix = '[{0}/{1}]'.format(proto, local_port) if proto or local_port else '' %} +{% set remote_port = tunnel_conf.remote.port if tunnel_conf.remote.port is vyos_defined else '' %} +{% set remote_suffix = '[{0}/{1}]'.format(proto, remote_port) if proto or remote_port else '' %} + peer_{{ name }}_tunnel_{{ tunnel_id }} { + esp_proposals = {{ tunnel_esp | get_esp_ike_cipher(ike) | join(',') }} +{% if tunnel_esp.life_bytes is vyos_defined %} + life_bytes = {{ tunnel_esp.life_bytes }} +{% endif %} +{% if tunnel_esp.life_packets is vyos_defined %} + life_packets = {{ tunnel_esp.life_packets }} +{% endif %} + life_time = {{ tunnel_esp.lifetime }}s +{% if tunnel_esp.mode is not defined or tunnel_esp.mode == 'tunnel' %} +{% if tunnel_conf.local.prefix is vyos_defined %} +{% set local_prefix = tunnel_conf.local.prefix if 'any' not in tunnel_conf.local.prefix else ['0.0.0.0/0', '::/0'] %} + local_ts = {{ local_prefix | join(local_suffix + ",") }}{{ local_suffix }} +{% endif %} +{% if tunnel_conf.remote.prefix is vyos_defined %} +{% set remote_prefix = tunnel_conf.remote.prefix if 'any' not in tunnel_conf.remote.prefix else ['0.0.0.0/0', '::/0'] %} + remote_ts = {{ remote_prefix | join(remote_suffix + ",") }}{{ remote_suffix }} +{% endif %} +{% if tunnel_conf.priority is vyos_defined %} + priority = {{ tunnel_conf.priority }} +{% endif %} +{% elif tunnel_esp.mode == 'transport' %} + local_ts = {{ peer_conf.local_address }}{{ local_suffix }} + remote_ts = {{ peer }}{{ remote_suffix }} +{% endif %} + ipcomp = {{ 'yes' if tunnel_esp.compression is vyos_defined('enable') else 'no' }} + mode = {{ tunnel_esp.mode }} +{% if peer[0:1] == '@' %} + start_action = none +{% elif peer_conf.connection_type is not vyos_defined or peer_conf.connection_type is vyos_defined('initiate') %} + start_action = start +{% elif peer_conf.connection_type is vyos_defined('respond') %} + start_action = trap +{% elif peer_conf.connection_type is vyos_defined('none') %} + start_action = none +{% endif %} +{% if ike.dead_peer_detection is vyos_defined %} +{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'restart'} %} + dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }} +{% endif %} + close_action = {{ {'none': 'none', 'hold': 'trap', 'restart': 'start'}[ike.close_action] }} +{% if peer_conf.vti.bind is vyos_defined %} +{# The key defaults to 0 and will match any policies which similarly do not have a lookup key configuration. #} +{# Thus we simply shift the key by one to also support a vti0 interface #} +{% set if_id = peer_conf.vti.bind | replace('vti', '') | int + 1 %} + updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }}" + if_id_in = {{ if_id }} + if_id_out = {{ if_id }} +{% endif %} + } +{% if tunnel_conf.passthrough is vyos_defined %} + peer_{{ name }}_tunnel_{{ tunnel_id }}_passthrough { + local_ts = {{ tunnel_conf.passthrough | join(",") }} + remote_ts = {{ tunnel_conf.passthrough | join(",") }} + start_action = trap + mode = pass + } +{% endif %} +{% endfor %} +{% endif %} + } + } +{% endmacro %} diff --git a/data/templates/ipsec/swanctl/peer.tmpl b/data/templates/ipsec/swanctl/peer.tmpl deleted file mode 100644 index 8c3776bf1..000000000 --- a/data/templates/ipsec/swanctl/peer.tmpl +++ /dev/null @@ -1,142 +0,0 @@ -{% macro conn(peer, peer_conf, ike_group, esp_group) %} -{% set name = peer.replace(".", "-").replace("@", "") %} -{# peer needs to reference the global IKE configuration for certain values #} -{% set ike = ike_group[peer_conf.ike_group] %} - peer_{{ name }} { - proposals = {{ ike | get_esp_ike_cipher | join(',') }} - version = {{ ike.key_exchange[4:] if ike is defined and ike.key_exchange is defined else "0" }} - local_addrs = {{ peer_conf.local_address if peer_conf.local_address != 'any' else '0.0.0.0/0' }} # dhcp:{{ peer_conf.dhcp_interface if 'dhcp_interface' in peer_conf else 'no' }} - remote_addrs = {{ peer if peer not in ['any', '0.0.0.0'] and peer[0:1] != '@' else '0.0.0.0/0' }} -{% if peer_conf.authentication is defined and peer_conf.authentication.mode is defined and peer_conf.authentication.mode == 'x509' %} - send_cert = always -{% endif %} -{% if ike.dead_peer_detection is defined %} - dpd_timeout = {{ ike.dead_peer_detection.timeout }} - dpd_delay = {{ ike.dead_peer_detection.interval }} -{% endif %} -{% if ike.key_exchange is defined and ike.key_exchange == "ikev1" and ike.mode is defined and ike.mode == "aggressive" %} - aggressive = yes -{% endif %} - rekey_time = {{ ike.lifetime }}s - mobike = {{ "yes" if ike.mobike is not defined or ike.mobike == "enable" else "no" }} -{% if peer[0:1] == '@' %} - keyingtries = 0 - reauth_time = 0 -{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %} - keyingtries = 0 -{% elif peer_conf.connection_type is defined and peer_conf.connection_type == 'respond' %} - keyingtries = 1 -{% endif %} -{% if peer_conf.force_encapsulation is defined and peer_conf.force_encapsulation == 'enable' %} - encap = yes -{% endif %} - local { -{% if peer_conf.authentication is defined and peer_conf.authentication.id is defined and peer_conf.authentication.id is not none %} - id = "{{ peer_conf.authentication.id }}" -{% endif %} - auth = {{ 'psk' if peer_conf.authentication.mode == 'pre-shared-secret' else 'pubkey' }} -{% if peer_conf.authentication.mode == 'x509' %} - certs = {{ peer_conf.authentication.x509.certificate }}.pem -{% elif peer_conf.authentication.mode == 'rsa' %} - pubkeys = {{ peer_conf.authentication.rsa.local_key }}.pem -{% endif %} - } - remote { -{% if peer_conf.authentication is defined and peer_conf.authentication.remote_id is defined and peer_conf.authentication.remote_id is not none %} - 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 -{% endif %} - } - children { -{% if peer_conf.vti is defined and peer_conf.vti.bind is defined and peer_conf.tunnel is not defined %} -{% set vti_esp = esp_group[ peer_conf.vti.esp_group ] if peer_conf.vti.esp_group is defined else esp_group[ peer_conf.default_esp_group ] %} - peer_{{ name }}_vti { - esp_proposals = {{ vti_esp | get_esp_ike_cipher(ike) | join(',') }} - life_time = {{ vti_esp.lifetime }}s - local_ts = 0.0.0.0/0,::/0 - remote_ts = 0.0.0.0/0,::/0 - updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }}" - {# The key defaults to 0 and will match any policies which similarly do not have a lookup key configuration. #} - {# Thus we simply shift the key by one to also support a vti0 interface #} -{% set if_id = peer_conf.vti.bind | replace('vti', '') | int +1 %} - if_id_in = {{ if_id }} - if_id_out = {{ if_id }} - ipcomp = {{ 'yes' if vti_esp.compression is defined and vti_esp.compression == 'enable' else 'no' }} - mode = {{ vti_esp.mode }} -{% if peer[0:1] == '@' %} - start_action = none -{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %} - start_action = start -{% elif peer_conf.connection_type == 'respond' %} - start_action = trap -{% endif %} -{% if ike.dead_peer_detection is defined %} -{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'start'} %} - dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }} -{% endif %} - } -{% elif peer_conf.tunnel is defined %} -{% for tunnel_id, tunnel_conf in peer_conf.tunnel.items() if tunnel_conf.disable is not defined %} -{% set tunnel_esp_name = tunnel_conf.esp_group if tunnel_conf.esp_group is defined else peer_conf.default_esp_group %} -{% set tunnel_esp = esp_group[tunnel_esp_name] %} -{% set proto = tunnel_conf.protocol if tunnel_conf.protocol is defined else '' %} -{% set local_port = tunnel_conf.local.port if tunnel_conf.local is defined and tunnel_conf.local.port is defined else '' %} -{% set local_suffix = '[{0}/{1}]'.format(proto, local_port) if proto or local_port else '' %} -{% set remote_port = tunnel_conf.remote.port if tunnel_conf.remote is defined and tunnel_conf.remote.port is defined else '' %} -{% set remote_suffix = '[{0}/{1}]'.format(proto, remote_port) if proto or remote_port else '' %} - peer_{{ name }}_tunnel_{{ tunnel_id }} { - esp_proposals = {{ tunnel_esp | get_esp_ike_cipher(ike) | join(',') }} - life_time = {{ tunnel_esp.lifetime }}s -{% if tunnel_esp.mode is not defined or tunnel_esp.mode == 'tunnel' %} -{% if tunnel_conf.local is defined and tunnel_conf.local.prefix is defined %} -{% set local_prefix = tunnel_conf.local.prefix if 'any' not in tunnel_conf.local.prefix else ['0.0.0.0/0', '::/0'] %} - local_ts = {{ local_prefix | join(local_suffix + ",") }}{{ local_suffix }} -{% endif %} -{% if tunnel_conf.remote is defined and tunnel_conf.remote.prefix is defined %} -{% set remote_prefix = tunnel_conf.remote.prefix if 'any' not in tunnel_conf.remote.prefix else ['0.0.0.0/0', '::/0'] %} - remote_ts = {{ remote_prefix | join(remote_suffix + ",") }}{{ remote_suffix }} -{% endif %} -{% elif tunnel_esp.mode == 'transport' %} - local_ts = {{ peer_conf.local_address }}{{ local_suffix }} - remote_ts = {{ peer }}{{ remote_suffix }} -{% endif %} - ipcomp = {{ 'yes' if tunnel_esp.compression is defined and tunnel_esp.compression == 'enable' else 'no' }} - mode = {{ tunnel_esp.mode }} -{% if peer[0:1] == '@' %} - start_action = none -{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %} - start_action = start -{% elif peer_conf.connection_type == 'respond' %} - start_action = trap -{% endif %} -{% if ike.dead_peer_detection is defined %} -{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'start'} %} - dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }} -{% endif %} -{% if peer_conf.vti is defined and peer_conf.vti.bind is defined %} - updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }}" - {# The key defaults to 0 and will match any policies which similarly do not have a lookup key configuration. #} - {# Thus we simply shift the key by one to also support a vti0 interface #} -{% set if_id = peer_conf.vti.bind | replace('vti', '') | int +1 %} - if_id_in = {{ if_id }} - if_id_out = {{ if_id }} -{% endif %} - } -{% if tunnel_conf.passthrough is defined and tunnel_conf.passthrough %} - peer_{{ name }}_tunnel_{{ tunnel_id }}_passthough { - local_ts = {{ tunnel_conf.passthrough | join(",") }} - remote_ts = {{ tunnel_conf.passthrough | join(",") }} - start_action = trap - mode = pass - } -{% endif %} -{% endfor %} -{% endif %} - } - } -{% endmacro %} diff --git a/data/templates/ipsec/swanctl/profile.tmpl b/data/templates/ipsec/swanctl/profile.j2 index a5cae31c0..d4f417378 100644 --- a/data/templates/ipsec/swanctl/profile.tmpl +++ b/data/templates/ipsec/swanctl/profile.j2 @@ -1,39 +1,39 @@ {% macro conn(name, profile_conf, ike_group, esp_group) %} -{# peer needs to reference the global IKE configuration for certain values #} -{% set ike = ike_group[profile_conf.ike_group] %} -{% set esp = esp_group[profile_conf.esp_group] %} -{% if profile_conf.bind is defined and profile_conf.bind.tunnel is defined %} +{# peer needs to reference the global IKE configuration for certain values #} +{% set ike = ike_group[profile_conf.ike_group] %} +{% set esp = esp_group[profile_conf.esp_group] %} +{% if profile_conf.bind.tunnel is vyos_defined %} {% for interface in profile_conf.bind.tunnel %} dmvpn-{{ name }}-{{ interface }} { proposals = {{ ike_group[profile_conf.ike_group] | get_esp_ike_cipher | join(',') }} - version = {{ ike.key_exchange[4:] if ike is defined and ike.key_exchange is defined else "0" }} + version = {{ ike.key_exchange[4:] if ike.key_exchange is vyos_defined else "0" }} rekey_time = {{ ike.lifetime }}s keyingtries = 0 -{% if profile_conf.authentication is defined and profile_conf.authentication.mode is defined and profile_conf.authentication.mode == 'pre-shared-secret' %} +{% if profile_conf.authentication.mode is vyos_defined('pre-shared-secret') %} local { auth = psk } remote { auth = psk } -{% endif %} +{% endif %} children { dmvpn { - esp_proposals = {{ esp | get_esp_ike_cipher(ike) | join(',') }} + esp_proposals = {{ esp | get_esp_ike_cipher(ike) | join(',') }} rekey_time = {{ esp.lifetime }}s rand_time = 540s local_ts = dynamic[gre] remote_ts = dynamic[gre] mode = {{ esp.mode }} -{% if ike.dead_peer_detection is defined and ike.dead_peer_detection.action is defined %} +{% if ike.dead_peer_detection.action is vyos_defined %} dpd_action = {{ ike.dead_peer_detection.action }} -{% endif %} -{% if esp.compression is defined and esp.compression == 'enable' %} +{% endif %} +{% if esp.compression is vyos_defined('enable') %} ipcomp = yes -{% endif %} +{% endif %} } } } {% endfor %} -{% endif %} +{% endif %} {% endmacro %} diff --git a/data/templates/ipsec/swanctl/remote_access.tmpl b/data/templates/ipsec/swanctl/remote_access.j2 index 6354c60b1..d2760ec1f 100644 --- a/data/templates/ipsec/swanctl/remote_access.tmpl +++ b/data/templates/ipsec/swanctl/remote_access.j2 @@ -1,37 +1,38 @@ {% macro conn(name, rw_conf, ike_group, esp_group) %} -{# peer needs to reference the global IKE configuration for certain values #} -{% set ike = ike_group[rw_conf.ike_group] %} -{% set esp = esp_group[rw_conf.esp_group] %} +{# peer needs to reference the global IKE configuration for certain values #} +{% set ike = ike_group[rw_conf.ike_group] %} +{% set esp = esp_group[rw_conf.esp_group] %} ra-{{ name }} { remote_addrs = %any - local_addrs = {{ rw_conf.local_address if rw_conf.local_address is defined else '%any' }} + local_addrs = {{ rw_conf.local_address if rw_conf.local_address is vyos_defined else '%any' }} proposals = {{ ike_group[rw_conf.ike_group] | get_esp_ike_cipher | join(',') }} - version = {{ ike.key_exchange[4:] if ike is defined and ike.key_exchange is defined else "0" }} + version = {{ ike.key_exchange[4:] if ike.key_exchange is vyos_defined else "0" }} send_certreq = no rekey_time = {{ ike.lifetime }}s keyingtries = 0 -{% if rw_conf.unique is defined and rw_conf.unique is not none %} +{% if rw_conf.unique is vyos_defined %} unique = {{ rw_conf.unique }} -{% endif %} -{% if rw_conf.pool is defined and rw_conf.pool is not none %} +{% endif %} +{% if rw_conf.pool is vyos_defined %} pools = {{ rw_conf.pool | join(',') }} -{% endif %} +{% endif %} local { -{% if rw_conf.authentication.id is defined and rw_conf.authentication.use_x509_id is not defined %} +{% if rw_conf.authentication.id is vyos_defined and rw_conf.authentication.use_x509_id is not vyos_defined %} +{# please use " quotes - else Apple iOS goes crazy #} id = "{{ rw_conf.authentication.id }}" -{% endif %} -{% if rw_conf.authentication.server_mode == 'x509' %} +{% endif %} +{% if rw_conf.authentication.server_mode == 'x509' %} auth = pubkey certs = {{ rw_conf.authentication.x509.certificate }}.pem -{% elif rw_conf.authentication.server_mode == 'pre-shared-secret' %} +{% elif rw_conf.authentication.server_mode == 'pre-shared-secret' %} auth = psk -{% endif %} +{% endif %} } remote { auth = {{ rw_conf.authentication.client_mode }} -{% if rw_conf.authentication.client_mode.startswith("eap") %} +{% if rw_conf.authentication.client_mode.startswith("eap") %} eap_id = %any -{% endif %} +{% endif %} } children { ikev2-vpn { @@ -40,9 +41,9 @@ rand_time = 540s dpd_action = clear inactivity = {{ rw_conf.timeout }} -{% set local_prefix = rw_conf.local.prefix if rw_conf.local is defined and rw_conf.local.prefix is defined else ['0.0.0.0/0', '::/0'] %} -{% set local_port = rw_conf.local.port if rw_conf.local is defined and rw_conf.local.port is defined else '' %} -{% set local_suffix = '[%any/{1}]'.format(local_port) if local_port else '' %} +{% set local_prefix = rw_conf.local.prefix if rw_conf.local.prefix is vyos_defined else ['0.0.0.0/0', '::/0'] %} +{% set local_port = rw_conf.local.port if rw_conf.local.port is vyos_defined else '' %} +{% set local_suffix = '[%any/{1}]'.format(local_port) if local_port else '' %} local_ts = {{ local_prefix | join(local_suffix + ",") }}{{ local_suffix }} } } diff --git a/data/templates/ipsec/windows_profile.tmpl b/data/templates/ipsec/windows_profile.j2 index 8c26944be..8c26944be 100644 --- a/data/templates/ipsec/windows_profile.tmpl +++ b/data/templates/ipsec/windows_profile.j2 diff --git a/data/templates/lcd/LCDd.conf.tmpl b/data/templates/lcd/LCDd.conf.j2 index 2c7ad920f..3631add1d 100644 --- a/data/templates/lcd/LCDd.conf.tmpl +++ b/data/templates/lcd/LCDd.conf.j2 @@ -48,14 +48,14 @@ DriverPath=/usr/lib/x86_64-linux-gnu/lcdproc/ # sed1520, serialPOS, serialVFD, shuttleVFD, sli, stv5730, svga, t6963, # text, tyan, ula200, vlsys_m428, xosd, yard2LCD -{% if model is defined %} -{% if model.startswith('cfa-') %} +{% if model is vyos_defined %} +{% if model.startswith('cfa-') %} Driver=CFontzPacket -{% elif model == 'sdec' %} +{% elif model == 'sdec' %} Driver=sdeclcd -{% elif model == 'hd44780' %} +{% elif model == 'hd44780' %} Driver=hd44780 -{% endif %} +{% endif %} {% endif %} # Tells the driver to bind to the given interface. [default: 127.0.0.1] @@ -115,8 +115,8 @@ Heartbeat=off # set title scrolling speed [default: 10; legal: 0-10] TitleSpeed=10 -{% if model is defined and model is not none %} -{% if model.startswith('cfa-') %} +{% if model is vyos_defined %} +{% if model.startswith('cfa-') %} ## CrystalFontz packet driver (for CFA533, CFA631, CFA633 & CFA635) ## [CFontzPacket] Model={{ model.split('-')[1] }} @@ -126,14 +126,14 @@ Brightness=500 OffBrightness=50 Reboot=yes USB=yes -{% elif model == 'sdec' %} +{% elif model == 'sdec' %} ## SDEC driver for Lanner, Watchguard, Sophos sppliances ## [sdeclcd] # No options -{% elif model == 'hd44780' %} +{% elif model == 'hd44780' %} [hd44780] ConnectionType=ezio Device={{ device }} Size=16x2 -{% endif %} +{% endif %} {% endif %} diff --git a/data/templates/lcd/lcdproc.conf.tmpl b/data/templates/lcd/lcdproc.conf.j2 index c79f3cd0d..c79f3cd0d 100644 --- a/data/templates/lcd/lcdproc.conf.tmpl +++ b/data/templates/lcd/lcdproc.conf.j2 diff --git a/data/templates/lldp/lldpd.j2 b/data/templates/lldp/lldpd.j2 new file mode 100644 index 000000000..3c499197d --- /dev/null +++ b/data/templates/lldp/lldpd.j2 @@ -0,0 +1,2 @@ +### Autogenerated by lldp.py ### +DAEMON_ARGS="-M 4 {{ '-x' if snmp.enable is vyos_defined }} {{ '-c' if legacy_protocols.cdp is vyos_defined }} {{ '-e' if legacy_protocols.edp is vyos_defined }} {{ '-f' if legacy_protocols.fdp is vyos_defined }} {{ '-s' if legacy_protocols.sonmp is vyos_defined }}" diff --git a/data/templates/lldp/lldpd.tmpl b/data/templates/lldp/lldpd.tmpl deleted file mode 100644 index 3db955b48..000000000 --- a/data/templates/lldp/lldpd.tmpl +++ /dev/null @@ -1,3 +0,0 @@ -### Autogenerated by lldp.py ### -DAEMON_ARGS="-M 4{% if options.snmp %} -x{% endif %}{% if options.cdp %} -c{% endif %}{% if options.edp %} -e{% endif %}{% if options.fdp %} -f{% endif %}{% if options.sonmp %} -s{% endif %}" - diff --git a/data/templates/lldp/vyos.conf.j2 b/data/templates/lldp/vyos.conf.j2 new file mode 100644 index 000000000..ec84231d8 --- /dev/null +++ b/data/templates/lldp/vyos.conf.j2 @@ -0,0 +1,25 @@ +### Autogenerated by lldp.py ### + +configure system platform VyOS +configure system description "VyOS {{ version }}" +{% if interface is vyos_defined %} +{% set tmp = [] %} +{% for iface, iface_options in interface.items() if not iface_options.disable %} +{% if iface == 'all' %} +{% set iface = '*' %} +{% endif %} +{% set _ = tmp.append(iface) %} +{% if iface_options.location is vyos_defined %} +{% if iface_options.location.elin is vyos_defined %} +configure ports {{ iface }} med location elin "{{ iface_options.location.elin }}" +{% endif %} +{% if iface_options.location.coordinate_based is vyos_defined %} +configure ports {{ iface }} med location coordinate latitude "{{ iface_options.location.coordinate_based.latitude }}" longitude "{{ iface_options.location.coordinate_based.longitude }}" altitude "{{ iface_options.location.coordinate_based.altitude }}m" datum "{{ iface_options.location.coordinate_based.datum }}" +{% endif %} +{% endif %} +{% endfor %} +configure system interface pattern "{{ tmp | join(",") }}" +{% endif %} +{% if management_address is vyos_defined %} +configure system ip management pattern {{ management_address | join(",") }} +{% endif %} diff --git a/data/templates/lldp/vyos.conf.tmpl b/data/templates/lldp/vyos.conf.tmpl deleted file mode 100644 index 07bbaf604..000000000 --- a/data/templates/lldp/vyos.conf.tmpl +++ /dev/null @@ -1,20 +0,0 @@ -### Autogenerated by lldp.py ### - -configure system platform VyOS -configure system description "VyOS {{ options.description }}" -{% if options.listen_on %} -configure system interface pattern "{{ ( options.listen_on | select('equalto','all') | map('replace','all','*') | list + options.listen_on | select('equalto','!all') | map('replace','!all','!*') | list + options.listen_on | reject('equalto','all') | reject('equalto','!all') | list ) | unique | join(",") }}" -{% endif %} -{% if options.mgmt_addr %} -configure system ip management pattern {{ options.mgmt_addr | join(",") }} -{% endif %} -{% for loc in location %} -{% if loc.elin %} -configure ports {{ loc.name }} med location elin "{{ loc.elin }}" -{% endif %} -{% if loc.coordinate_based %} -configure ports {{ loc.name }} med location coordinate {% if loc.coordinate_based.latitude %}latitude {{ loc.coordinate_based.latitude }}{% endif %} {% if loc.coordinate_based.longitude %}longitude {{ loc.coordinate_based.longitude }}{% endif %} {% if loc.coordinate_based.altitude %}altitude {{ loc.coordinate_based.altitude }} m{% endif %} {% if loc.coordinate_based.datum %}datum {{ loc.coordinate_based.datum }}{% endif %} -{% endif %} - - -{% endfor %} diff --git a/data/templates/login/authorized_keys.j2 b/data/templates/login/authorized_keys.j2 new file mode 100644 index 000000000..aabca47cf --- /dev/null +++ b/data/templates/login/authorized_keys.j2 @@ -0,0 +1,9 @@ +### Automatically generated by system-login.py ### + +{% if authentication.public_keys is vyos_defined %} +{% for key, key_options in authentication.public_keys.items() %} +{# The whitespace after options is wisely chosen #} +{{ key_options.options ~ ' ' if key_options.options is vyos_defined }}{{ key_options.type }} {{ key_options.key }} {{ key }} +{% endfor %} +{% endif %} + diff --git a/data/templates/login/authorized_keys.tmpl b/data/templates/login/authorized_keys.tmpl deleted file mode 100644 index 639a80e1d..000000000 --- a/data/templates/login/authorized_keys.tmpl +++ /dev/null @@ -1,9 +0,0 @@ -### Automatically generated by system-login.py ### - -{% if authentication is defined and authentication.public_keys is defined and authentication.public_keys is not none %} -{% for key, key_options in authentication.public_keys.items() %} -{# The whitespace after options is wisely chosen #} -{{ key_options.options + ' ' if key_options.options is defined }}{{ key_options.type }} {{ key_options.key }} {{ key }} -{% endfor %} -{% endif %} - diff --git a/data/templates/login/pam_radius_auth.conf.j2 b/data/templates/login/pam_radius_auth.conf.j2 new file mode 100644 index 000000000..1105b60e5 --- /dev/null +++ b/data/templates/login/pam_radius_auth.conf.j2 @@ -0,0 +1,36 @@ +# Automatically generated by system-login.py +# RADIUS configuration file + +{% if radius is vyos_defined %} +{# RADIUS IPv6 source address must be specified in [] notation #} +{% set source_address = namespace() %} +{% if radius.source_address is vyos_defined %} +{% for address in radius.source_address %} +{% if address | is_ipv4 %} +{% set source_address.ipv4 = address %} +{% elif address | is_ipv6 %} +{% set source_address.ipv6 = "[" + address + "]" %} +{% endif %} +{% endfor %} +{% endif %} +{% if radius.server is vyos_defined %} +# server[:port] shared_secret timeout source_ip +{# .items() returns a tuple of two elements: key and value. 1 relates to the 2nd element i.e. the value and .priority relates to the key from the internal dict #} +{% for server, options in radius.server.items() | sort(attribute='1.priority') if not options.disabled %} +{# RADIUS IPv6 servers must be specified in [] notation #} +{% if server | is_ipv4 %} +{{ server }}:{{ options.port }} {{ "%-25s" | format(options.key) }} {{ "%-10s" | format(options.timeout) }} {{ source_address.ipv4 if source_address.ipv4 is vyos_defined }} +{% else %} +[{{ server }}]:{{ options.port }} {{ "%-25s" | format(options.key) }} {{ "%-10s" | format(options.timeout) }} {{ source_address.ipv6 if source_address.ipv6 is vyos_defined }} +{% endif %} +{% endfor %} +{% endif %} + +priv-lvl 15 +mapped_priv_user radius_priv_user + +{% if radius.vrf is vyos_defined %} +vrf-name {{ radius.vrf }} +{% endif %} +{% endif %} + diff --git a/data/templates/login/pam_radius_auth.conf.tmpl b/data/templates/login/pam_radius_auth.conf.tmpl deleted file mode 100644 index fad8e7dcb..000000000 --- a/data/templates/login/pam_radius_auth.conf.tmpl +++ /dev/null @@ -1,36 +0,0 @@ -# Automatically generated by system-login.py -# RADIUS configuration file - -{% if radius is defined and radius is not none %} -{# RADIUS IPv6 source address must be specified in [] notation #} -{% set source_address = namespace() %} -{% if radius.source_address is defined and radius.source_address is not none %} -{% for address in radius.source_address %} -{% if address | is_ipv4 %} -{% set source_address.ipv4 = address %} -{% elif address | is_ipv6 %} -{% set source_address.ipv6 = "[" + address + "]" %} -{% endif %} -{% endfor %} -{% endif %} -{% if radius.server is defined and radius.server is not none %} -# server[:port] shared_secret timeout source_ip -{# .items() returns a tuple of two elements: key and value. 1 relates to the 2nd element i.e. the value and .priority relates to the key from the internal dict #} -{% for server, options in radius.server.items() | sort(attribute='1.priority') if not options.disabled %} -{# RADIUS IPv6 servers must be specified in [] notation #} -{% if server | is_ipv4 %} -{{ server }}:{{ options.port }} {{ "%-25s" | format(options.key) }} {{ "%-10s" | format(options.timeout) }} {{ source_address.ipv4 if source_address.ipv4 is defined }} -{% else %} -[{{ server }}]:{{ options.port }} {{ "%-25s" | format(options.key) }} {{ "%-10s" | format(options.timeout) }} {{ source_address.ipv6 if source_address.ipv6 is defined }} -{% endif %} -{% endfor %} -{% endif %} - -priv-lvl 15 -mapped_priv_user radius_priv_user - -{% if radius.vrf is defined and radius.vrf is not none %} -vrf-name {{ radius.vrf }} -{% endif %} -{% endif %} - diff --git a/data/templates/logs/logrotate/vyos-atop.j2 b/data/templates/logs/logrotate/vyos-atop.j2 new file mode 100644 index 000000000..2d078f379 --- /dev/null +++ b/data/templates/logs/logrotate/vyos-atop.j2 @@ -0,0 +1,20 @@ +/var/log/atop/atop.log { + daily + dateext + dateformat _%Y-%m-%d_%H-%M-%S + maxsize {{ max_size }}M + missingok + nocompress + nocreate + nomail + rotate {{ rotate }} + prerotate + # stop the service + systemctl stop atop.service + endscript + postrotate + # start atop service again + systemctl start atop.service + endscript +} + diff --git a/data/templates/logs/logrotate/vyos-rsyslog.j2 b/data/templates/logs/logrotate/vyos-rsyslog.j2 new file mode 100644 index 000000000..f2e4d2ab2 --- /dev/null +++ b/data/templates/logs/logrotate/vyos-rsyslog.j2 @@ -0,0 +1,13 @@ +/var/log/messages { + create + missingok + nomail + notifempty + rotate {{ rotate }} + size {{ max_size }}M + postrotate + # inform rsyslog service about rotation + /usr/lib/rsyslog/rsyslog-rotate + endscript +} + diff --git a/data/templates/macsec/wpa_supplicant.conf.tmpl b/data/templates/macsec/wpa_supplicant.conf.j2 index 5b353def8..0ac7cb860 100644 --- a/data/templates/macsec/wpa_supplicant.conf.tmpl +++ b/data/templates/macsec/wpa_supplicant.conf.j2 @@ -45,10 +45,9 @@ network={ # - the key server has decided to enable MACsec # 0: Encrypt traffic (default) # 1: Integrity only - macsec_integ_only={{ '0' if security is defined and security.encrypt is defined else '1' }} + macsec_integ_only={{ '0' if security.encrypt is vyos_defined else '1' }} -{% if security is defined %} -{% if security.encrypt is defined %} +{% if security.encrypt is vyos_defined %} # mka_cak, mka_ckn, and mka_priority: IEEE 802.1X/MACsec pre-shared key mode # This allows to configure MACsec with a pre-shared key using a (CAK,CKN) pair. # In this mode, instances of wpa_supplicant can act as MACsec peers. The peer @@ -63,9 +62,9 @@ network={ # mka_priority (Priority of MKA Actor) is in 0..255 range with 255 being # default priority mka_priority={{ security.mka.priority }} -{% endif %} +{% endif %} -{% if security.replay_window is defined %} +{% if security.replay_window is vyos_defined %} # macsec_replay_protect: IEEE 802.1X/MACsec replay protection # This setting applies only when MACsec is in use, i.e., # - macsec_policy is enabled @@ -83,7 +82,6 @@ network={ # 0: No replay window, strict check (default) # 1..2^32-1: number of packets that could be misordered macsec_replay_window={{ security.replay_window }} -{% endif %} {% endif %} } diff --git a/data/templates/mdns-repeater/avahi-daemon.tmpl b/data/templates/mdns-repeater/avahi-daemon.j2 index 65bb5a306..65bb5a306 100644 --- a/data/templates/mdns-repeater/avahi-daemon.tmpl +++ b/data/templates/mdns-repeater/avahi-daemon.j2 diff --git a/data/templates/monitoring/override.conf.j2 b/data/templates/monitoring/override.conf.j2 new file mode 100644 index 000000000..f8f150791 --- /dev/null +++ b/data/templates/monitoring/override.conf.j2 @@ -0,0 +1,7 @@ +[Unit] +After=vyos-router.service +ConditionPathExists=/run/telegraf/vyos-telegraf.conf +[Service] +Environment=INFLUX_TOKEN={{ authentication.token }} +CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_ADMIN +AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN diff --git a/data/templates/monitoring/syslog_telegraf.j2 b/data/templates/monitoring/syslog_telegraf.j2 new file mode 100644 index 000000000..cdcbd92a4 --- /dev/null +++ b/data/templates/monitoring/syslog_telegraf.j2 @@ -0,0 +1,5 @@ +# Generated by /usr/libexec/vyos/conf_mode/service_monitoring_telegraf.py + +$ModLoad omuxsock +$OMUxSockSocket /run/telegraf/telegraf_syslog.sock +*.notice :omuxsock: diff --git a/data/templates/monitoring/systemd_vyos_telegraf_service.j2 b/data/templates/monitoring/systemd_vyos_telegraf_service.j2 new file mode 100644 index 000000000..234ef5586 --- /dev/null +++ b/data/templates/monitoring/systemd_vyos_telegraf_service.j2 @@ -0,0 +1,16 @@ +[Unit] +Description=The plugin-driven server agent for reporting metrics into InfluxDB +Documentation=https://github.com/influxdata/telegraf +After=network.target + +[Service] +EnvironmentFile=-/etc/default/telegraf +User=telegraf +ExecStart=/usr/bin/telegraf -config /run/telegraf/vyos-telegraf.conf -config-directory /etc/telegraf/telegraf.d $TELEGRAF_OPTS +ExecReload=/bin/kill -HUP $MAINPID +Restart=on-failure +RestartForceExitStatus=SIGPIPE +KillMode=control-group + +[Install] +WantedBy=multi-user.target diff --git a/data/templates/monitoring/telegraf.j2 b/data/templates/monitoring/telegraf.j2 new file mode 100644 index 000000000..a732fb5de --- /dev/null +++ b/data/templates/monitoring/telegraf.j2 @@ -0,0 +1,122 @@ +# Generated by /usr/libexec/vyos/conf_mode/service_monitoring_telegraf.py + +[agent] + interval = "15s" + round_interval = true + metric_batch_size = 1000 + metric_buffer_limit = 10000 + collection_jitter = "5s" + flush_interval = "15s" + flush_jitter = "0s" + precision = "" + debug = false + quiet = false + logfile = "" + hostname = "" + omit_hostname = false +{% if azure_data_explorer is vyos_defined %} +### Azure Data Explorer ### +[[outputs.azure_data_explorer]] + ## The URI property of the Azure Data Explorer resource on Azure + endpoint_url = "{{ azure_data_explorer.url }}" + + ## The Azure Data Explorer database that the metrics will be ingested into. + ## The plugin will NOT generate this database automatically, it's expected that this database already exists before ingestion. + database = "{{ azure_data_explorer.database }}" + metrics_grouping_type = "{{ azure_data_explorer.group_metrics }}" + + ## Name of the single table to store all the metrics (Only needed if metrics_grouping_type is "SingleTable"). +{% if azure_data_explorer.table is vyos_defined and azure_data_explorer.group_metrics == 'SingleTable' %} + table_name = "{{ azure_data_explorer.table }}" +{% endif %} +### End Azure Data Explorer ### +{% endif %} +{% if influxdb_configured is vyos_defined %} +### InfluxDB2 ### +[[outputs.influxdb_v2]] + urls = ["{{ url }}:{{ port }}"] + insecure_skip_verify = true + token = "$INFLUX_TOKEN" + organization = "{{ authentication.organization }}" + bucket = "{{ bucket }}" +### End InfluxDB2 ### +{% endif %} +{% if prometheus_client is vyos_defined %} +### Prometheus ### +[[outputs.prometheus_client]] + ## Address to listen on + listen = "{{ prometheus_client.listen_address if prometheus_client.listen_address is vyos_defined else '' }}:{{ prometheus_client.port }}" + metric_version = {{ prometheus_client.metric_version }} +{% if prometheus_client.authentication.username is vyos_defined and prometheus_client.authentication.password is vyos_defined %} + ## Use HTTP Basic Authentication + basic_username = "{{ prometheus_client.authentication.username }}" + basic_password = "{{ prometheus_client.authentication.password }}" +{% endif %} +{% if prometheus_client.allow_from is vyos_defined %} + ip_range = {{ prometheus_client.allow_from }} +{% endif %} +### End Prometheus ### +{% endif %} +{% if splunk is vyos_defined %} +### Splunk ### +[[outputs.http]] + ## URL is the address to send metrics to + url = "{{ splunk.url }}" + ## Timeout for HTTP message + # timeout = "5s" + ## Use TLS but skip chain & host verification +{% if splunk.authentication.insecure is vyos_defined %} + insecure_skip_verify = true +{% endif %} + ## Data format to output + data_format = "splunkmetric" + ## Provides time, index, source overrides for the HEC + splunkmetric_hec_routing = true + ## Additional HTTP headers + [outputs.http.headers] + # Should be set manually to "application/json" for json data_format + Content-Type = "application/json" + Authorization = "Splunk {{ splunk.authentication.token }}" + X-Splunk-Request-Channel = "{{ splunk.authentication.token }}" +### End Splunk ### +{% endif %} +[[inputs.cpu]] + percpu = true + totalcpu = true + collect_cpu_time = false + report_active = false +[[inputs.disk]] + ignore_fs = ["devtmpfs", "devfs"] +[[inputs.diskio]] +[[inputs.mem]] +[[inputs.net]] +[[inputs.system]] +[[inputs.netstat]] +[[inputs.processes]] +[[inputs.kernel]] +[[inputs.interrupts]] +[[inputs.linux_sysctl_fs]] +[[inputs.systemd_units]] +[[inputs.conntrack]] + files = ["ip_conntrack_count","ip_conntrack_max","nf_conntrack_count","nf_conntrack_max"] + dirs = ["/proc/sys/net/ipv4/netfilter","/proc/sys/net/netfilter"] +[[inputs.ethtool]] + interface_include = {{ interfaces_ethernet }} +[[inputs.ntpq]] + dns_lookup = true +[[inputs.internal]] +[[inputs.nstat]] +[[inputs.syslog]] + server = "unixgram:///run/telegraf/telegraf_syslog.sock" + best_effort = true + syslog_standard = "RFC3164" +{% if influxdb_configured is vyos_defined %} +[[inputs.exec]] + commands = [ + "{{ custom_scripts_dir }}/show_firewall_input_filter.py", + "{{ custom_scripts_dir }}/show_interfaces_input_filter.py", + "{{ custom_scripts_dir }}/vyos_services_input_filter.py" + ] + timeout = "10s" + data_format = "influx" +{% endif %} diff --git a/data/templates/ndppd/ndppd.conf.j2 b/data/templates/ndppd/ndppd.conf.j2 new file mode 100644 index 000000000..120fa0a64 --- /dev/null +++ b/data/templates/ndppd/ndppd.conf.j2 @@ -0,0 +1,44 @@ +######################################################## +# +# autogenerated by nat66.py +# +# The configuration file must define one upstream +# interface. +# +# For some services, such as nat66, because it runs +# stateless, it needs to rely on NDP Proxy to respond +# to NDP requests. +# +# When using nat66 source rules, NDP Proxy needs +# to be enabled +# +######################################################## + +{% set global = namespace(ndppd_interfaces = [],ndppd_prefixs = []) %} +{% if source.rule is vyos_defined %} +{% for rule, config in source.rule.items() if config.disable is not defined %} +{% if config.outbound_interface is vyos_defined %} +{% if config.outbound_interface not in global.ndppd_interfaces %} +{% set global.ndppd_interfaces = global.ndppd_interfaces + [config.outbound_interface] %} +{% endif %} +{% if config.translation.address is vyos_defined and config.translation.address | is_ip_network %} +{% set global.ndppd_prefixs = global.ndppd_prefixs + [{'interface':config.outbound_interface,'rule':config.translation.address}] %} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} + +{% for interface in global.ndppd_interfaces %} +proxy {{ interface }} { + router yes + timeout 500 + ttl 30000 +{% for map in global.ndppd_prefixs %} +{% if map.interface == interface %} + rule {{ map.rule }} { + static + } +{% endif %} +{% endfor %} +} +{% endfor %} diff --git a/data/templates/ndppd/ndppd.conf.tmpl b/data/templates/ndppd/ndppd.conf.tmpl deleted file mode 100644 index 502dab5b8..000000000 --- a/data/templates/ndppd/ndppd.conf.tmpl +++ /dev/null @@ -1,44 +0,0 @@ -######################################################## -# -# autogenerated by nat66.py -# -# The configuration file must define one upstream -# interface. -# -# For some services, such as nat66, because it runs -# stateless, it needs to rely on NDP Proxy to respond -# to NDP requests. -# -# When using nat66 source rules, NDP Proxy needs -# to be enabled -# -######################################################## - -{% set global = namespace(ndppd_interfaces = [],ndppd_prefixs = []) %} -{% if source is defined and source.rule is defined and source.rule is not none %} -{% for rule, config in source.rule.items() if config.disable is not defined %} -{% if config.outbound_interface is defined %} -{% if config.outbound_interface not in global.ndppd_interfaces %} -{% set global.ndppd_interfaces = global.ndppd_interfaces + [config.outbound_interface] %} -{% endif %} -{% if config.translation is defined and config.translation.address is defined and config.translation.address | is_ip_network %} -{% set global.ndppd_prefixs = global.ndppd_prefixs + [{'interface':config.outbound_interface,'rule':config.translation.address}] %} -{% endif %} -{% endif %} -{% endfor %} -{% endif %} - -{% for interface in global.ndppd_interfaces %} -proxy {{ interface }} { - router yes - timeout 500 - ttl 30000 -{% for map in global.ndppd_prefixs %} -{% if map.interface == interface %} - rule {{ map.rule }} { - static - } -{% endif %} -{% endfor %} -} -{% endfor %} diff --git a/data/templates/netflow/uacctd.conf.tmpl b/data/templates/netflow/uacctd.conf.tmpl deleted file mode 100644 index 1c183bb20..000000000 --- a/data/templates/netflow/uacctd.conf.tmpl +++ /dev/null @@ -1,72 +0,0 @@ -# Genereated from VyOS configuration -daemonize: true -promisc: false -pidfile: /var/run/uacctd.pid -uacctd_group: 2 -uacctd_nl_size: 2097152 -snaplen: {{ snaplen }} -{% if templatecfg['enable-egress'] != none %} -aggregate: in_iface,out_iface,src_mac,dst_mac,vlan,src_host,dst_host,src_port,dst_port,proto,tos,flows -{% else %} -aggregate: in_iface,src_mac,dst_mac,vlan,src_host,dst_host,src_port,dst_port,proto,tos,flows -{% endif %} -plugin_pipe_size: {{ templatecfg['plugin_pipe_size'] }} -plugin_buffer_size: {{ templatecfg['plugin_buffer_size'] }} -{% if templatecfg['syslog-facility'] != none %} -syslog: {{ templatecfg['syslog-facility'] }} -{% endif %} -{% if templatecfg['disable-imt'] == none %} -imt_path: /tmp/uacctd.pipe -imt_mem_pools_number: 169 -{% endif %} -plugins: {% if templatecfg['netflow']['servers'] != none %} -{% for server in templatecfg['netflow']['servers'] %} -{% if loop.last %}nfprobe[nf_{{ server['address'] }}]{% else %}nfprobe[nf_{{ server['address'] }}],{% endif %} -{% endfor %} -{% set plugins_presented = true %} -{% endif %} -{% if templatecfg['sflow']['servers'] != none %} -{% if plugins_presented %} -{% for server in templatecfg['sflow']['servers'] %},sfprobe[sf_{{ server['address'] }}]{% endfor %} -{% else %} -{% for server in templatecfg['sflow']['servers'] %} -{% if loop.last %}sfprobe[sf_{{ server['address'] }}]{% else %}sfprobe[sf_{{ server['address'] }}],{% endif %} -{% endfor %} -{% endif %} -{% set plugins_presented = true %} -{% endif %} -{% if templatecfg['disable-imt'] == none %} -{% if plugins_presented %},memory{% else %}memory{% endif %} -{% endif %} - -{% if templatecfg['netflow']['servers'] != none %} -{% for server in templatecfg['netflow']['servers'] %} -nfprobe_receiver[nf_{{ server['address'] }}]: {{ server['address'] }}:{{ server['port'] }} -nfprobe_version[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['version'] }} -{% if templatecfg['netflow']['engine-id'] != none %} -nfprobe_engine[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['engine-id'] }} -{% endif %} -{% if templatecfg['netflow']['max-flows'] != none %} -nfprobe_maxflows[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['max-flows'] }} -{% endif %} -{% if templatecfg['netflow']['sampling-rate'] != none %} -sampling_rate[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['sampling-rate'] }} -{% endif %} -{% if templatecfg['netflow']['source-ip'] != none %} -nfprobe_source_ip[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['source-ip'] }} -{% endif %} -{% if templatecfg['netflow']['timeout_string'] != '' %} -nfprobe_timeouts[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['timeout_string'] }} -{% endif %} -{% endfor %} -{% endif %} - -{% if templatecfg['sflow']['servers'] != none %} -{% for server in templatecfg['sflow']['servers'] %} -sfprobe_receiver[sf_{{ server['address'] }}]: {{ server['address'] }}:{{ server['port'] }} -sfprobe_agentip[sf_{{ server['address'] }}]: {{ templatecfg['sflow']['agent-address'] }} -{% if templatecfg['sflow']['sampling-rate'] != none %} -sampling_rate[sf_{{ server['address'] }}]: {{ templatecfg['sflow']['sampling-rate'] }} -{% endif %} -{% endfor %} -{% endif %} diff --git a/data/templates/nhrp/opennhrp.conf.j2 b/data/templates/nhrp/opennhrp.conf.j2 new file mode 100644 index 000000000..c040a8f14 --- /dev/null +++ b/data/templates/nhrp/opennhrp.conf.j2 @@ -0,0 +1,42 @@ +{# j2lint: disable=jinja-variable-format #} +# Created by VyOS - manual changes will be overwritten + +{% if tunnel is vyos_defined %} +{% for name, tunnel_conf in tunnel.items() %} +{% set type = 'spoke' if tunnel_conf.map is vyos_defined or tunnel_conf.dynamic_map is vyos_defined else 'hub' %} +{% set profile_name = profile_map[name] if profile_map is vyos_defined and name in profile_map else '' %} +interface {{ name }} #{{ type }} {{ profile_name }} +{% if tunnel_conf.map is vyos_defined %} +{% for map, map_conf in tunnel_conf.map.items() %} +{% set cisco = ' cisco' if map_conf.cisco is vyos_defined else '' %} +{% set register = ' register' if map_conf.register is vyos_defined else '' %} + map {{ map }} {{ map_conf.nbma_address }}{{ register }}{{ cisco }} +{% endfor %} +{% endif %} +{% if tunnel_conf.dynamic_map is vyos_defined %} +{% for map, map_conf in tunnel_conf.dynamic_map.items() %} + dynamic-map {{ map }} {{ map_conf.nbma_domain_name }} +{% endfor %} +{% endif %} +{% if tunnel_conf.cisco_authentication is vyos_defined %} + cisco-authentication {{ tunnel_conf.cisco_authentication }} +{% endif %} +{% if tunnel_conf.holding_time is vyos_defined %} + holding-time {{ tunnel_conf.holding_time }} +{% endif %} +{% if tunnel_conf.multicast is vyos_defined %} + multicast {{ tunnel_conf.multicast }} +{% endif %} +{% for key in ['non_caching', 'redirect', 'shortcut', 'shortcut_destination'] %} +{% if key in tunnel_conf %} + {{ key | replace("_", "-") }} +{% endif %} +{% endfor %} +{% if tunnel_conf.shortcut_target is vyos_defined %} +{% for target, shortcut_conf in tunnel_conf.shortcut_target.items() %} + shortcut-target {{ target }}{{ ' holding-time ' + shortcut_conf.holding_time if shortcut_conf.holding_time is vyos_defined }} +{% endfor %} +{% endif %} + +{% endfor %} +{% endif %} diff --git a/data/templates/nhrp/opennhrp.conf.tmpl b/data/templates/nhrp/opennhrp.conf.tmpl deleted file mode 100644 index 948327198..000000000 --- a/data/templates/nhrp/opennhrp.conf.tmpl +++ /dev/null @@ -1,41 +0,0 @@ -# Created by VyOS - manual changes will be overwritten - -{% if tunnel is defined and tunnel is not none %} -{% for name, tunnel_conf in tunnel.items() %} -{% set type = 'spoke' if tunnel_conf.map is defined or tunnel_conf.dynamic_map is defined else 'hub' %} -{% set profile_name = profile_map[name] if profile_map is defined and name in profile_map else '' %} -interface {{ name }} #{{ type }} {{ profile_name }} -{% if tunnel_conf.map is defined and tunnel_conf.map is not none %} -{% for map, map_conf in tunnel_conf.map.items() %} -{% set cisco = ' cisco' if map_conf.cisco is defined else '' %} -{% set register = ' register' if map_conf.register is defined else '' %} - map {{ map }} {{ map_conf.nbma_address }}{{ register }}{{ cisco }} -{% endfor %} -{% endif %} -{% if tunnel_conf.dynamic_map is defined and tunnel_conf.dynamic_map is not none %} -{% for map, map_conf in tunnel_conf.dynamic_map.items() %} - dynamic-map {{ map }} {{ map_conf.nbma_domain_name }} -{% endfor %} -{% endif %} -{% if tunnel_conf.cisco_authentication is defined and tunnel_conf.cisco_authentication is not none %} - cisco-authentication {{ tunnel_conf.cisco_authentication }} -{% endif %} -{% if tunnel_conf.holding_time is defined and tunnel_conf.holding_time is not none %} - holding-time {{ tunnel_conf.holding_time }} -{% endif %} -{% if tunnel_conf.multicast is defined and tunnel_conf.multicast is not none %} - multicast {{ tunnel_conf.multicast }} -{% endif %} -{% for key in ['non_caching', 'redirect', 'shortcut', 'shortcut_destination'] %} -{% if key in tunnel_conf %} - {{ key | replace("_", "-") }} -{% endif %} -{% endfor %} -{% if tunnel_conf.shortcut_target is defined and tunnel_conf.shortcut_target is not none %} -{% for target, shortcut_conf in tunnel_conf.shortcut_target.items() %} - shortcut-target {{ target }} {{ shortcut_conf.holding_time if shortcut_conf.holding_time is defined else '' }} -{% endfor %} -{% endif %} - -{% endfor %} -{% endif %} diff --git a/data/templates/ntp/ntpd.conf.tmpl b/data/templates/ntp/ntpd.conf.j2 index 38e68f24f..da610051e 100644 --- a/data/templates/ntp/ntpd.conf.tmpl +++ b/data/templates/ntp/ntpd.conf.j2 @@ -15,27 +15,28 @@ restrict -6 ::1 # # Configurable section # -{% if server is defined and server is not none %} -{% for server, config in server.items() %} -{% set association = 'server' %} -{% if config.pool is defined %} -{% set association = 'pool' %} -{% endif %} -{{ association }} {{ server | replace('_', '-') }} iburst {{ 'noselect' if config.noselect is defined }} {{ 'preempt' if config.preempt is defined }} {{ 'prefer' if config.prefer is defined }} -{% endfor %} +{% 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 is defined and allow_clients.address is defined %} +{% if allow_clients.address is vyos_defined %} # Allowed clients configuration -{% for address in allow_clients.address %} -restrict {{ address|address_from_cidr }} mask {{ address|netmask_from_cidr }} nomodify notrap nopeer -{% endfor %} +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 %} # NTP should listen on configured addresses only interface ignore wildcard -{% for address in listen_address %} +{% for address in listen_address %} interface listen {{ address }} -{% endfor %} +{% endfor %} {% endif %} diff --git a/data/templates/ntp/override.conf.j2 b/data/templates/ntp/override.conf.j2 new file mode 100644 index 000000000..6fed9d7d2 --- /dev/null +++ b/data/templates/ntp/override.conf.j2 @@ -0,0 +1,14 @@ +{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %} +[Unit] +StartLimitIntervalSec=0 +ConditionPathExists={{ config_file }} +After=vyos-router.service + +[Service] +ExecStart= +ExecStart={{ vrf_command }}/usr/sbin/ntpd -g -p {{ config_file | replace('.conf', '.pid') }} -c {{ config_file }} -u ntp:ntp +PIDFile= +PIDFile={{ config_file | replace('.conf', '.pid') }} +Restart=always +RestartSec=10 + diff --git a/data/templates/ntp/override.conf.tmpl b/data/templates/ntp/override.conf.tmpl deleted file mode 100644 index 28eb61b21..000000000 --- a/data/templates/ntp/override.conf.tmpl +++ /dev/null @@ -1,14 +0,0 @@ -{% set vrf_command = 'ip vrf exec ' + vrf + ' ' if vrf is defined else '' %} -[Unit] -StartLimitIntervalSec=0 -ConditionPathExists={{config_file}} -After=vyos-router.service - -[Service] -ExecStart= -ExecStart={{vrf_command}}/usr/sbin/ntpd -g -p {{config_file | replace('.conf', '.pid') }} -c {{config_file}} -u ntp:ntp -PIDFile= -PIDFile={{config_file | replace('.conf', '.pid') }} -Restart=always -RestartSec=10 - diff --git a/data/templates/ocserv/ocserv_config.tmpl b/data/templates/ocserv/ocserv_config.j2 index 0be805235..8418a2185 100644 --- a/data/templates/ocserv/ocserv_config.tmpl +++ b/data/templates/ocserv/ocserv_config.j2 @@ -8,19 +8,27 @@ run-as-group = daemon {% if "radius" in authentication.mode %} auth = "radius [config=/run/ocserv/radiusclient.conf]" +{% elif "local" in authentication.mode %} +{% if authentication.mode.local == "password-otp" %} +auth = "plain[passwd=/run/ocserv/ocpasswd,otp=/run/ocserv/users.oath]" +{% elif authentication.mode.local == "otp" %} +auth = "plain[otp=/run/ocserv/users.oath]" +{% else %} +auth = "plain[/run/ocserv/ocpasswd]" +{% endif %} {% else %} auth = "plain[/run/ocserv/ocpasswd]" {% endif %} -{% if ssl.certificate is defined %} +{% if ssl.certificate is vyos_defined %} server-cert = /run/ocserv/cert.pem server-key = /run/ocserv/cert.key -{% if ssl.passphrase is defined %} +{% if ssl.passphrase is vyos_defined %} key-pin = {{ ssl.passphrase }} -{% endif %} +{% endif %} {% endif %} -{% if ssl.ca_certificate is defined %} +{% if ssl.ca_certificate is vyos_defined %} ca-cert = /run/ocserv/ca.pem {% endif %} @@ -42,7 +50,8 @@ rekey-method = ssl try-mtu-discovery = true cisco-client-compat = true dtls-legacy = true - +max-ban-score = 80 +ban-reset-time = 300 # The name to use for the tun device device = sslvpn @@ -50,33 +59,33 @@ device = sslvpn # An alternative way of specifying the network: {% if network_settings %} # DNS settings -{% if network_settings.name_server is string %} +{% if network_settings.name_server is string %} dns = {{ network_settings.name_server }} -{% else %} -{% for dns in network_settings.name_server %} +{% else %} +{% for dns in network_settings.name_server %} dns = {{ dns }} -{% endfor %} -{% endif %} +{% endfor %} +{% endif %} # IPv4 network pool -{% if network_settings.client_ip_settings %} -{% if network_settings.client_ip_settings.subnet %} +{% if network_settings.client_ip_settings %} +{% if network_settings.client_ip_settings.subnet %} ipv4-network = {{ network_settings.client_ip_settings.subnet }} +{% endif %} {% endif %} -{% endif %} # IPv6 network pool -{% if network_settings.client_ipv6_pool %} -{% if network_settings.client_ipv6_pool.prefix %} +{% if network_settings.client_ipv6_pool %} +{% if network_settings.client_ipv6_pool.prefix %} ipv6-network = {{ network_settings.client_ipv6_pool.prefix }} ipv6-subnet-prefix = {{ network_settings.client_ipv6_pool.mask }} +{% endif %} {% endif %} -{% endif %} {% endif %} {% if network_settings.push_route is string %} route = {{ network_settings.push_route }} {% else %} -{% for route in network_settings.push_route %} +{% for route in network_settings.push_route %} route = {{ route }} -{% endfor %} +{% endfor %} {% endif %} diff --git a/data/templates/ocserv/ocserv_otp_usr.j2 b/data/templates/ocserv/ocserv_otp_usr.j2 new file mode 100644 index 000000000..b2511ed94 --- /dev/null +++ b/data/templates/ocserv/ocserv_otp_usr.j2 @@ -0,0 +1,8 @@ +#<token_type> <username> <pin> <secret_hex_key> <counter> <lastpass> <time> +{% if username is vyos_defined %} +{% for user, user_config in username.items() %} +{% if user_config.disable is not vyos_defined and user_config.otp is vyos_defined %} +{{ user_config.otp.token_tmpl }} {{ user }} {{ user_config.otp.pin | default("-", true) }} {{ user_config.otp.key }} +{% endif %} +{% endfor %} +{% endif %} diff --git a/data/templates/ocserv/ocserv_passwd.j2 b/data/templates/ocserv/ocserv_passwd.j2 new file mode 100644 index 000000000..30c79d66a --- /dev/null +++ b/data/templates/ocserv/ocserv_passwd.j2 @@ -0,0 +1,8 @@ +#<username>:<group>:<hash> +{% if username is vyos_defined %} +{% for user, user_config in username.items() %} +{% if user_config.disable is not vyos_defined %} +{{ user }}:*:{{ user_config.hash }} +{% endif %} +{% endfor %} +{% endif %}
\ No newline at end of file diff --git a/data/templates/ocserv/ocserv_passwd.tmpl b/data/templates/ocserv/ocserv_passwd.tmpl deleted file mode 100644 index ffadb4860..000000000 --- a/data/templates/ocserv/ocserv_passwd.tmpl +++ /dev/null @@ -1,6 +0,0 @@ -#<username>:<group>:<hash> -{% for user in username if username is defined %} -{% if not "disable" in username[user] %} -{{ user }}:*:{{ username[user].hash }} -{% endif %} -{% endfor %}
\ No newline at end of file diff --git a/data/templates/ocserv/radius_conf.tmpl b/data/templates/ocserv/radius_conf.j2 index 1712d83ef..b6612fee5 100644 --- a/data/templates/ocserv/radius_conf.tmpl +++ b/data/templates/ocserv/radius_conf.j2 @@ -1,13 +1,13 @@ ### generated by vpn_openconnect.py ### nas-identifier VyOS {% for srv in server %} -{% if not "disable" in server[srv] %} -{% if "port" in server[srv] %} -authserver {{ srv }}:{{server[srv]["port"]}} -{% else %} +{% if not "disable" in server[srv] %} +{% if "port" in server[srv] %} +authserver {{ srv }}:{{ server[srv]["port"] }} +{% else %} authserver {{ srv }} +{% endif %} {% endif %} -{% endif %} {% endfor %} radius_timeout {{ timeout }} {% if source_address %} @@ -15,7 +15,7 @@ bindaddr {{ source_address }} {% else %} bindaddr * {% endif %} -servers /run/ocserv/radius_servers +servers /run/ocserv/radius_servers dictionary /etc/radcli/dictionary default_realm radius_retries 3 diff --git a/data/templates/ocserv/radius_servers.j2 b/data/templates/ocserv/radius_servers.j2 new file mode 100644 index 000000000..302e91600 --- /dev/null +++ b/data/templates/ocserv/radius_servers.j2 @@ -0,0 +1,7 @@ +### generated by vpn_openconnect.py ### +# server key +{% for srv in server %} +{% if not "disable" in server[srv] %} +{{ srv }} {{ server[srv].key }} +{% endif %} +{% endfor %} diff --git a/data/templates/ocserv/radius_servers.tmpl b/data/templates/ocserv/radius_servers.tmpl deleted file mode 100644 index 7bacac992..000000000 --- a/data/templates/ocserv/radius_servers.tmpl +++ /dev/null @@ -1,7 +0,0 @@ -### generated by vpn_openconnect.py ### -# server key -{% for srv in server %} -{% if not "disable" in server[srv] %} -{{ srv }} {{ server[srv].key }} -{% endif %} -{% endfor %} diff --git a/data/templates/openvpn/auth.pw.tmpl b/data/templates/openvpn/auth.pw.j2 index 9b20c9742..218121062 100644 --- a/data/templates/openvpn/auth.pw.tmpl +++ b/data/templates/openvpn/auth.pw.j2 @@ -1,5 +1,5 @@ {# Autogenerated by interfaces-openvpn.py #} -{% if authentication is defined and authentication is not none %} +{% if authentication is vyos_defined %} {{ authentication.username }} {{ authentication.password }} {% endif %} diff --git a/data/templates/openvpn/client.conf.tmpl b/data/templates/openvpn/client.conf.j2 index e6e15b6ad..2e327e4d3 100644 --- a/data/templates/openvpn/client.conf.tmpl +++ b/data/templates/openvpn/client.conf.j2 @@ -1,31 +1,31 @@ ### Autogenerated by interfaces-openvpn.py ### -{% if ip %} +{% if ip is vyos_defined %} ifconfig-push {{ ip[0] }} {{ server_subnet[0] | netmask_from_cidr }} {% endif %} -{% if push_route is defined and push_route is not none %} -{% for route in push_route %} +{% if push_route is vyos_defined %} +{% for route in push_route %} push "route {{ route | address_from_cidr }} {{ route | netmask_from_cidr }}" -{% endfor %} +{% endfor %} {% endif %} -{% if subnet is defined and subnet is not none %} -{% for network in subnet %} +{% if subnet is vyos_defined %} +{% for network in subnet %} iroute {{ network | address_from_cidr }} {{ network | netmask_from_cidr }} -{% endfor %} +{% endfor %} {% endif %} {# ipv6_remote is only set when IPv6 server is enabled #} -{% if ipv6_remote %} +{% if ipv6_remote is vyos_defined %} # IPv6 -{% if ipv6_ip %} +{% if ipv6_ip is vyos_defined %} ifconfig-ipv6-push {{ ipv6_ip[0] }} {{ ipv6_remote }} -{% endif %} -{% for route6 in ipv6_push_route %} +{% endif %} +{% for route6 in ipv6_push_route %} push "route-ipv6 {{ route6 }}" -{% endfor %} -{% for net6 in ipv6_subnet %} +{% endfor %} +{% for net6 in ipv6_subnet %} iroute-ipv6 {{ net6 }} -{% endfor %} +{% endfor %} {% endif %} -{% if disable is defined %} +{% if disable is vyos_defined %} disable {% endif %} diff --git a/data/templates/openvpn/server.conf.j2 b/data/templates/openvpn/server.conf.j2 new file mode 100644 index 000000000..6dd4ef88d --- /dev/null +++ b/data/templates/openvpn/server.conf.j2 @@ -0,0 +1,224 @@ +### Autogenerated by interfaces-openvpn.py ### +# +# See https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage +# for individual keyword definition +# +# {{ description if description is vyos_defined }} +# + +verb 3 +dev-type {{ device_type }} +dev {{ ifname }} +persist-key +{% if protocol is vyos_defined('tcp-active') %} +proto tcp-client +{% elif protocol is vyos_defined('tcp-passive') %} +proto tcp-server +{% else %} +proto udp +{% endif %} +{% if local_host is vyos_defined %} +local {{ local_host }} +{% endif %} +{% if mode is vyos_defined('server') and protocol is vyos_defined('udp') and local_host is not vyos_defined %} +multihome +{% endif %} +{% if local_port is vyos_defined %} +lport {{ local_port }} +{% endif %} +{% if remote_port is vyos_defined %} +rport {{ remote_port }} +{% endif %} +{% if remote_host is vyos_defined %} +{% for remote in remote_host %} +remote {{ remote }} +{% endfor %} +{% endif %} +{% if shared_secret_key is vyos_defined %} +secret /run/openvpn/{{ ifname }}_shared.key +{% endif %} +{% if persistent_tunnel is vyos_defined %} +persist-tun +{% endif %} +{% if replace_default_route.local is vyos_defined %} +push "redirect-gateway local def1" +{% elif replace_default_route is vyos_defined %} +push "redirect-gateway def1" +{% endif %} +{% if use_lzo_compression is vyos_defined %} +compress lzo +{% endif %} + +{% if mode is vyos_defined('client') %} +# +# OpenVPN Client mode +# +client +nobind + +{% elif mode is vyos_defined('server') %} +# +# OpenVPN Server mode +# +mode server +tls-server +{% if server is vyos_defined %} +{% if server.subnet is vyos_defined %} +{% if server.topology is vyos_defined('point-to-point') %} +topology p2p +{% elif server.topology is vyos_defined %} +topology {{ server.topology }} +{% endif %} +{% for subnet in server.subnet %} +{% if subnet | is_ipv4 %} +server {{ subnet | address_from_cidr }} {{ subnet | netmask_from_cidr }} nopool +{# First ip address is used as gateway. It's allows to use metrics #} +{% if server.push_route is vyos_defined %} +{% for route, route_config in server.push_route.items() %} +{% if route | is_ipv4 %} +push "route {{ route | address_from_cidr }} {{ route | netmask_from_cidr }} {{ subnet | first_host_address ~ ' ' ~ route_config.metric if route_config.metric is vyos_defined }}" +{% elif route | is_ipv6 %} +push "route-ipv6 {{ route }}" +{% endif %} +{% endfor %} +{% endif %} +{# OpenVPN assigns the first IP address to its local interface so the pool used #} +{# in net30 topology - where each client receives a /30 must start from the second subnet #} +{% if server.topology is vyos_defined('net30') %} +ifconfig-pool {{ subnet | inc_ip('4') }} {{ subnet | last_host_address | dec_ip('1') }} {{ subnet | netmask_from_cidr if device_type == 'tap' else '' }} +{% else %} +{# OpenVPN assigns the first IP address to its local interface so the pool must #} +{# start from the second address and end on the last address #} +ifconfig-pool {{ subnet | first_host_address | inc_ip('1') }} {{ subnet | last_host_address | dec_ip('1') }} {{ subnet | netmask_from_cidr if device_type == 'tun' else '' }} +{% endif %} +{% elif subnet | is_ipv6 %} +server-ipv6 {{ subnet }} +{% endif %} +{% endfor %} +{% endif %} + +{% if server.client_ip_pool is vyos_defined and server.client_ip_pool.disable is not vyos_defined %} +ifconfig-pool {{ server.client_ip_pool.start }} {{ server.client_ip_pool.stop }}{{ server.client_ip_pool.subnet_mask if server.client_ip_pool.subnet_mask is vyos_defined }} +{% endif %} +{% if server.max_connections is vyos_defined %} +max-clients {{ server.max_connections }} +{% endif %} +{% if server.client is vyos_defined %} +client-config-dir /run/openvpn/ccd/{{ ifname }} +{% endif %} +{% endif %} +keepalive {{ keep_alive.interval }} {{ keep_alive.interval | int * keep_alive.failure_count | int }} +management /run/openvpn/openvpn-mgmt-intf unix +{% if server is vyos_defined %} +{% if server.reject_unconfigured_clients is vyos_defined %} +ccd-exclusive +{% endif %} + +{% if server.name_server is vyos_defined %} +{% for nameserver in server.name_server %} +{% if nameserver | is_ipv4 %} +push "dhcp-option DNS {{ nameserver }}" +{% elif nameserver | is_ipv6 %} +push "dhcp-option DNS6 {{ nameserver }}" +{% endif %} +{% endfor %} +{% endif %} +{% if server.domain_name is vyos_defined %} +push "dhcp-option DOMAIN {{ server.domain_name }}" +{% endif %} +{% if server.mfa.totp is vyos_defined %} +{% set totp_config = server.mfa.totp %} +plugin "{{ plugin_dir }}/openvpn-otp.so" "otp_secrets=/config/auth/openvpn/{{ ifname }}-otp-secrets otp_slop={{ totp_config.slop }} totp_t0={{ totp_config.drift }} totp_step={{ totp_config.step }} totp_digits={{ totp_config.digits }} password_is_cr={{ '1' if totp_config.challenge == 'enable' else '0' }}" +{% endif %} +{% endif %} +{% else %} +# +# OpenVPN site-2-site mode +# +ping {{ keep_alive.interval }} +ping-restart {{ keep_alive.failure_count }} + +{% if device_type == 'tap' %} +{% if local_address is vyos_defined %} +{% for laddr, laddr_conf in local_address.items() if laddr | is_ipv4 %} +{% if laddr_conf.subnet_mask is vyos_defined %} +ifconfig {{ laddr }} {{ laddr_conf.subnet_mask }} +{% endif %} +{% endfor %} +{% endif %} +{% else %} +{% for laddr in local_address if laddr | is_ipv4 %} +{% for raddr in remote_address if raddr | is_ipv4 %} +ifconfig {{ laddr }} {{ raddr }} +{% endfor %} +{% endfor %} +{% for laddr in local_address if laddr | is_ipv6 %} +{% for raddr in remote_address if raddr | is_ipv6 %} +ifconfig-ipv6 {{ laddr }} {{ raddr }} +{% endfor %} +{% endfor %} +{% endif %} +{% endif %} + +{% if tls is vyos_defined %} +# TLS options +{% if tls.ca_certificate is vyos_defined %} +ca /run/openvpn/{{ ifname }}_ca.pem +{% endif %} +{% if tls.certificate is vyos_defined %} +cert /run/openvpn/{{ ifname }}_cert.pem +{% endif %} +{% if tls.private_key is vyos_defined %} +key /run/openvpn/{{ ifname }}_cert.key +{% endif %} +{% if tls.crypt_key is vyos_defined %} +tls-crypt /run/openvpn/{{ ifname }}_crypt.key +{% endif %} +{% if tls.crl is vyos_defined %} +crl-verify /run/openvpn/{{ ifname }}_crl.pem +{% endif %} +{% if tls.tls_version_min is vyos_defined %} +tls-version-min {{ tls.tls_version_min }} +{% endif %} +{% if tls.dh_params is vyos_defined %} +dh /run/openvpn/{{ ifname }}_dh.pem +{% elif mode is vyos_defined('server') and tls.private_key is vyos_defined %} +dh none +{% endif %} +{% if tls.auth_key is vyos_defined %} +{% if mode == 'client' %} +tls-auth /run/openvpn/{{ ifname }}_auth.key 1 +{% elif mode == 'server' %} +tls-auth /run/openvpn/{{ ifname }}_auth.key 0 +{% endif %} +{% endif %} +{% if tls.role is vyos_defined('active') %} +tls-client +{% elif tls.role is vyos_defined('passive') %} +tls-server +{% endif %} +{% endif %} + +# Encryption options +{% if encryption is vyos_defined %} +{% if encryption.cipher is vyos_defined %} +cipher {{ encryption.cipher | openvpn_cipher }} +{% if encryption.cipher is vyos_defined('bf128') %} +keysize 128 +{% elif encryption.cipher is vyos_defined('bf256') %} +keysize 256 +{% endif %} +{% endif %} +{% if encryption.ncp_ciphers is vyos_defined %} +data-ciphers {{ encryption.ncp_ciphers | openvpn_ncp_ciphers }} +{% endif %} +{% endif %} + +{% if hash is vyos_defined %} +auth {{ hash }} +{% endif %} + +{% if authentication is vyos_defined %} +auth-user-pass {{ auth_user_pass_file }} +auth-retry nointeract +{% endif %} diff --git a/data/templates/openvpn/server.conf.tmpl b/data/templates/openvpn/server.conf.tmpl deleted file mode 100644 index 7a0470d0e..000000000 --- a/data/templates/openvpn/server.conf.tmpl +++ /dev/null @@ -1,226 +0,0 @@ -### Autogenerated by interfaces-openvpn.py ### -# -# See https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage -# for individual keyword definition -# -# {{ description if description is defined and description is not none }} -# - -verb 3 -dev-type {{ device_type }} -dev {{ ifname }} -persist-key -{% if protocol == 'tcp-active' %} -proto tcp-client -{% elif protocol == 'tcp-passive' %} -proto tcp-server -{% else %} -proto udp -{% endif %} -{% if local_host is defined and local_host is not none %} -local {{ local_host }} -{% endif %} -{% if mode is defined and mode == 'server' and protocol == 'udp' and local_host is not defined %} -multihome -{% endif %} -{% if local_port is defined and local_port is not none %} -lport {{ local_port }} -{% endif %} -{% if remote_port is defined and remote_port is not none %} -rport {{ remote_port }} -{% endif %} -{% if remote_host is defined and remote_host is not none %} -{% for remote in remote_host %} -remote {{ remote }} -{% endfor %} -{% endif %} -{% if shared_secret_key is defined and shared_secret_key is not none %} -secret /run/openvpn/{{ ifname }}_shared.key -{% endif %} -{% if persistent_tunnel is defined %} -persist-tun -{% endif %} -{% if replace_default_route is defined and replace_default_route.local is defined %} -push "redirect-gateway local def1" -{% elif replace_default_route is defined %} -push "redirect-gateway def1" -{% endif %} -{% if use_lzo_compression is defined %} -compress lzo -{% endif %} - -{% if mode == 'client' %} -# -# OpenVPN Client mode -# -client -nobind - -{% elif mode == 'server' %} -# -# OpenVPN Server mode -# -mode server -tls-server -{% if server is defined and server is not none %} -{% if server.subnet is defined and server.subnet is not none %} -{% if server.topology is defined and server.topology == 'point-to-point' %} -topology p2p -{% elif server.topology is defined and server.topology is not none %} -topology {{ server.topology }} -{% endif %} -{% for subnet in server.subnet %} -{% if subnet | is_ipv4 %} -server {{ subnet | address_from_cidr }} {{ subnet | netmask_from_cidr }} nopool -{# First ip address is used as gateway. It's allows to use metrics #} -{% if server.push_route is defined and server.push_route is not none %} -{% for route, route_config in server.push_route.items() %} -{% if route | is_ipv4 %} -push "route {{ route | address_from_cidr }} {{ route | netmask_from_cidr }}{% if route_config.metric is defined %} {{ subnet | first_host_address }} {{ route_config.metric }}{% endif %}" -{% elif route | is_ipv6 %} -push "route-ipv6 {{ route }}" -{% endif %} -{% endfor %} -{% endif %} -{# OpenVPN assigns the first IP address to its local interface so the pool used #} -{# in net30 topology - where each client receives a /30 must start from the second subnet #} -{% if server.topology is defined and server.topology == 'net30' %} -ifconfig-pool {{ subnet | inc_ip('4') }} {{ subnet | last_host_address | dec_ip('1') }} {{ subnet | netmask_from_cidr if device_type == 'tap' else '' }} -{% else %} -{# OpenVPN assigns the first IP address to its local interface so the pool must #} -{# start from the second address and end on the last address #} -ifconfig-pool {{ subnet | first_host_address | inc_ip('1') }} {{ subnet | last_host_address | dec_ip('1') }} {{ subnet | netmask_from_cidr if device_type == 'tun' else '' }} -{% endif %} -{% elif subnet | is_ipv6 %} -server-ipv6 {{ subnet }} -{% endif %} -{% endfor %} -{% endif %} - -{% if server.client_ip_pool is defined and server.client_ip_pool is not none and server.client_ip_pool.disable is not defined %} -ifconfig-pool {{ server.client_ip_pool.start }} {{ server.client_ip_pool.stop }}{{ server.client_ip_pool.subnet_mask if server.client_ip_pool.subnet_mask is defined and server.client_ip_pool.subnet_mask is not none }} -{% endif %} -{% if server.max_connections is defined and server.max_connections is not none %} -max-clients {{ server.max_connections }} -{% endif %} -{% if server.client is defined and server.client is not none %} -client-config-dir /run/openvpn/ccd/{{ ifname }} -{% endif %} -{% endif %} -keepalive {{ keep_alive.interval }} {{ keep_alive.interval|int * keep_alive.failure_count|int }} -management /run/openvpn/openvpn-mgmt-intf unix -{% if server is defined and server is not none %} -{% if server.reject_unconfigured_clients is defined %} -ccd-exclusive -{% endif %} - -{% if server.name_server is defined and server.name_server is not none %} -{% for nameserver in server.name_server %} -{% if nameserver | is_ipv4 %} -push "dhcp-option DNS {{ nameserver }}" -{% elif nameserver | is_ipv6 %} -push "dhcp-option DNS6 {{ nameserver }}" -{% endif %} -{% endfor %} -{% endif %} -{% if server.domain_name is defined and server.domain_name is not none %} -push "dhcp-option DOMAIN {{ server.domain_name }}" -{% endif %} -{% if server.mfa is defined and server.mfa is not none %} -{% if server.mfa.totp is defined and server.mfa.totp is not none %} -{% set totp_config = server.mfa.totp %} -plugin "{{ plugin_dir}}/openvpn-otp.so" "otp_secrets=/config/auth/openvpn/{{ ifname }}-otp-secrets {{ 'otp_slop=' ~ totp_config.slop }} {{ 'totp_t0=' ~ totp_config.drift }} {{ 'totp_step=' ~ totp_config.step }} {{ 'totp_digits=' ~ totp_config.digits }} password_is_cr={{ '1' if totp_config.challenge == 'enable' else '0' }}" -{% endif %} -{% endif %} -{% endif %} -{% else %} -# -# OpenVPN site-2-site mode -# -ping {{ keep_alive.interval }} -ping-restart {{ keep_alive.failure_count }} - -{% if device_type == 'tap' %} -{% for laddr, laddr_conf in local_address.items() if laddr | is_ipv4 %} -{% if laddr_conf is defined and laddr_conf.subnet_mask is defined and laddr_conf.subnet_mask is not none %} -ifconfig {{ laddr }} {{ laddr_conf.subnet_mask }} -{% endif %} -{% endfor %} -{% else %} -{% for laddr in local_address if laddr | is_ipv4 %} -{% for raddr in remote_address if raddr | is_ipv4 %} -ifconfig {{ laddr }} {{ raddr }} -{% endfor %} -{% endfor %} -{% for laddr in local_address if laddr | is_ipv6 %} -{% for raddr in remote_address if raddr | is_ipv6 %} -ifconfig-ipv6 {{ laddr }} {{ raddr }} -{% endfor %} -{% endfor %} -{% endif %} -{% endif %} - -{% if tls is defined and tls is not none %} -# TLS options -{% if tls.ca_certificate is defined and tls.ca_certificate is not none %} -ca /run/openvpn/{{ ifname }}_ca.pem -{% endif %} -{% if tls.certificate is defined and tls.certificate is not none %} -cert /run/openvpn/{{ ifname }}_cert.pem -{% endif %} -{% if tls.private_key is defined %} -key /run/openvpn/{{ ifname }}_cert.key -{% endif %} -{% if tls.crypt_key is defined and tls.crypt_key is not none %} -tls-crypt /run/openvpn/{{ ifname }}_crypt.key -{% endif %} -{% if tls.crl is defined %} -crl-verify /run/openvpn/{{ ifname }}_crl.pem -{% endif %} -{% if tls.tls_version_min is defined and tls.tls_version_min is not none %} -tls-version-min {{ tls.tls_version_min }} -{% endif %} -{% if tls.dh_params is defined and tls.dh_params is not none %} -dh /run/openvpn/{{ ifname }}_dh.pem -{% elif mode == 'server' and tls.private_key is defined %} -dh none -{% endif %} -{% if tls.auth_key is defined and tls.auth_key is not none %} -{% if mode == 'client' %} -tls-auth /run/openvpn/{{ ifname }}_auth.key 1 -{% elif mode == 'server' %} -tls-auth /run/openvpn/{{ ifname }}_auth.key 0 -{% endif %} -{% endif %} -{% if tls.role is defined and tls.role is not none %} -{% if tls.role == 'active' %} -tls-client -{% elif tls.role == 'passive' %} -tls-server -{% endif %} -{% endif %} -{% endif %} - -# Encryption options -{% if encryption is defined and encryption is not none %} -{% if encryption.cipher is defined and encryption.cipher is not none %} -cipher {{ encryption.cipher | openvpn_cipher }} -{% if encryption.cipher == 'bf128' %} -keysize 128 -{% elif encryption.cipher == 'bf256' %} -keysize 256 -{% endif %} -{% endif %} -{% if encryption.ncp_ciphers is defined and encryption.ncp_ciphers is not none %} -data-ciphers {{ encryption.ncp_ciphers | openvpn_ncp_ciphers }} -{% endif %} -{% endif %} - -{% if hash is defined and hash is not none %} -auth {{ hash }} -{% endif %} - -{% if authentication is defined and authentication is not none %} -auth-user-pass {{ auth_user_pass_file }} -auth-retry nointeract -{% endif %} diff --git a/data/templates/openvpn/service-override.conf.j2 b/data/templates/openvpn/service-override.conf.j2 new file mode 100644 index 000000000..616ba3bfc --- /dev/null +++ b/data/templates/openvpn/service-override.conf.j2 @@ -0,0 +1,21 @@ +{% set options = namespace(value='') %} +{% if openvpn_option is vyos_defined %} +{% for option in openvpn_option %} +{# Remove the '--' prefix from variable if it is presented #} +{% if option.startswith('--') %} +{% set option = option.split('--', maxsplit=1)[1] %} +{% endif %} +{# Workaround to pass '--push' options properly. Previously openvpn accepted this option without values in double-quotes #} +{# But now it stopped doing this, so we need to add them for compatibility #} +{# HOWEVER! This is a raw option and we do not promise that this or any other trick will work for all the cases. #} +{# Using 'openvpn-option' you take all responsibility for compatibility for yourself. #} +{% if option.startswith('push') and not (option.startswith('push "') and option.endswith('"')) %} +{% set option = 'push \"%s\"' | format(option.split('push ', maxsplit=1)[1]) %} +{% endif %} +{% set options.value = options.value ~ ' --' ~ option %} +{% endfor %} +{% endif %} +[Service] +ExecStart= +ExecStart=/usr/sbin/openvpn --daemon openvpn-%i --config %i.conf --status %i.status 30 --writepid %i.pid {{ options.value }} + diff --git a/data/templates/openvpn/service-override.conf.tmpl b/data/templates/openvpn/service-override.conf.tmpl deleted file mode 100644 index 069bdbd08..000000000 --- a/data/templates/openvpn/service-override.conf.tmpl +++ /dev/null @@ -1,20 +0,0 @@ -[Service] -ExecStart= -ExecStart=/usr/sbin/openvpn --daemon openvpn-%i --config %i.conf --status %i.status 30 --writepid %i.pid -{%- if openvpn_option is defined and openvpn_option is not none %} -{% for option in openvpn_option %} -{# Remove the '--' prefix from variable if it is presented #} -{% if option.startswith('--') %} -{% set option = option.split('--', maxsplit=1)[1] %} -{% endif %} -{# Workaround to pass '--push' options properly. Previously openvpn accepted this option without values in double-quotes #} -{# But now it stopped doing this, so we need to add them for compatibility #} -{# HOWEVER! This is a raw option and we do not promise that this or any other trick will work for all the cases. #} -{# Using 'openvpn-option' you take all responsibility for compatibility for yourself. #} -{% if option.startswith('push') and not (option.startswith('push "') and option.endswith('"')) %} -{% set option = 'push \"%s\"'|format(option.split('push ', maxsplit=1)[1]) %} -{% endif %} - --{{ option }} -{%- endfor %} -{% endif %} - diff --git a/data/templates/pmacct/override.conf.j2 b/data/templates/pmacct/override.conf.j2 new file mode 100644 index 000000000..213569ddc --- /dev/null +++ b/data/templates/pmacct/override.conf.j2 @@ -0,0 +1,17 @@ +{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %} +[Unit] +After= +After=vyos-router.service +ConditionPathExists= +ConditionPathExists=/run/pmacct/uacctd.conf + +[Service] +EnvironmentFile= +ExecStart= +ExecStart={{ vrf_command }}/usr/sbin/uacctd -f /run/pmacct/uacctd.conf +WorkingDirectory= +WorkingDirectory=/run/pmacct +PIDFile= +PIDFile=/run/pmacct/uacctd.pid +Restart=always +RestartSec=10 diff --git a/data/templates/pmacct/uacctd.conf.j2 b/data/templates/pmacct/uacctd.conf.j2 new file mode 100644 index 000000000..a5016691f --- /dev/null +++ b/data/templates/pmacct/uacctd.conf.j2 @@ -0,0 +1,80 @@ +# Genereated from VyOS configuration +daemonize: true +promisc: false +pidfile: /run/pmacct/uacctd.pid +uacctd_group: 2 +uacctd_nl_size: 2097152 +snaplen: {{ packet_length }} +aggregate: in_iface{{ ',out_iface' if enable_egress is vyos_defined }},src_mac,dst_mac,vlan,src_host,dst_host,src_port,dst_port,proto,tos,flows +{% set pipe_size = buffer_size | int *1024 *1024 %} +plugin_pipe_size: {{ pipe_size }} +{# We need an integer division (//) without any remainder or fraction #} +plugin_buffer_size: {{ pipe_size // 1000 }} +{% if syslog_facility is vyos_defined %} +syslog: {{ syslog_facility }} +{% endif %} +{% if disable_imt is not defined %} +imt_path: /tmp/uacctd.pipe +imt_mem_pools_number: 169 +{% endif %} + +{% set plugin = [] %} +{% if netflow.server is vyos_defined %} +{% for server in netflow.server %} +{% set nf_server_key = 'nf_' ~ server | replace(':', '.') %} +{% set _ = plugin.append('nfprobe['~ nf_server_key ~ ']') %} +{% endfor %} +{% endif %} +{% if sflow.server is vyos_defined %} +{% for server in sflow.server %} +{% set sf_server_key = 'sf_' ~ server | replace(':', '.') %} +{% set _ = plugin.append('sfprobe[' ~ sf_server_key ~ ']') %} +{% endfor %} +{% endif %} +{% if disable_imt is not defined %} +{% set _ = plugin.append('memory') %} +{% endif %} +plugins: {{ plugin | join(',') }} + +{% if netflow.server is vyos_defined %} +# NetFlow servers +{% for server, server_config in netflow.server.items() %} +{# # prevent pmacct syntax error when using IPv6 flow collectors #} +{% set nf_server_key = 'nf_' ~ server | replace(':', '.') %} +nfprobe_receiver[{{ nf_server_key }}]: {{ server | bracketize_ipv6 }}:{{ server_config.port }} +nfprobe_version[{{ nf_server_key }}]: {{ netflow.version }} +{% if netflow.engine_id is vyos_defined %} +nfprobe_engine[{{ nf_server_key }}]: {{ netflow.engine_id }} +{% endif %} +{% if netflow.max_flows is vyos_defined %} +nfprobe_maxflows[{{ nf_server_key }}]: {{ netflow.max_flows }} +{% endif %} +{% if netflow.sampling_rate is vyos_defined %} +sampling_rate[{{ nf_server_key }}]: {{ netflow.sampling_rate }} +{% endif %} +{% if netflow.source_address is vyos_defined %} +nfprobe_source_ip[{{ nf_server_key }}]: {{ netflow.source_address }} +{% endif %} +{% if netflow.timeout is vyos_defined %} +nfprobe_timeouts[{{ nf_server_key }}]: expint={{ netflow.timeout.expiry_interval }}:general={{ netflow.timeout.flow_generic }}:icmp={{ netflow.timeout.icmp }}:maxlife={{ netflow.timeout.max_active_life }}:tcp.fin={{ netflow.timeout.tcp_fin }}:tcp={{ netflow.timeout.tcp_generic }}:tcp.rst={{ netflow.timeout.tcp_rst }}:udp={{ netflow.timeout.udp }} +{% endif %} + +{% endfor %} +{% endif %} + +{% if sflow.server is vyos_defined %} +# sFlow servers +{% for server, server_config in sflow.server.items() %} +{# # prevent pmacct syntax error when using IPv6 flow collectors #} +{% set sf_server_key = 'sf_' ~ server | replace(':', '.') %} +sfprobe_receiver[{{ sf_server_key }}]: {{ server | bracketize_ipv6 }}:{{ server_config.port }} +sfprobe_agentip[{{ sf_server_key }}]: {{ sflow.agent_address }} +{% if sflow.sampling_rate is vyos_defined %} +sampling_rate[{{ sf_server_key }}]: {{ sflow.sampling_rate }} +{% endif %} +{% if sflow.source_address is vyos_defined %} +sfprobe_source_ip[{{ sf_server_key }}]: {{ sflow.source_address }} +{% endif %} + +{% endfor %} +{% endif %} diff --git a/data/templates/pppoe/ip-down.script.tmpl b/data/templates/pppoe/ip-down.script.tmpl deleted file mode 100644 index bac4155d6..000000000 --- a/data/templates/pppoe/ip-down.script.tmpl +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -# As PPPoE is an "on demand" interface we need to re-configure it when it -# becomes up -if [ "$6" != "{{ ifname }}" ]; then - exit -fi - -# add some info to syslog -DIALER_PID=$(cat /var/run/{{ ifname }}.pid) -logger -t pppd[$DIALER_PID] "executing $0" - -{% if connect_on_demand is not defined %} -# See https://phabricator.vyos.net/T2248. Determine if we are enslaved to a -# VRF, this is needed to properly insert the default route. -VRF_NAME="" -if [ -d /sys/class/net/{{ ifname }}/upper_* ]; then - # Determine upper (VRF) interface - VRF=$(basename $(ls -d /sys/class/net/{{ ifname }}/upper_*)) - # Remove upper_ prefix from result string - VRF=${VRF#"upper_"} - # Populate variable to run in VR context - VRF_NAME="vrf ${VRF_NAME}" -fi - -{% if default_route != 'none' %} -# Always delete default route when interface goes down if we installed it -vtysh -c "conf t" ${VRF_NAME} -c "no ip route 0.0.0.0/0 {{ ifname }} ${VRF_NAME}" -{% if ipv6 is defined and ipv6.address is defined and ipv6.address.autoconf is defined %} -vtysh -c "conf t" ${VRF_NAME} -c "no ipv6 route ::/0 {{ ifname }} ${VRF_NAME}" -{% endif %} -{% endif %} -{% endif %} - -{% if dhcpv6_options is defined and dhcpv6_options.pd is defined %} -# Stop wide dhcpv6 client -systemctl stop dhcp6c@{{ ifname }}.service -{% endif %} diff --git a/data/templates/pppoe/ip-pre-up.script.tmpl b/data/templates/pppoe/ip-pre-up.script.tmpl deleted file mode 100644 index a54e4e9bd..000000000 --- a/data/templates/pppoe/ip-pre-up.script.tmpl +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -# As PPPoE is an "on demand" interface we need to re-configure it when it -# becomes up -if [ "$6" != "{{ ifname }}" ]; then - exit -fi - -# add some info to syslog -DIALER_PID=$(cat /var/run/{{ ifname }}.pid) -logger -t pppd[$DIALER_PID] "executing $0" - -echo "{{ description }}" > /sys/class/net/{{ ifname }}/ifalias - -{% if vrf %} -logger -t pppd[$DIALER_PID] "configuring dialer interface $6 for VRF {{ vrf }}" -ip link set dev {{ ifname }} master {{ vrf }} -{% endif %} diff --git a/data/templates/pppoe/ip-up.script.tmpl b/data/templates/pppoe/ip-up.script.tmpl deleted file mode 100644 index 302756960..000000000 --- a/data/templates/pppoe/ip-up.script.tmpl +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh - -# As PPPoE is an "on demand" interface we need to re-configure it when it -# becomes up -if [ "$6" != "{{ ifname }}" ]; then - exit -fi - -{% if connect_on_demand is not defined %} -# add some info to syslog -DIALER_PID=$(cat /var/run/{{ ifname }}.pid) -logger -t pppd[$DIALER_PID] "executing $0" - -{% if default_route != 'none' %} -# See https://phabricator.vyos.net/T2248 & T2220. Determine if we are enslaved -# to a VRF, this is needed to properly insert the default route. - -SED_OPT="^ip route" -VRF_NAME="" -if [ -d /sys/class/net/{{ ifname }}/upper_* ]; then - # Determine upper (VRF) interface - VRF=$(basename $(ls -d /sys/class/net/{{ ifname }}/upper_*)) - # Remove upper_ prefix from result string - VRF=${VRF#"upper_"} - # generate new SED command - SED_OPT="vrf ${VRF}" - # generate vtysh option - VRF_NAME="vrf ${VRF}" -fi - -{% if default_route == 'auto' %} -# Only insert a new default route if there is no default route configured -routes=$(vtysh -c "show running-config" | sed -n "/${SED_OPT}/,/!/p" | grep 0.0.0.0/0 | wc -l) -if [ "$routes" -ne 0 ]; then - exit 1 -fi - -{% elif default_route == 'force' %} -# Retrieve current static default routes and remove it from the routing table -vtysh -c "show running-config" | sed -n "/${SED_OPT}/,/!/p" | grep 0.0.0.0/0 | while read route ; do - vtysh -c "conf t" ${VTY_OPT} -c "no ${route} ${VRF_NAME}" -done -{% endif %} - -# Add default route to default or VRF routing table -vtysh -c "conf t" ${VTY_OPT} -c "ip route 0.0.0.0/0 {{ ifname }} ${VRF_NAME}" -logger -t pppd[$DIALER_PID] "added default route via {{ ifname }} ${VRF_NAME}" -{% endif %} -{% endif %} diff --git a/data/templates/pppoe/ipv6-up.script.tmpl b/data/templates/pppoe/ipv6-up.script.tmpl deleted file mode 100644 index da73cb4d5..000000000 --- a/data/templates/pppoe/ipv6-up.script.tmpl +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh - -# As PPPoE is an "on demand" interface we need to re-configure it when it -# becomes up - -if [ "$6" != "{{ ifname }}" ]; then - exit -fi - - -{% if default_route != 'none' %} -# See https://phabricator.vyos.net/T2248 & T2220. Determine if we are enslaved -# to a VRF, this is needed to properly insert the default route. - -SED_OPT="^ipv6 route" -VRF_NAME="" -if [ -d /sys/class/net/{{ ifname }}/upper_* ]; then - # Determine upper (VRF) interface - VRF=$(basename $(ls -d /sys/class/net/{{ ifname }}/upper_*)) - # Remove upper_ prefix from result string - VRF=${VRF#"upper_"} - # generate new SED command - SED_OPT="vrf ${VRF}" - # generate vtysh option - VRF_NAME="vrf ${VRF}" -fi - -{% if default_route == 'auto' %} -# Only insert a new default route if there is no default route configured -routes=$(vtysh -c "show running-config" | sed -n "/${SED_OPT}/,/!/p" | grep ::/0 | wc -l) -if [ "$routes" -ne 0 ]; then - exit 1 -fi - -{% elif default_route == 'force' %} -# Retrieve current static default routes and remove it from the routing table -vtysh -c "show running-config" | sed -n "/${SED_OPT}/,/!/p" | grep ::/0 | while read route ; do - vtysh -c "conf t" ${VTY_OPT} -c "no ${route} ${VRF_NAME}" -done -{% endif %} - -# Add default route to default or VRF routing table -vtysh -c "conf t" ${VTY_OPT} -c "ipv6 route ::/0 {{ ifname }} ${VRF_NAME}" -logger -t pppd[$DIALER_PID] "added default route via {{ ifname }} ${VRF_NAME}" -{% endif %} - diff --git a/data/templates/pppoe/peer.tmpl b/data/templates/pppoe/peer.j2 index 928ed1238..6221abb9b 100644 --- a/data/templates/pppoe/peer.tmpl +++ b/data/templates/pppoe/peer.j2 @@ -1,5 +1,5 @@ ### Autogenerated by interfaces-pppoe.py ### -{{ '# ' ~ description if description is defined else '' }} +{{ '# ' ~ description if description is vyos_defined else '' }} # Require peer to provide the local IP address if it is not # specified explicitly in the config file. @@ -35,10 +35,10 @@ noproxyarp maxfail 0 plugin rp-pppoe.so {{ source_interface }} -{% if access_concentrator is defined and access_concentrator is not none %} +{% if access_concentrator is vyos_defined %} rp_pppoe_ac '{{ access_concentrator }}' {% endif %} -{% if service_name is defined and service_name is not none %} +{% if service_name is vyos_defined %} rp_pppoe_service '{{ service_name }}' {% endif %} @@ -49,34 +49,34 @@ debug mtu {{ mtu }} mru {{ mtu }} -{% if authentication is defined %} -{{ 'user "' + authentication.user + '"' if authentication.user is defined }} -{{ 'password "' + authentication.password + '"' if authentication.password is defined }} +{% if authentication is vyos_defined %} +{{ 'user "' + authentication.user + '"' if authentication.user is vyos_defined }} +{{ 'password "' + authentication.password + '"' if authentication.password is vyos_defined }} {% endif %} -{{ "usepeerdns" if no_peer_dns is not defined }} +{{ "usepeerdns" if no_peer_dns is not vyos_defined }} -{% if ipv6 is defined %} -+ipv6 {{ 'ipv6cp-use-ipaddr' if ipv6.address is defined and ipv6.address.autoconf is defined }} +{% if ipv6 is vyos_defined %} ++ipv6 {{ 'ipv6cp-use-ipaddr' if ipv6.address.autoconf is vyos_defined }} {% else %} noipv6 {% endif %} -{% if connect_on_demand is defined %} +{% if connect_on_demand is vyos_defined %} demand # See T2249. PPP default route options should only be set when in on-demand # mode. As soon as we are not in on-demand mode the default-route handling is # passed to the ip-up.d/ip-down.s scripts which is required for VRF support. -{% if 'auto' in default_route %} +{% if 'auto' in default_route %} defaultroute -{{ 'defaultroute6' if ipv6 is defined }} -{% elif 'force' in default_route %} +{{ 'defaultroute6' if ipv6 is vyos_defined }} +{% elif 'force' in default_route %} defaultroute replacedefaultroute -{{ 'defaultroute6' if ipv6 is defined }} -{% endif %} +{{ 'defaultroute6' if ipv6 is vyos_defined }} +{% endif %} {% else %} nodefaultroute noreplacedefaultroute -{{ 'nodefaultroute6' if ipv6 is defined }} +{{ 'nodefaultroute6' if ipv6 is vyos_defined }} {% endif %} diff --git a/data/templates/router-advert/radvd.conf.j2 b/data/templates/router-advert/radvd.conf.j2 new file mode 100644 index 000000000..6902dc05a --- /dev/null +++ b/data/templates/router-advert/radvd.conf.j2 @@ -0,0 +1,66 @@ +### Autogenerated by service_router-advert.py ### + +{% if interface is vyos_defined %} +{% for iface, iface_config in interface.items() %} +interface {{ iface }} { + IgnoreIfMissing on; +{% if iface_config.default_preference is vyos_defined %} + AdvDefaultPreference {{ iface_config.default_preference }}; +{% endif %} +{% if iface_config.managed_flag is vyos_defined %} + AdvManagedFlag {{ 'on' if iface_config.managed_flag is vyos_defined else 'off' }}; +{% endif %} +{% if iface_config.interval.max is vyos_defined %} + MaxRtrAdvInterval {{ iface_config.interval.max }}; +{% endif %} +{% if iface_config.interval.min is vyos_defined %} + MinRtrAdvInterval {{ iface_config.interval.min }}; +{% endif %} +{% if iface_config.reachable_time is vyos_defined %} + AdvReachableTime {{ iface_config.reachable_time }}; +{% endif %} + AdvIntervalOpt {{ 'off' if iface_config.no_send_advert is vyos_defined else 'on' }}; + AdvSendAdvert {{ 'off' if iface_config.no_send_advert is vyos_defined else 'on' }}; +{% if iface_config.default_lifetime is vyos_defined %} + AdvDefaultLifetime {{ iface_config.default_lifetime }}; +{% endif %} +{% if iface_config.link_mtu is vyos_defined %} + AdvLinkMTU {{ iface_config.link_mtu }}; +{% endif %} + AdvOtherConfigFlag {{ 'on' if iface_config.other_config_flag is vyos_defined else 'off' }}; + AdvRetransTimer {{ iface_config.retrans_timer }}; + AdvCurHopLimit {{ iface_config.hop_limit }}; +{% if iface_config.route is vyos_defined %} +{% for route, route_options in iface_config.route.items() %} + route {{ route }} { +{% if route_options.valid_lifetime is vyos_defined %} + AdvRouteLifetime {{ route_options.valid_lifetime }}; +{% endif %} +{% if route_options.route_preference is vyos_defined %} + AdvRoutePreference {{ route_options.route_preference }}; +{% endif %} + RemoveRoute {{ 'off' if route_options.no_remove_route is vyos_defined else 'on' }}; + }; +{% endfor %} +{% endif %} +{% if iface_config.prefix is vyos_defined %} +{% for prefix, prefix_options in iface_config.prefix.items() %} + prefix {{ prefix }} { + AdvAutonomous {{ 'off' if prefix_options.no_autonomous_flag is vyos_defined else 'on' }}; + AdvValidLifetime {{ prefix_options.valid_lifetime }}; + AdvOnLink {{ 'off' if prefix_options.no_on_link_flag is vyos_defined else 'on' }}; + AdvPreferredLifetime {{ prefix_options.preferred_lifetime }}; + }; +{% endfor %} +{% endif %} +{% if iface_config.name_server is vyos_defined %} + RDNSS {{ iface_config.name_server | join(" ") }} { + }; +{% endif %} +{% if iface_config.dnssl is vyos_defined %} + DNSSL {{ iface_config.dnssl | join(" ") }} { + }; +{% endif %} +}; +{% endfor %} +{% endif %} diff --git a/data/templates/router-advert/radvd.conf.tmpl b/data/templates/router-advert/radvd.conf.tmpl deleted file mode 100644 index 88d066491..000000000 --- a/data/templates/router-advert/radvd.conf.tmpl +++ /dev/null @@ -1,66 +0,0 @@ -### Autogenerated by service_router-advert.py ### - -{% if interface is defined and interface is not none %} -{% for iface, iface_config in interface.items() %} -interface {{ iface }} { - IgnoreIfMissing on; -{% if iface_config.default_preference is defined and iface_config.default_preference is not none %} - AdvDefaultPreference {{ iface_config.default_preference }}; -{% endif %} -{% if iface_config.managed_flag is defined and iface_config.managed_flag is not none %} - AdvManagedFlag {{ 'on' if iface_config.managed_flag is defined else 'off' }}; -{% endif %} -{% if iface_config.interval.max is defined and iface_config.interval.max is not none %} - MaxRtrAdvInterval {{ iface_config.interval.max }}; -{% endif %} -{% if iface_config.interval.min is defined and iface_config.interval.min is not none %} - MinRtrAdvInterval {{ iface_config.interval.min }}; -{% endif %} -{% if iface_config.reachable_time is defined and iface_config.reachable_time is not none %} - AdvReachableTime {{ iface_config.reachable_time }}; -{% endif %} - AdvIntervalOpt {{ 'off' if iface_config.no_send_advert is defined else 'on' }}; - AdvSendAdvert {{ 'off' if iface_config.no_send_advert is defined else 'on' }}; -{% if iface_config.default_lifetime is defined %} - AdvDefaultLifetime {{ iface_config.default_lifetime }}; -{% endif %} -{% if iface_config.link_mtu is defined %} - AdvLinkMTU {{ iface_config.link_mtu }}; -{% endif %} - AdvOtherConfigFlag {{ 'on' if iface_config.other_config_flag is defined else 'off' }}; - AdvRetransTimer {{ iface_config.retrans_timer }}; - AdvCurHopLimit {{ iface_config.hop_limit }}; -{% if iface_config.route is defined %} -{% for route, route_options in iface_config.route.items() %} - route {{ route }} { -{% if route_options.valid_lifetime is defined %} - AdvRouteLifetime {{ route_options.valid_lifetime }}; -{% endif %} -{% if route_options.route_preference is defined %} - AdvRoutePreference {{ route_options.route_preference }}; -{% endif %} - RemoveRoute {{ 'off' if route_options.no_remove_route is defined else 'on' }}; - }; -{% endfor %} -{% endif %} -{% if iface_config.prefix is defined and iface_config.prefix is not none %} -{% for prefix, prefix_options in iface_config.prefix.items() %} - prefix {{ prefix }} { - AdvAutonomous {{ 'off' if prefix_options.no_autonomous_flag is defined else 'on' }}; - AdvValidLifetime {{ prefix_options.valid_lifetime }}; - AdvOnLink {{ 'off' if prefix_options.no_on_link_flag is defined else 'on' }}; - AdvPreferredLifetime {{ prefix_options.preferred_lifetime }}; - }; -{% endfor %} -{% endif %} -{% if iface_config.name_server is defined %} - RDNSS {{ iface_config.name_server | join(" ") }} { - }; -{% endif %} -{% if iface_config.dnssl is defined %} - DNSSL {{ iface_config.dnssl | join(" ") }} { - }; -{% endif %} -}; -{% endfor %} -{% endif %} diff --git a/data/templates/salt-minion/minion.tmpl b/data/templates/salt-minion/minion.j2 index 99749b57a..f4001db64 100644 --- a/data/templates/salt-minion/minion.tmpl +++ b/data/templates/salt-minion/minion.j2 @@ -32,17 +32,17 @@ log_file: /var/log/salt/minion # ['garbage', 'trace', 'debug'] # # Default: 'warning' -log_level: {{ log_level }} +log_level: warning # Set the location of the salt master server, if the master server cannot be # resolved, then the minion will fail to start. master: {% for host in master %} -- {{ host }} + - {{ host | bracketize_ipv6 }} {% endfor %} # The user to run salt -user: {{ user }} +user: minion # The directory to store the pki information in pki_dir: /config/salt/pki/minion @@ -52,10 +52,16 @@ pki_dir: /config/salt/pki/minion # Since salt uses detached ids it is possible to run multiple minions on the # same machine but with different ids, this can be useful for salt compute # clusters. -id: {{ salt_id }} - +id: {{ id }} # The number of minutes between mine updates. mine_interval: {{ interval }} -verify_master_pubkey_sign: {{ verify_master_pubkey_sign }} +{% if source_interface is vyos_defined %} +# The name of the interface to use when establishing the connection to the Master. +source_interface_name: {{ source_interface }} +{% endif %} + +# Enables verification of the master-public-signature returned by the master +# in auth-replies. +verify_master_pubkey_sign: {{ 'True' if master_key is vyos_defined else 'False' }} diff --git a/data/templates/snmp/etc.snmp.conf.tmpl b/data/templates/snmp/etc.snmp.conf.j2 index 6e4c6f063..8012cf6bb 100644 --- a/data/templates/snmp/etc.snmp.conf.tmpl +++ b/data/templates/snmp/etc.snmp.conf.j2 @@ -1,4 +1,4 @@ ### Autogenerated by snmp.py ### -{% if trap_source %} +{% if trap_source is vyos_defined %} clientaddr {{ trap_source }} {% endif %} diff --git a/data/templates/snmp/etc.snmpd.conf.j2 b/data/templates/snmp/etc.snmpd.conf.j2 new file mode 100644 index 000000000..d7dc0ba5d --- /dev/null +++ b/data/templates/snmp/etc.snmpd.conf.j2 @@ -0,0 +1,182 @@ +### Autogenerated by snmp.py ### + +# non configurable defaults +sysObjectID 1.3.6.1.4.1.44641 +sysServices 14 +master agentx +agentXPerms 0777 0777 +pass .1.3.6.1.2.1.31.1.1.1.18 /opt/vyatta/sbin/if-mib-alias +smuxpeer .1.3.6.1.2.1.83 +smuxpeer .1.3.6.1.2.1.157 +smuxsocket localhost + +# linkUp/Down configure the Event MIB tables to monitor +# the ifTable for network interfaces being taken up or down +# for making internal queries to retrieve any necessary information +iquerySecName {{ vyos_user }} + +# Modified from the default linkUpDownNotification +# to include more OIDs and poll more frequently +notificationEvent linkUpTrap linkUp ifIndex ifDescr ifType ifAdminStatus ifOperStatus +notificationEvent linkDownTrap linkDown ifIndex ifDescr ifType ifAdminStatus ifOperStatus +monitor -r 10 -e linkUpTrap "Generate linkUp" ifOperStatus != 2 +monitor -r 10 -e linkDownTrap "Generate linkDown" ifOperStatus == 2 + +# Remove all old ifTable entries with the same ifName as newly appeared +# interface (with different ifIndex) - this is the case on e.g. ppp interfaces +interface_replace_old yes + +######################## +# configurable section # +######################## + +# Default system description is VyOS version +sysDescr VyOS {{ version }} + +{% if description is vyos_defined %} +# Description +SysDescr {{ description }} +{% endif %} + +# Listen +{% set options = [] %} +{% if listen_address is vyos_defined %} +{% for address, address_options in listen_address.items() %} +{% if address | is_ipv6 %} +{% set protocol = protocol ~ '6' %} +{% endif %} +{% set _ = options.append(protocol ~ ':' ~ address | bracketize_ipv6 ~ ':' ~ address_options.port) %} +{% endfor %} +{% else %} +{% set _ = options.append(protocol ~ ':161') %} +{% set _ = options.append(protocol ~ '6:161') %} +{% endif %} +agentaddress unix:/run/snmpd.socket{{ ',' ~ options | join(',') if options is vyos_defined }} + +# SNMP communities +{% if community is vyos_defined %} +{% for comm, comm_config in community.items() %} +{% if comm_config.client is vyos_defined %} +{% for client in comm_config.client %} +{% if client | is_ipv4 %} +{{ comm_config.authorization }}community {{ comm }} {{ client }} +{% elif client | is_ipv6 %} +{{ comm_config.authorization }}community6 {{ comm }} {{ client }} +{% endif %} +{% endfor %} +{% endif %} +{% if comm_config.network is vyos_defined %} +{% for network in comm_config.network %} +{% if network | is_ipv4 %} +{{ comm_config.authorization }}community {{ comm }} {{ network }} +{% elif client | is_ipv6 %} +{{ comm_config.authorization }}community6 {{ comm }} {{ network }} +{% endif %} +{% endfor %} +{% endif %} +{% if comm_config.client is not vyos_defined and comm_config.network is not vyos_defined %} +{{ comm_config.authorization }}community {{ comm }} +{% endif %} +{% endfor %} +{% endif %} + +{% if contact is vyos_defined %} +# system contact information +SysContact {{ contact }} +{% endif %} + +{% if location is vyos_defined %} +# system location information +SysLocation {{ location }} +{% endif %} + +{% if smux_peer is vyos_defined %} +# additional smux peers +{% for peer in smux_peer %} +smuxpeer {{ peer }} +{% endfor %} +{% endif %} + +{% if trap_target is vyos_defined %} +# if there is a problem - tell someone! +{% for trap, trap_config in trap_target.items() %} +trap2sink {{ trap }}:{{ trap_config.port }} {{ trap_config.community }} +{% endfor %} +{% endif %} + +{% if v3 is vyos_defined %} +# +# SNMPv3 stuff goes here +# +{% if v3.view is vyos_defined %} +# views +{% for view, view_config in v3.view.items() %} +{% if view_config.oid is vyos_defined %} +{% for oid in view_config.oid %} +view {{ view }} included .{{ oid }} +{% endfor %} +{% endif %} +{% endfor %} +{% endif %} + +# access +{% if v3.group is vyos_defined %} +# context sec.model sec.level match read write notif +{% for group, group_config in v3.group.items() %} +access {{ group }} "" usm {{ group_config.seclevel }} exact {{ group_config.view }} {{ 'none' if group_config.mode == 'ro' else group_config.view }} none +{% endfor %} +{% endif %} + +# trap-target +{% if v3.trap_target is vyos_defined %} +{% for trap, trap_config in v3.trap_target.items() %} +{% set options = '' %} +{% if trap_config.type == 'inform' %} +{% set options = options ~ ' -Ci' %} +{% endif %} +{% if v3.engineid is vyos_defined %} +{% set options = options ~ ' -e "' ~ v3.engineid ~ '"' %} +{% endif %} +{% if trap_config.user is vyos_defined %} +{% set options = options ~ ' -u ' ~ trap_config.user %} +{% endif %} +{% if trap_config.auth.plaintext_password is vyos_defined or trap_config.auth.encrypted_password is vyos_defined %} +{% set options = options ~ ' -a ' ~ trap_config.auth.type %} +{% if trap_config.auth.plaintext_password is vyos_defined %} +{% set options = options ~ ' -A ' ~ trap_config.auth.plaintext_password %} +{% elif trap_config.auth.encrypted_password is vyos_defined %} +{% set options = options ~ ' -3m ' ~ trap_config.auth.encrypted_password %} +{% endif %} +{% if trap_config.privacy.plaintext_password is vyos_defined or trap_config.privacy.encrypted_password is vyos_defined %} +{% set options = options ~ ' -x ' ~ trap_config.privacy.type %} +{% if trap_config.privacy.plaintext_password is vyos_defined %} +{% set options = options ~ ' -X ' ~ trap_config.privacy.plaintext_password %} +{% elif trap_config.privacy.encrypted_password is vyos_defined %} +{% set options = options ~ ' -3M ' ~ trap_config.privacy.encrypted_password %} +{% endif %} +{% set options = options ~ ' -l authPriv' %} +{% else %} +{% set options = options ~ ' -l authNoPriv' %} +{% endif %} +{% else %} +{% set options = options ~ ' -l noAuthNoPriv' %} +{% endif %} +trapsess -v 3 {{ options }} {{ trap }}:{{ trap_config.protocol }}:{{ trap_config.port }} +{% endfor %} +{% endif %} + +# group +{% if v3.user is vyos_defined %} +{% for user, user_config in v3.user.items() %} +group {{ user_config.group }} usm {{ user }} +{% endfor %} +{% endif %} +{# SNMPv3 end #} +{% endif %} + +{% if script_extensions.extension_name is vyos_defined %} +# extension scripts +{% for script, script_config in script_extensions.extension_name.items() | sort(attribute=script) %} +extend {{ script }} {{ script_config.script }} +{% endfor %} +{% endif %} diff --git a/data/templates/snmp/etc.snmpd.conf.tmpl b/data/templates/snmp/etc.snmpd.conf.tmpl deleted file mode 100644 index 30806ce8a..000000000 --- a/data/templates/snmp/etc.snmpd.conf.tmpl +++ /dev/null @@ -1,119 +0,0 @@ -### Autogenerated by snmp.py ### - -# non configurable defaults -sysObjectID 1.3.6.1.4.1.44641 -sysServices 14 -master agentx -agentXPerms 0777 0777 -pass .1.3.6.1.2.1.31.1.1.1.18 /opt/vyatta/sbin/if-mib-alias -smuxpeer .1.3.6.1.2.1.83 -smuxpeer .1.3.6.1.2.1.157 -smuxsocket localhost - -# linkUp/Down configure the Event MIB tables to monitor -# the ifTable for network interfaces being taken up or down -# for making internal queries to retrieve any necessary information -iquerySecName {{ vyos_user }} - -# Modified from the default linkUpDownNotification -# to include more OIDs and poll more frequently -notificationEvent linkUpTrap linkUp ifIndex ifDescr ifType ifAdminStatus ifOperStatus -notificationEvent linkDownTrap linkDown ifIndex ifDescr ifType ifAdminStatus ifOperStatus -monitor -r 10 -e linkUpTrap "Generate linkUp" ifOperStatus != 2 -monitor -r 10 -e linkDownTrap "Generate linkDown" ifOperStatus == 2 - -# Remove all old ifTable entries with the same ifName as newly appeared -# interface (with different ifIndex) - this is the case on e.g. ppp interfaces -interface_replace_old yes - -######################## -# configurable section # -######################## - -# Default system description is VyOS version -sysDescr VyOS {{ version }} - -{% if description %} -# Description -SysDescr {{ description }} -{% endif %} - -# Listen -agentaddress unix:/run/snmpd.socket{% if listen_on %}{% for li in listen_on %},{{ li }}{% endfor %}{% else %},{{protocol}}:161{% if ipv6_enabled %},{{protocol}}6:161{% endif %}{% endif %} - -# SNMP communities -{% for c in communities %} -{% if c.network_v4 %} -{% for network in c.network_v4 %} -{{ c.authorization }}community {{ c.name }} {{ network }} -{% endfor %} -{% elif not c.has_source %} -{{ c.authorization }}community {{ c.name }} -{% endif %} -{% if c.network_v6 %} -{% for network in c.network_v6 %} -{{ c.authorization }}community6 {{ c.name }} {{ network }} -{% endfor %} -{% elif not c.has_source %} -{{ c.authorization }}community6 {{ c.name }} -{% endif %} -{% endfor %} - -{% if contact %} -# system contact information -SysContact {{ contact }} -{% endif %} - -{% if location %} -# system location information -SysLocation {{ location }} -{% endif %} - -{% if smux_peers %} -# additional smux peers -{% for sp in smux_peers %} -smuxpeer {{ sp }} -{% endfor %} -{% endif %} - -{% if trap_targets %} -# if there is a problem - tell someone! -{% for trap in trap_targets %} -trap2sink {{ trap.target }}{{ ":" + trap.port if trap.port is defined }} {{ trap.community }} -{% endfor %} -{% endif %} - -{% if v3_enabled %} -# -# SNMPv3 stuff goes here -# -# views -{% for view in v3_views %} -{% for oid in view.oids %} -view {{ view.name }} included .{{ oid.oid }} -{% endfor %} -{% endfor %} - -# access -# context sec.model sec.level match read write notif -{% for group in v3_groups %} -access {{ group.name }} "" usm {{ group.seclevel }} exact {{ group.view }} {% if group.mode == 'ro' %}none{% else %}{{ group.view }}{% endif %} none -{% endfor %} - -# trap-target -{% for t in v3_traps %} -trapsess -v 3 {{ '-Ci' if t.type == 'inform' }} -e {{ v3_engineid }} -u {{ t.secName }} -l {{ t.secLevel }} -a {{ t.authProtocol }} {% if t.authPassword %}-A {{ t.authPassword }}{% elif t.authMasterKey %}-3m {{ t.authMasterKey }}{% endif %} -x {{ t.privProtocol }} {% if t.privPassword %}-X {{ t.privPassword }}{% elif t.privMasterKey %}-3M {{ t.privMasterKey }}{% endif %} {{ t.ipProto }}:{{ t.ipAddr }}:{{ t.ipPort }} -{% endfor %} - -# group -{% for u in v3_users %} -group {{ u.group }} usm {{ u.name }} -{% endfor %} -{% endif %} - -{% if script_ext %} -# extension scripts -{% for ext in script_ext|sort(attribute='name') %} -extend {{ ext.name }} {{ ext.script }} -{% endfor %} -{% endif %} diff --git a/data/templates/snmp/override.conf.j2 b/data/templates/snmp/override.conf.j2 new file mode 100644 index 000000000..5d787de86 --- /dev/null +++ b/data/templates/snmp/override.conf.j2 @@ -0,0 +1,14 @@ +{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %} +{% set oid_route_table = ' ' if oid_enable is vyos_defined('route-table') else '-I -ipCidrRouteTable,inetCidrRouteTable' %} +[Unit] +StartLimitIntervalSec=0 +After=vyos-router.service + +[Service] +Environment= +Environment="MIBDIRS=/usr/share/snmp/mibs:/usr/share/snmp/mibs/iana:/usr/share/snmp/mibs/ietf:/usr/share/vyos/mibs" +ExecStart= +ExecStart={{ vrf_command }}/usr/sbin/snmpd -LS0-5d -Lf /dev/null -u Debian-snmp -g Debian-snmp {{ oid_route_table }} -f -p /run/snmpd.pid +Restart=always +RestartSec=10 + diff --git a/data/templates/snmp/override.conf.tmpl b/data/templates/snmp/override.conf.tmpl deleted file mode 100644 index 2ac45a89f..000000000 --- a/data/templates/snmp/override.conf.tmpl +++ /dev/null @@ -1,14 +0,0 @@ -{% set vrf_command = 'ip vrf exec ' + vrf + ' ' if vrf is defined else '' %} -{% set oid_route_table = ' ' if route_table is sameas true else '-I -ipCidrRouteTable,inetCidrRouteTable' %} -[Unit] -StartLimitIntervalSec=0 -After=vyos-router.service - -[Service] -Environment= -Environment="MIBDIRS=/usr/share/snmp/mibs:/usr/share/snmp/mibs/iana:/usr/share/snmp/mibs/ietf:/usr/share/vyos/mibs" -ExecStart= -ExecStart={{vrf_command}}/usr/sbin/snmpd -LS0-5d -Lf /dev/null -u Debian-snmp -g Debian-snmp {{oid_route_table}} -f -p /run/snmpd.pid -Restart=always -RestartSec=10 - diff --git a/data/templates/snmp/usr.snmpd.conf.j2 b/data/templates/snmp/usr.snmpd.conf.j2 new file mode 100644 index 000000000..a713c1cec --- /dev/null +++ b/data/templates/snmp/usr.snmpd.conf.j2 @@ -0,0 +1,8 @@ +### Autogenerated by snmp.py ### +{% if v3.user is vyos_defined %} +{% for user, user_config in v3.user.items() %} +{{ user_config.mode }}user {{ user }} +{% endfor %} +{% endif %} + +rwuser {{ vyos_user }} diff --git a/data/templates/snmp/usr.snmpd.conf.tmpl b/data/templates/snmp/usr.snmpd.conf.tmpl deleted file mode 100644 index e2c5ec102..000000000 --- a/data/templates/snmp/usr.snmpd.conf.tmpl +++ /dev/null @@ -1,6 +0,0 @@ -### Autogenerated by snmp.py ### -{% for u in v3_users %} -{{ u.mode }}user {{ u.name }} -{% endfor %} - -rwuser {{ vyos_user }} diff --git a/data/templates/snmp/var.snmpd.conf.j2 b/data/templates/snmp/var.snmpd.conf.j2 new file mode 100644 index 000000000..012f33aeb --- /dev/null +++ b/data/templates/snmp/var.snmpd.conf.j2 @@ -0,0 +1,16 @@ +### Autogenerated by snmp.py ### +# user +{% if v3 is vyos_defined %} +{% if v3.user is vyos_defined %} +{% for user, user_config in v3.user.items() %} +usmUser 1 3 0x{{ v3.engineid }} "{{ user }}" "{{ user }}" NULL {{ user_config.auth.type | snmp_auth_oid }} 0x{{ user_config.auth.encrypted_password }} {{ user_config.privacy.type | snmp_auth_oid }} 0x{{ user_config.privacy.encrypted_password }} 0x +{% endfor %} +{% endif %} + +# VyOS default user +createUser {{ vyos_user }} MD5 "{{ vyos_user_pass }}" DES + +{% if v3.engineid is vyos_defined %} +oldEngineID 0x{{ v3.engineid }} +{% endif %} +{% endif %} diff --git a/data/templates/snmp/var.snmpd.conf.tmpl b/data/templates/snmp/var.snmpd.conf.tmpl deleted file mode 100644 index c779587df..000000000 --- a/data/templates/snmp/var.snmpd.conf.tmpl +++ /dev/null @@ -1,14 +0,0 @@ -### Autogenerated by snmp.py ### -# user -{% for u in v3_users %} -{% if u.authOID == 'none' %} -createUser {{ u.name }} -{% else %} -usmUser 1 3 0x{{ v3_engineid }} "{{ u.name }}" "{{ u.name }}" NULL {{ u.authOID }} 0x{{ u.authMasterKey }} {{ u.privOID }} 0x{{ u.privMasterKey }} 0x -{% endif %} -{% endfor %} - -createUser {{ vyos_user }} MD5 "{{ vyos_user_pass }}" DES -{% if v3_engineid %} -oldEngineID 0x{{ v3_engineid }} -{% endif %} diff --git a/data/templates/squid/sg_acl.conf.tmpl b/data/templates/squid/sg_acl.conf.j2 index ce72b173a..ce72b173a 100644 --- a/data/templates/squid/sg_acl.conf.tmpl +++ b/data/templates/squid/sg_acl.conf.j2 diff --git a/data/templates/squid/squid.conf.j2 b/data/templates/squid/squid.conf.j2 new file mode 100644 index 000000000..a0fdeb20e --- /dev/null +++ b/data/templates/squid/squid.conf.j2 @@ -0,0 +1,111 @@ +### generated by service_webproxy.py ### + +acl net src all +acl SSL_ports port 443 +acl Safe_ports port 80 # http +acl Safe_ports port 21 # ftp +acl Safe_ports port 443 # https +acl Safe_ports port 873 # rsync +acl Safe_ports port 70 # gopher +acl Safe_ports port 210 # wais +acl Safe_ports port 1025-65535 # unregistered ports +acl Safe_ports port 280 # http-mgmt +acl Safe_ports port 488 # gss-http +acl Safe_ports port 591 # filemaker +acl Safe_ports port 777 # multiling http +acl CONNECT method CONNECT + +{% if authentication is vyos_defined %} +{% if authentication.children is vyos_defined %} +auth_param basic children {{ authentication.children }} +{% endif %} +{% if authentication.credentials_ttl is vyos_defined %} +auth_param basic credentialsttl {{ authentication.credentials_ttl }} minute +{% endif %} +{% if authentication.realm is vyos_defined %} +auth_param basic realm "{{ authentication.realm }}" +{% endif %} +{# LDAP based Authentication #} +{% if authentication.method is vyos_defined %} +{% if authentication.ldap is vyos_defined and authentication.method is vyos_defined('ldap') %} +auth_param basic program /usr/lib/squid/basic_ldap_auth -v {{ authentication.ldap.version }} -b "{{ authentication.ldap.base_dn }}" {{ '-D "' ~ authentication.ldap.bind_dn ~ '"' if authentication.ldap.bind_dn is vyos_defined }} {{ '-w "' ~ authentication.ldap.password ~ '"' if authentication.ldap.password is vyos_defined }} {{ '-f "' ~ authentication.ldap.filter_expression ~ '"' if authentication.ldap.filter_expression is vyos_defined }} {{ '-u "' ~ authentication.ldap.username_attribute ~ '"' if authentication.ldap.username_attribute is vyos_defined }} -p {{ authentication.ldap.port }} {{ '-ZZ' if authentication.ldap.use_ssl is vyos_defined }} -R -h "{{ authentication.ldap.server }}" +{% endif %} +acl auth proxy_auth REQUIRED +http_access allow auth +{% endif %} +{% endif %} + +http_access allow manager localhost +http_access deny manager +http_access deny !Safe_ports +http_access deny CONNECT !SSL_ports +http_access allow localhost +http_access allow net +http_access deny all + +{% if reply_block_mime is vyos_defined %} +{% for mime_type in reply_block_mime %} +acl BLOCK_MIME rep_mime_type {{ mime_type }} +{% endfor %} +http_reply_access deny BLOCK_MIME +{% endif %} + +{% if cache_size is vyos_defined %} +{% if cache_size | int > 0 %} +cache_dir ufs /var/spool/squid {{ cache_size }} 16 256 +{% else %} +# disabling disk cache +{% endif %} +{% endif %} +{% if mem_cache_size is vyos_defined %} +cache_mem {{ mem_cache_size }} MB +{% endif %} +{% if disable_access_log is vyos_defined %} +access_log none +{% else %} +access_log /var/log/squid/access.log squid +{% endif %} + +{# by default we'll disable the store log #} +cache_store_log none + +{% if append_domain is vyos_defined %} +append_domain {{ append_domain }} +{% endif %} +{% if maximum_object_size is vyos_defined %} +maximum_object_size {{ maximum_object_size }} KB +{% endif %} +{% if minimum_object_size is vyos_defined %} +minimum_object_size {{ minimum_object_size }} KB +{% endif %} +{% if reply_body_max_size is vyos_defined %} +reply_body_max_size {{ reply_body_max_size }} KB +{% endif %} +{% if outgoing_address is vyos_defined %} +tcp_outgoing_address {{ outgoing_address }} +{% endif %} + + +{% if listen_address is vyos_defined %} +{% for address, config in listen_address.items() %} +http_port {{ address | bracketize_ipv6 }}:{{ config.port if config.port is vyos_defined else default_port }} {{ 'intercept' if config.disable_transparent is not vyos_defined }} +{% endfor %} +{% endif %} +http_port 127.0.0.1:{{ default_port }} + +{# NOT insert the client address in X-Forwarded-For header #} +forwarded_for off + +{# SquidGuard #} +{% if url_filtering.disable is not vyos_defined and url_filtering.squidguard is vyos_defined %} +url_rewrite_program /usr/bin/squidGuard -c {{ squidguard_conf }} +url_rewrite_children 8 +url_rewrite_bypass on +{% endif %} + +{% if cache_peer is vyos_defined %} +{% for peer, config in cache_peer.items() %} +cache_peer {{ config.address }} {{ config.type }} {{ config.http_port }} {{ config.icp_port }} {{ config.options }} +{% endfor %} +never_direct allow all +{% endif %} diff --git a/data/templates/squid/squid.conf.tmpl b/data/templates/squid/squid.conf.tmpl deleted file mode 100644 index 80826fc75..000000000 --- a/data/templates/squid/squid.conf.tmpl +++ /dev/null @@ -1,113 +0,0 @@ -### generated by service_webproxy.py ### - -acl net src all -acl SSL_ports port 443 -acl Safe_ports port 80 # http -acl Safe_ports port 21 # ftp -acl Safe_ports port 443 # https -acl Safe_ports port 873 # rsync -acl Safe_ports port 70 # gopher -acl Safe_ports port 210 # wais -acl Safe_ports port 1025-65535 # unregistered ports -acl Safe_ports port 280 # http-mgmt -acl Safe_ports port 488 # gss-http -acl Safe_ports port 591 # filemaker -acl Safe_ports port 777 # multiling http -acl CONNECT method CONNECT - -{% if authentication is defined and authentication is not none %} -{% if authentication.children is defined and authentication.children is not none %} -auth_param basic children {{ authentication.children }} -{% endif %} -{% if authentication.credentials_ttl is defined and authentication.credentials_ttl is not none %} -auth_param basic credentialsttl {{ authentication.credentials_ttl }} minute -{% endif %} -{% if authentication.realm is defined and authentication.realm is not none %} -auth_param basic realm "{{ authentication.realm }}" -{% endif %} -{# LDAP based Authentication #} -{% if authentication.method is defined and authentication.method is not none %} -{% if authentication.ldap is defined and authentication.ldap is not none and authentication.method == 'ldap' %} -auth_param basic program /usr/lib/squid/basic_ldap_auth -v {{ authentication.ldap.version }} -b "{{ authentication.ldap.base_dn }}" {{ '-D "' + authentication.ldap.bind_dn + '"' if authentication.ldap.bind_dn is defined }} {{ '-w "' + authentication.ldap.password + '"' if authentication.ldap.password is defined }} {{ '-f "' + authentication.ldap.filter_expression + '"' if authentication.ldap.filter_expression is defined }} {{ '-u "' + authentication.ldap.username_attribute + '"' if authentication.ldap.username_attribute is defined }} -p {{ authentication.ldap.port }} {{ '-ZZ' if authentication.ldap.use_ssl is defined }} -R -h "{{ authentication.ldap.server }}" -{% endif %} -acl auth proxy_auth REQUIRED -http_access allow auth -{% endif %} -{% endif %} - -http_access allow manager localhost -http_access deny manager -http_access deny !Safe_ports -http_access deny CONNECT !SSL_ports -http_access allow localhost -http_access allow net -http_access deny all - -{% if reply_block_mime is defined and reply_block_mime is not none %} -{% for mime_type in reply_block_mime %} -acl BLOCK_MIME rep_mime_type {{ mime_type }} -{% endfor %} -http_reply_access deny BLOCK_MIME -{% endif %} - -{% if cache_size is defined and cache_size is not none %} -{% if cache_size | int > 0 %} -cache_dir ufs /var/spool/squid {{ cache_size }} 16 256 -{% else %} -# disabling disk cache -{% endif %} -{% endif %} -{% if mem_cache_size is defined and mem_cache_size is not none %} -cache_mem {{ mem_cache_size }} MB -{% endif %} -{% if disable_access_log is defined %} -access_log none -{% else %} -access_log /var/log/squid/access.log squid -{% endif %} - -{# by default we'll disable the store log #} -cache_store_log none - -{% if append_domain is defined and append_domain is not none %} -append_domain {{ append_domain }} -{% endif %} -{% if maximum_object_size is defined and maximum_object_size is not none %} -maximum_object_size {{ maximum_object_size }} KB -{% endif %} -{% if minimum_object_size is defined and minimum_object_size is not none %} -minimum_object_size {{ minimum_object_size }} KB -{% endif %} -{% if reply_body_max_size is defined and reply_body_max_size is not none %} -reply_body_max_size {{ reply_body_max_size }} KB -{% endif %} -{% if outgoing_address is defined and outgoing_address is not none %} -tcp_outgoing_address {{ outgoing_address }} -{% endif %} - - -{% if listen_address is defined and listen_address is not none %} -{% for address, config in listen_address.items() %} -http_port {{ address }}:{{ config.port if config.port is defined else default_port }} {{ 'intercept' if config.disable_transparent is not defined }} -{% endfor %} -{% endif %} -http_port 127.0.0.1:{{ default_port }} - -{# NOT insert the client address in X-Forwarded-For header #} -forwarded_for off - -{# SquidGuard #} -{% if url_filtering is defined and url_filtering.disable is not defined %} -{% if url_filtering.squidguard is defined and url_filtering.squidguard is not none %} -url_rewrite_program /usr/bin/squidGuard -c {{ squidguard_conf }} -url_rewrite_children 8 -url_rewrite_bypass on -{% endif %} -{% endif %} - -{% if cache_peer is defined and cache_peer is not none %} -{% for peer, config in cache_peer.items() %} -cache_peer {{ config.address }} {{ config.type }} {{ config.http_port }} {{ config.icp_port }} {{ config.options }} -{% endfor %} -never_direct allow all -{% endif %} diff --git a/data/templates/squid/squidGuard.conf.j2 b/data/templates/squid/squidGuard.conf.j2 new file mode 100644 index 000000000..1bc4c984f --- /dev/null +++ b/data/templates/squid/squidGuard.conf.j2 @@ -0,0 +1,124 @@ +### generated by service_webproxy.py ### + +{% macro sg_rule(category, log, db_dir) %} +{% set expressions = db_dir + '/' + category + '/expressions' %} +dest {{ category }}-default { + domainlist {{ category }}/domains + urllist {{ category }}/urls +{% if expressions | is_file %} + expressionlist {{ category }}/expressions +{% endif %} +{% if log is vyos_defined %} + log blacklist.log +{% endif %} +} +{% endmacro %} + +{% if url_filtering is vyos_defined and url_filtering.disable is not vyos_defined %} +{% if url_filtering.squidguard is vyos_defined %} +{% set sg_config = url_filtering.squidguard %} +{% set acl = namespace(value='local-ok-default') %} +{% set acl.value = acl.value + ' !in-addr' if sg_config.allow_ipaddr_url is not defined else acl.value %} +dbhome {{ squidguard_db_dir }} +logdir /var/log/squid + +rewrite safesearch { + s@(.*\.google\..*/(custom|search|images|groups|news)?.*q=.*)@\1\&safe=active@i + s@(.*\..*/yandsearch?.*text=.*)@\1\&fyandex=1@i + s@(.*\.yahoo\..*/search.*p=.*)@\1\&vm=r@i + s@(.*\.live\..*/.*q=.*)@\1\&adlt=strict@i + s@(.*\.msn\..*/.*q=.*)@\1\&adlt=strict@i + s@(.*\.bing\..*/search.*q=.*)@\1\&adlt=strict@i + log rewrite.log +} + +{% if sg_config.local_ok is vyos_defined %} +{% set acl.value = acl.value + ' local-ok-default' %} +dest local-ok-default { + domainlist local-ok-default/domains +} +{% endif %} +{% if sg_config.local_ok_url is vyos_defined %} +{% set acl.value = acl.value + ' local-ok-url-default' %} +dest local-ok-url-default { + urllist local-ok-url-default/urls +} +{% endif %} +{% if sg_config.local_block is vyos_defined %} +{% set acl.value = acl.value + ' !local-block-default' %} +dest local-block-default { + domainlist local-block-default/domains +} +{% endif %} +{% if sg_config.local_block_url is vyos_defined %} +{% set acl.value = acl.value + ' !local-block-url-default' %} +dest local-block-url-default { + urllist local-block-url-default/urls +} +{% endif %} +{% if sg_config.local_block_keyword is vyos_defined %} +{% set acl.value = acl.value + ' !local-block-keyword-default' %} +dest local-block-keyword-default { + expressionlist local-block-keyword-default/expressions +} +{% endif %} + +{% if sg_config.block_category is vyos_defined %} +{% for category in sg_config.block_category %} +{{ sg_rule(category, sg_config.log, squidguard_db_dir) }} +{% set acl.value = acl.value + ' !' + category + '-default' %} +{% endfor %} +{% endif %} +{% if sg_config.allow_category is vyos_defined %} +{% for category in sg_config.allow_category %} +{{ sg_rule(category, False, squidguard_db_dir) }} +{% set acl.value = acl.value + ' ' + category + '-default' %} +{% endfor %} +{% endif %} +{% if sg_config.source_group is vyos_defined %} +{% for sgroup, sg_config in sg_config.source_group.items() %} +{% if sg_config.address is vyos_defined %} +src {{ sgroup }} { +{% for address in sg_config.address %} + ip {{ address }} +{% endfor %} +} + +{% endif %} +{% endfor %} +{% endif %} +{% if sg_config.rule is vyos_defined %} +{% for rule, rule_config in sg_config.rule.items() %} +{% for b_category in rule_config.block_category %} +dest {{ b_category }} { + domainlist {{ b_category }}/domains + urllist {{ b_category }}/urls +} +{% endfor %} + +{% endfor %} +{% endif %} +acl { +{% if sg_config.rule is vyos_defined %} +{% for rule, rule_config in sg_config.rule.items() %} + {{ rule_config.source_group }} { +{% for b_category in rule_config.block_category %} + pass local-ok-1 !in-addr !{{ b_category }} all +{% endfor %} + } +{% endfor %} +{% endif %} + + default { +{% if sg_config.enable_safe_search is vyos_defined %} + rewrite safesearch +{% endif %} + pass {{ acl.value }} {{ 'none' if sg_config.default_action is vyos_defined('block') else 'allow' }} + redirect 302:http://{{ sg_config.redirect_url }} +{% if sg_config.log is vyos_defined %} + log blacklist.log +{% endif %} + } +} +{% endif %} +{% endif %} diff --git a/data/templates/squid/squidGuard.conf.tmpl b/data/templates/squid/squidGuard.conf.tmpl deleted file mode 100644 index c59dc901e..000000000 --- a/data/templates/squid/squidGuard.conf.tmpl +++ /dev/null @@ -1,124 +0,0 @@ -### generated by service_webproxy.py ### - -{% macro sg_rule(category, log, db_dir) %} -{% set expressions = db_dir + '/' + category + '/expressions' %} -dest {{ category }}-default { - domainlist {{ category }}/domains - urllist {{ category }}/urls -{% if expressions | is_file %} - expressionlist {{ category }}/expressions -{% endif %} -{% if log is defined %} - log blacklist.log -{% endif %} -} -{% endmacro %} - -{% if url_filtering is defined and url_filtering.disable is not defined %} -{% if url_filtering.squidguard is defined and url_filtering.squidguard is not none %} -{% set sg_config = url_filtering.squidguard %} -{% set acl = namespace(value='local-ok-default') %} -{% set acl.value = acl.value + ' !in-addr' if sg_config.allow_ipaddr_url is not defined else acl.value %} -dbhome {{ squidguard_db_dir }} -logdir /var/log/squid - -rewrite safesearch { - s@(.*\.google\..*/(custom|search|images|groups|news)?.*q=.*)@\1\&safe=active@i - s@(.*\..*/yandsearch?.*text=.*)@\1\&fyandex=1@i - s@(.*\.yahoo\..*/search.*p=.*)@\1\&vm=r@i - s@(.*\.live\..*/.*q=.*)@\1\&adlt=strict@i - s@(.*\.msn\..*/.*q=.*)@\1\&adlt=strict@i - s@(.*\.bing\..*/search.*q=.*)@\1\&adlt=strict@i - log rewrite.log -} - -{% if sg_config.local_ok is defined and sg_config.local_ok is not none %} -{% set acl.value = acl.value + ' local-ok-default' %} -dest local-ok-default { - domainlist local-ok-default/domains -} -{% endif %} -{% if sg_config.local_ok_url is defined and sg_config.local_ok_url is not none %} -{% set acl.value = acl.value + ' local-ok-url-default' %} -dest local-ok-url-default { - urllist local-ok-url-default/urls -} -{% endif %} -{% if sg_config.local_block is defined and sg_config.local_block is not none %} -{% set acl.value = acl.value + ' !local-block-default' %} -dest local-block-default { - domainlist local-block-default/domains -} -{% endif %} -{% if sg_config.local_block_url is defined and sg_config.local_block_url is not none %} -{% set acl.value = acl.value + ' !local-block-url-default' %} -dest local-block-url-default { - urllist local-block-url-default/urls -} -{% endif %} -{% if sg_config.local_block_keyword is defined and sg_config.local_block_keyword is not none %} -{% set acl.value = acl.value + ' !local-block-keyword-default' %} -dest local-block-keyword-default { - expressionlist local-block-keyword-default/expressions -} -{% endif %} - -{% if sg_config.block_category is defined and sg_config.block_category is not none %} -{% for category in sg_config.block_category %} -{{ sg_rule(category, sg_config.log, squidguard_db_dir) }} -{% set acl.value = acl.value + ' !' + category + '-default' %} -{% endfor %} -{% endif %} -{% if sg_config.allow_category is defined and sg_config.allow_category is not none %} -{% for category in sg_config.allow_category %} -{{ sg_rule(category, False, squidguard_db_dir) }} -{% set acl.value = acl.value + ' ' + category + '-default' %} -{% endfor %} -{% endif %} -{% if sg_config.source_group is defined and sg_config.source_group is not none %} -{% for sgroup, sg_config in sg_config.source_group.items() %} -{% if sg_config.address is defined and sg_config.address is not none %} -src {{ sgroup }} { -{% for address in sg_config.address %} - ip {{ address }} -{% endfor %} -} - -{% endif %} -{% endfor %} -{% endif %} -{% if sg_config.rule is defined and sg_config.rule is not none %} -{% for rule, rule_config in sg_config.rule.items() %} -{% for b_category in rule_config.block_category%} -dest {{ b_category }} { - domainlist {{ b_category }}/domains - urllist {{ b_category }}/urls -} -{% endfor %} - -{% endfor %} -{% endif %} -acl { -{% if sg_config.rule is defined and sg_config.rule is not none %} -{% for rule, rule_config in sg_config.rule.items() %} - {{ rule_config.source_group }} { -{% for b_category in rule_config.block_category%} - pass local-ok-1 !in-addr !{{ b_category }} all -{% endfor %} - } -{% endfor %} -{% endif %} - - default { -{% if sg_config.enable_safe_search is defined %} - rewrite safesearch -{% endif %} - pass {{ acl.value }} {{ 'none' if sg_config.default_action is defined and sg_config.default_action == 'block' else 'allow' }} - redirect 302:http://{{ sg_config.redirect_url }} -{% if sg_config.log is defined and sg_config.log is not none %} - log blacklist.log -{% endif %} - } -} -{% endif %} -{% endif %} diff --git a/data/templates/ssh/override.conf.j2 b/data/templates/ssh/override.conf.j2 new file mode 100644 index 000000000..e4d6f51cb --- /dev/null +++ b/data/templates/ssh/override.conf.j2 @@ -0,0 +1,13 @@ +{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %} +[Unit] +StartLimitIntervalSec=0 +After=vyos-router.service +ConditionPathExists={{ config_file }} + +[Service] +ExecStart= +ExecStart={{ vrf_command }}/usr/sbin/sshd -f {{ config_file }} -D $SSHD_OPTS +Restart=always +RestartPreventExitStatus= +RestartSec=10 +RuntimeDirectoryPreserve=yes diff --git a/data/templates/ssh/override.conf.tmpl b/data/templates/ssh/override.conf.tmpl deleted file mode 100644 index 5f8f35e89..000000000 --- a/data/templates/ssh/override.conf.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -{% set vrf_command = 'ip vrf exec ' + vrf + ' ' if vrf is defined else '' %} -[Unit] -StartLimitIntervalSec=0 -After=vyos-router.service -ConditionPathExists={{config_file}} - -[Service] -ExecStart= -ExecStart={{vrf_command}}/usr/sbin/sshd -f {{config_file}} -D $SSHD_OPTS -Restart=always -RestartPreventExitStatus= -RestartSec=10 -RuntimeDirectoryPreserve=yes diff --git a/data/templates/ssh/sshd_config.tmpl b/data/templates/ssh/sshd_config.j2 index 2f2b78a66..e7dbca581 100644 --- a/data/templates/ssh/sshd_config.tmpl +++ b/data/templates/ssh/sshd_config.j2 @@ -29,6 +29,7 @@ UsePAM yes PermitRootLogin no PidFile /run/sshd/sshd.pid AddressFamily any +DebianBanner no # # User configurable section @@ -36,7 +37,7 @@ AddressFamily any # Look up remote host name and check that the resolved host name for the remote IP # address maps back to the very same IP address. -UseDNS {{ "no" if disable_host_validation is defined else "yes" }} +UseDNS {{ "no" if disable_host_validation is vyos_defined else "yes" }} # Specifies the port number that sshd(8) listens on {% for value in port %} @@ -47,61 +48,50 @@ Port {{ value }} LogLevel {{ loglevel | upper }} # Specifies whether password authentication is allowed -PasswordAuthentication {{ "no" if disable_password_authentication is defined else "yes" }} +PasswordAuthentication {{ "no" if disable_password_authentication is vyos_defined else "yes" }} -{% if listen_address is defined and listen_address is not none %} +{% if listen_address is vyos_defined %} # Specifies the local addresses sshd should listen on -{% for address in listen_address %} +{% for address in listen_address %} ListenAddress {{ address }} -{% endfor %} +{% endfor %} {% endif %} -{% if ciphers is defined and ciphers is not none %} +{% if ciphers is vyos_defined %} # Specifies the ciphers allowed for protocol version 2 -{% set value = ciphers if ciphers is string else ciphers | join(',') %} -Ciphers {{ value }} +Ciphers {{ ciphers | join(',') }} {% endif %} -{% if mac is defined and mac is not none %} +{% if mac is vyos_defined %} # Specifies the available MAC (message authentication code) algorithms -{% set value = mac if mac is string else mac | join(',') %} -MACs {{ value }} +MACs {{ mac | join(',') }} {% endif %} -{% if key_exchange is defined and key_exchange is not none %} +{% if key_exchange is vyos_defined %} # Specifies the available Key Exchange algorithms -{% set value = key_exchange if key_exchange is string else key_exchange | join(',') %} -KexAlgorithms {{ value }} +KexAlgorithms {{ key_exchange | join(',') }} {% endif %} -{% if access_control is defined and access_control is not none %} -{% if access_control.allow is defined and access_control.allow is not none %} -{% if access_control.allow.user is defined %} +{% if access_control is vyos_defined %} +{% if access_control.allow.user is vyos_defined %} # If specified, login is allowed only for user names that match -{% set value = access_control.allow.user if access_control.allow.user is string else access_control.allow.user | join(' ') %} -AllowUsers {{ value }} +AllowUsers {{ access_control.allow.user | join(' ') }} {% endif %} -{% if access_control.allow.group is defined %} +{% if access_control.allow.group is vyos_defined %} # If specified, login is allowed only for users whose primary group or supplementary group list matches -{% set value = access_control.allow.group if access_control.allow.group is string else access_control.allow.group | join(' ') %} -AllowGroups {{ value }} +AllowGroups {{ access_control.allow.group | join(' ') }} {% endif %} -{% endif %} -{% if access_control.deny is defined and access_control.deny is not none %} -{% if access_control.deny.user is defined %} +{% if access_control.deny.user is vyos_defined %} # Login is disallowed for user names that match -{% set value = access_control.deny.user if access_control.deny.user is string else access_control.deny.user | join(' ') %} -DenyUsers {{ value }} +DenyUsers {{ access_control.deny.user | join(' ') }} {% endif %} -{% if access_control.deny.group is defined %} +{% if access_control.deny.group is vyos_defined %} # Login is disallowed for users whose primary group or supplementary group list matches -{% set value = access_control.deny.group if access_control.deny.group is string else access_control.deny.group | join(' ') %} -DenyGroups {{ value }} +DenyGroups {{ access_control.deny.group | join(' ') }} {% endif %} -{% endif %} {% endif %} -{% if client_keepalive_interval is defined and client_keepalive_interval is not none %} +{% if client_keepalive_interval is vyos_defined %} # Sets a timeout interval in seconds after which if no data has been received from the client, # sshd(8) will send a message through the encrypted channel to request a response from the client ClientAliveInterval {{ client_keepalive_interval }} diff --git a/data/templates/ssh/sshguard_config.j2 b/data/templates/ssh/sshguard_config.j2 new file mode 100644 index 000000000..58c6ad48d --- /dev/null +++ b/data/templates/ssh/sshguard_config.j2 @@ -0,0 +1,27 @@ +### Autogenerated by ssh.py ### + +{% if dynamic_protection is vyos_defined %} +# Full path to backend executable (required, no default) +BACKEND="/usr/libexec/sshguard/sshg-fw-nft-sets" + +# Shell command that provides logs on standard output. (optional, no default) +# Example 1: ssh and sendmail from systemd journal: +LOGREADER="LANG=C journalctl -afb -p info -n1 -t sshd -o cat" + +#### OPTIONS #### +# Block attackers when their cumulative attack score exceeds THRESHOLD. +# Most attacks have a score of 10. (optional, default 30) +THRESHOLD={{ dynamic_protection.threshold }} + +# Block attackers for initially BLOCK_TIME seconds after exceeding THRESHOLD. +# Subsequent blocks increase by a factor of 1.5. (optional, default 120) +BLOCK_TIME={{ dynamic_protection.block_time }} + +# Remember potential attackers for up to DETECTION_TIME seconds before +# resetting their score. (optional, default 1800) +DETECTION_TIME={{ dynamic_protection.detect_time }} + +# IP addresses listed in the WHITELIST_FILE are considered to be +# friendlies and will never be blocked. +WHITELIST_FILE=/etc/sshguard/whitelist +{% endif %} diff --git a/data/templates/ssh/sshguard_whitelist.j2 b/data/templates/ssh/sshguard_whitelist.j2 new file mode 100644 index 000000000..47a950a2b --- /dev/null +++ b/data/templates/ssh/sshguard_whitelist.j2 @@ -0,0 +1,7 @@ +### Autogenerated by ssh.py ### + +{% if dynamic_protection.allow_from is vyos_defined %} +{% for address in dynamic_protection.allow_from %} +{{ address }} +{% endfor %} +{% endif %} diff --git a/data/templates/syslog/logrotate.j2 b/data/templates/syslog/logrotate.j2 new file mode 100644 index 000000000..c1b951e8b --- /dev/null +++ b/data/templates/syslog/logrotate.j2 @@ -0,0 +1,11 @@ +{{ config_render['log-file'] }} { + missingok + notifempty + create + rotate {{ config_render['max-files'] }} + size={{ config_render['max-size'] // 1024 }}k + postrotate + invoke-rc.d rsyslog rotate > /dev/null + endscript +} + diff --git a/data/templates/syslog/logrotate.tmpl b/data/templates/syslog/logrotate.tmpl deleted file mode 100644 index f758265e4..000000000 --- a/data/templates/syslog/logrotate.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -{% for file in files %} -{{files[file]['log-file']}} { - missingok - notifempty - create - rotate {{files[file]['max-files']}} - size={{files[file]['max-size']//1024}}k - postrotate - invoke-rc.d rsyslog rotate > /dev/null - endscript -} -{% endfor %} diff --git a/data/templates/syslog/rsyslog.conf.j2 b/data/templates/syslog/rsyslog.conf.j2 new file mode 100644 index 000000000..4445d568b --- /dev/null +++ b/data/templates/syslog/rsyslog.conf.j2 @@ -0,0 +1,54 @@ +## generated by syslog.py ## +## file based logging +{% if files['global']['marker'] %} +$ModLoad immark +{% if files['global']['marker-interval'] %} +$MarkMessagePeriod {{ files['global']['marker-interval'] }} +{% endif %} +{% endif %} +{% if files['global']['preserver_fqdn'] %} +$PreserveFQDN on +{% endif %} +{% for file, file_options in files.items() %} +$outchannel {{ file }},{{ file_options['log-file'] }},{{ file_options['max-size'] }},{{ file_options['action-on-max-size'] }} +{{ file_options['selectors'] }} :omfile:${{ file }} +{% endfor %} +{% if console is defined and console is not none %} +## console logging +{% for con, con_options in console.items() %} +{{ con_options['selectors'] }} /dev/console +{% endfor %} +{% endif %} +{% if hosts is defined and hosts is not none %} +## remote logging +{% for host, host_options in hosts.items() %} +{% if host_options.proto == 'tcp' %} +{% if host_options.port is defined %} +{% if host_options.oct_count is defined %} +{{ host_options.selectors }} @@(o){{ host | bracketize_ipv6 }}:{{ host_options.port }};RSYSLOG_SyslogProtocol23Format +{% else %} +{{ host_options.selectors }} @@{{ host | bracketize_ipv6 }}:{{ host_options.port }} +{% endif %} +{% else %} +{{ host_options.selectors }} @@{{ host | bracketize_ipv6 }} +{% endif %} +{% elif host_options.proto == 'udp' %} +{% if host_options.port is defined %} +{{ host_options.selectors }} @{{ host | bracketize_ipv6 }}:{{ host_options.port }}{{ ';RSYSLOG_SyslogProtocol23Format' if host_options.oct_count is sameas true }} +{% else %} +{{ host_options.selectors }} @{{ host | bracketize_ipv6 }} +{% endif %} +{% else %} +{% if host_options['port'] %} +{{ host_options.selectors }} @{{ host | bracketize_ipv6 }}:{{ host_options.port }} +{% else %} +{{ host_options.selectors }} @{{ host | bracketize_ipv6 }} +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{% if user is defined and user is not none %} +{% for username, user_options in user.items() %} +{{ user_options.selectors }} :omusrmsg:{{ username }} +{% endfor %} +{% endif %} diff --git a/data/templates/syslog/rsyslog.conf.tmpl b/data/templates/syslog/rsyslog.conf.tmpl deleted file mode 100644 index e25ef48d4..000000000 --- a/data/templates/syslog/rsyslog.conf.tmpl +++ /dev/null @@ -1,48 +0,0 @@ -## generated by syslog.py ## -## file based logging -{% if files['global']['marker'] %} -$ModLoad immark -{% if files['global']['marker-interval'] %} -$MarkMessagePeriod {{files['global']['marker-interval']}} -{% endif %} -{% endif %} -{% if files['global']['preserver_fqdn'] %} -$PreserveFQDN on -{% endif %} -{% for file, file_options in files.items() %} -$outchannel {{ file }},{{ file_options['log-file'] }},{{ file_options['max-size'] }},{{ file_options['action-on-max-size'] }} -{{ file_options['selectors'] }} :omfile:${{ file }} -{% endfor %} -{% if console is defined and console is not none %} -## console logging -{% for con, con_options in console.items() %} -{{ con_options['selectors'] }} /dev/console -{% endfor %} -{% endif %} -{% if hosts is defined and hosts is not none %} -## remote logging -{% for host, host_options in hosts.items() %} -{% if host_options.proto == 'tcp' %} -{% if host_options.port is defined %} -{% if host_options.oct_count is defined %} -{{ host_options.selectors }} @@(o){{ host }}:{{ host_options.port }};RSYSLOG_SyslogProtocol23Format -{% else %} -{{ host_options.selectors }} @@{{ host }}:{{ host_options.port }} -{% endif %} -{% else %} -{{ host_options.selectors }} @@{{ host }} -{% endif %} -{% else %} -{% if host_options['port'] %} -{{ host_options.selectors }} @{{ host | bracketize_ipv6 }}:{{ host_options.port }} -{% else %} -{{ host_options.selectors }} @{{ host | bracketize_ipv6 }} -{% endif %} -{% endif %} -{% endfor %} -{% endif %} -{% if user is defined and user is not none %} -{% for username, user_options in user.items() %} -{{ user_options.selectors }} :omusrmsg:{{ username }} -{% endfor %} -{% endif %} diff --git a/data/templates/system/curlrc.j2 b/data/templates/system/curlrc.j2 new file mode 100644 index 000000000..be4efe8ba --- /dev/null +++ b/data/templates/system/curlrc.j2 @@ -0,0 +1,6 @@ +{% if http_client.source_interface is vyos_defined %} +--interface "{{ http_client.source_interface }}" +{% endif %} +{% if http_client.source_address is vyos_defined %} +--interface "{{ http_client.source_address }}" +{% endif %} diff --git a/data/templates/system/curlrc.tmpl b/data/templates/system/curlrc.tmpl deleted file mode 100644 index 3e5ce801c..000000000 --- a/data/templates/system/curlrc.tmpl +++ /dev/null @@ -1,8 +0,0 @@ -{% if http_client is defined %} -{% if http_client.source_interface is defined %} ---interface "{{ http_client.source_interface }}" -{% endif %} -{% if http_client.source_address is defined %} ---interface "{{ http_client.source_address }}" -{% endif %} -{% endif %} diff --git a/data/templates/system/proxy.j2 b/data/templates/system/proxy.j2 new file mode 100644 index 000000000..215c4c5c2 --- /dev/null +++ b/data/templates/system/proxy.j2 @@ -0,0 +1,7 @@ +# generated by system-proxy.py +{% if url is vyos_defined and port is vyos_defined %} +{# remove http:// prefix so we can inject a username/password if present #} +export http_proxy=http://{{ username ~ ':' ~ password ~ '@' if username is vyos_defined and password is vyos_defined }}{{ url | replace('http://', '') }}:{{ port }} +export https_proxy=$http_proxy +export ftp_proxy=$http_proxy +{% endif %} diff --git a/data/templates/system/ssh_config.j2 b/data/templates/system/ssh_config.j2 new file mode 100644 index 000000000..1449f95b1 --- /dev/null +++ b/data/templates/system/ssh_config.j2 @@ -0,0 +1,3 @@ +{% if ssh_client.source_address is vyos_defined %} +BindAddress {{ ssh_client.source_address }} +{% endif %} diff --git a/data/templates/system/ssh_config.tmpl b/data/templates/system/ssh_config.tmpl deleted file mode 100644 index abc03f069..000000000 --- a/data/templates/system/ssh_config.tmpl +++ /dev/null @@ -1,3 +0,0 @@ -{% if ssh_client is defined and ssh_client.source_address is defined and ssh_client.source_address is not none %} -BindAddress {{ ssh_client.source_address }} -{% endif %} diff --git a/data/templates/system/sysctl.conf.j2 b/data/templates/system/sysctl.conf.j2 new file mode 100644 index 000000000..59a19e157 --- /dev/null +++ b/data/templates/system/sysctl.conf.j2 @@ -0,0 +1,7 @@ +# autogenerated by system_sysctl.py
+
+{% if parameter is vyos_defined %}
+{% for k, v in parameter.items() %}
+{{ k }} = {{ v.value }}
+{% endfor %}
+{% endif %}
diff --git a/data/templates/system/sysctl.conf.tmpl b/data/templates/system/sysctl.conf.tmpl deleted file mode 100644 index 72af82ee5..000000000 --- a/data/templates/system/sysctl.conf.tmpl +++ /dev/null @@ -1,7 +0,0 @@ -# autogenerated by system_sysctl.py
-
-{% if parameter is defined and parameter is not none %}
-{% for k, v in parameter.items() %}
-{{ k }} = {{ v.value }}
-{% endfor %}
-{% endif %}
diff --git a/data/templates/tftp-server/default.j2 b/data/templates/tftp-server/default.j2 new file mode 100644 index 000000000..b2676e0aa --- /dev/null +++ b/data/templates/tftp-server/default.j2 @@ -0,0 +1,8 @@ +{# j2lint: disable=jinja-variable-format #} +### Autogenerated by tftp_server.py ### +DAEMON_ARGS="--listen --user tftp --address {{ listen_address }} {{ "--create --umask 000" if allow_upload is vyos_defined }} --secure {{ directory }}" +{% if vrf is vyos_defined %} +VRF_ARGS="ip vrf exec {{ vrf }}" +{% else %} +VRF_ARGS="" +{% endif %} diff --git a/data/templates/tftp-server/default.tmpl b/data/templates/tftp-server/default.tmpl deleted file mode 100644 index 6b2d6a903..000000000 --- a/data/templates/tftp-server/default.tmpl +++ /dev/null @@ -1,2 +0,0 @@ -### Autogenerated by tftp_server.py ### -DAEMON_ARGS="--listen --user tftp --address {{ listen_address }} {{ "--create --umask 000" if allow_upload is defined }} --secure {{ directory }}" diff --git a/data/templates/vrf/vrf.conf.j2 b/data/templates/vrf/vrf.conf.j2 new file mode 100644 index 000000000..d31d23574 --- /dev/null +++ b/data/templates/vrf/vrf.conf.j2 @@ -0,0 +1,9 @@ +### Autogenerated by vrf.py ### +# +# Routing table ID to name mapping reference +# id vrf name comment +{% if name is vyos_defined %} +{% for vrf, vrf_config in name.items() %} +{{ "%-10s" | format(vrf_config.table) }} {{ "%-16s" | format(vrf) }} {{ '# ' ~ vrf_config.description if vrf_config.description is vyos_defined }} +{% endfor %} +{% endif %} diff --git a/data/templates/vrf/vrf.conf.tmpl b/data/templates/vrf/vrf.conf.tmpl deleted file mode 100644 index 29c0ba08d..000000000 --- a/data/templates/vrf/vrf.conf.tmpl +++ /dev/null @@ -1,9 +0,0 @@ -### Autogenerated by vrf.py ### -# -# Routing table ID to name mapping reference -# id vrf name comment -{% if name is defined and name is not none %} -{% for vrf, vrf_config in name.items() %} -{{ "%-10s" | format(vrf_config.table) }} {{ "%-16s" | format(vrf) }} {{ '# ' + vrf_config.description if vrf_config.description is defined and vrf_config.description is not none }} -{% endfor %} -{% endif %} diff --git a/data/templates/vrrp/keepalived.conf.tmpl b/data/templates/vrrp/keepalived.conf.tmpl deleted file mode 100644 index b4824a994..000000000 --- a/data/templates/vrrp/keepalived.conf.tmpl +++ /dev/null @@ -1,106 +0,0 @@ -# Autogenerated by VyOS -# Do not edit this file, all your changes will be lost -# on next commit or reboot - -global_defs { - dynamic_interfaces - script_user root - # Don't run scripts configured to be run as root if any part of the path - # is writable by a non-root user. - enable_script_security - notify_fifo /run/keepalived/keepalived_notify_fifo - notify_fifo_script /usr/libexec/vyos/system/keepalived-fifo.py -} - -{% if group is defined and group is not none %} -{% for name, group_config in group.items() if group_config.disable is not defined %} -{% if group_config.health_check is defined and group_config.health_check.script is defined and group_config.health_check.script is not none %} -vrrp_script healthcheck_{{ name }} { - script "{{ group_config.health_check.script }}" - interval {{ group_config.health_check.interval }} - fall {{ group_config.health_check.failure_count }} - rise 1 -} -{% endif %} -vrrp_instance {{ name }} { -{% if group_config.description is defined and group_config.description is not none %} - # {{ group_config.description }} -{% endif %} - state BACKUP - interface {{ group_config.interface }} - virtual_router_id {{ group_config.vrid }} - priority {{ group_config.priority }} - advert_int {{ group_config.advertise_interval }} -{% if group_config.no_preempt is not defined and group_config.preempt_delay is defined and group_config.preempt_delay is not none %} - preempt_delay {{ group_config.preempt_delay }} -{% elif group_config.no_preempt is defined %} - nopreempt -{% endif %} -{% if group_config.peer_address is defined and group_config.peer_address is not none %} - unicast_peer { {{ group_config.peer_address }} } -{% endif %} -{% if group_config.hello_source_address is defined and group_config.hello_source_address is not none %} -{% if group_config.peer_address is defined and group_config.peer_address is not none %} - unicast_src_ip {{ group_config.hello_source_address }} -{% else %} - mcast_src_ip {{ group_config.hello_source_address }} -{% endif %} -{% endif %} -{% if group_config.rfc3768_compatibility is defined and group_config.peer_address is defined %} - use_vmac {{ group_config.interface }}v{{ group_config.vrid }} - vmac_xmit_base -{% elif group_config.rfc3768_compatibility is defined %} - use_vmac {{ group_config.interface }}v{{ group_config.vrid }} -{% endif %} -{% if group_config.authentication is defined and group_config.authentication is not none %} - authentication { - auth_pass "{{ group_config.authentication.password }}" -{% if group_config.authentication.type == 'plaintext-password' %} - auth_type PASS -{% else %} - auth_type {{ group_config.authentication.type | upper }} -{% endif %} - } -{% endif %} -{% if group_config.address is defined and group_config.address is not none %} - virtual_ipaddress { -{% for addr in group_config.address %} - {{ addr }} -{% endfor %} - } -{% endif %} -{% if group_config.excluded_address is defined and group_config.excluded_address is not none %} - virtual_ipaddress_excluded { -{% for addr in group_config.excluded_address %} - {{ addr }} -{% endfor %} - } -{% endif %} -{% if group_config.health_check is defined and group_config.health_check.script is defined and group_config.health_check.script is not none %} - track_script { - healthcheck_{{ name }} - } -{% endif %} -} -{% endfor %} -{% endif %} - -{% if sync_group is defined and sync_group is not none %} -{% for name, group_config in sync_group.items() if group_config.disable is not defined %} -vrrp_sync_group {{ name }} { - group { -{% if group_config.member is defined and group_config.member is not none %} -{% for member in group_config.member %} - {{ member }} -{% endfor %} -{% endif %} - } -{% if conntrack_sync_group is defined and conntrack_sync_group == name %} -{% set vyos_helper = "/usr/libexec/vyos/vyos-vrrp-conntracksync.sh" %} - notify_master "{{ vyos_helper }} master {{ name }}" - notify_backup "{{ vyos_helper }} backup {{ name }}" - notify_fault "{{ vyos_helper }} fault {{ name }}" -{% endif %} -} -{% endfor %} -{% endif %} diff --git a/data/templates/vyos-hostsd/hosts.tmpl b/data/templates/vyos-hostsd/hosts.j2 index 03662d562..5cad983b4 100644 --- a/data/templates/vyos-hostsd/hosts.tmpl +++ b/data/templates/vyos-hostsd/hosts.j2 @@ -1,3 +1,4 @@ +{# j2lint: disable=single-statement-per-line #} ### Autogenerated by VyOS ### ### Do not edit, your changes will get overwritten ### @@ -12,14 +13,14 @@ ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters -{% if hosts is defined and hosts is not none %} +{% if hosts is vyos_defined %} # From 'system static-host-mapping' and DHCP server -{% for tag, taghosts in hosts.items() %} +{% for tag, taghosts in hosts.items() %} # {{ tag }} -{% for host, hostprops in taghosts.items() if hostprops.address is defined %} -{% for addr in hostprops.address %} -{{ "%-15s" | format(addr) }} {{ host }} {{ hostprops.aliases|join(' ') if hostprops.aliases is defined }} -{% endfor %} +{% for host, hostprops in taghosts.items() if hostprops.address is vyos_defined %} +{% for addr in hostprops.address %} +{{ "%-15s" | format(addr) }} {{ host }} {{ hostprops.aliases | join(' ') if hostprops.aliases is vyos_defined }} +{% endfor %} +{% endfor %} {% endfor %} -{% endfor %} {% endif %} diff --git a/data/templates/vyos-hostsd/resolv.conf.tmpl b/data/templates/vyos-hostsd/resolv.conf.j2 index 58a5f9312..5f651f1a1 100644 --- a/data/templates/vyos-hostsd/resolv.conf.tmpl +++ b/data/templates/vyos-hostsd/resolv.conf.j2 @@ -5,12 +5,12 @@ {# the order of tags, then by the order of nameservers within that tag #} {% for tag in name_server_tags_system %} -{% if tag in name_servers %} +{% if tag in name_servers %} # {{ tag }} -{% for ns in name_servers[tag] %} +{% for ns in name_servers[tag] %} nameserver {{ ns }} -{% endfor %} -{% endif %} +{% endfor %} +{% endif %} {% endfor %} {% if domain_name %} @@ -18,8 +18,8 @@ domain {{ domain_name }} {% endif %} {% for tag in name_server_tags_system %} -{% if tag in search_domains %} +{% if tag in search_domains %} # {{ tag }} -search {{ search_domains[tag]|join(' ') }} -{% endif %} +search {{ search_domains[tag] | join(' ') }} +{% endif %} {% endfor %} diff --git a/data/templates/wifi/cfg80211.conf.tmpl b/data/templates/wifi/cfg80211.conf.tmpl deleted file mode 100644 index 91df57aab..000000000 --- a/data/templates/wifi/cfg80211.conf.tmpl +++ /dev/null @@ -1 +0,0 @@ -{{ 'options cfg80211 ieee80211_regdom=' + regdom if regdom is defined }} diff --git a/data/templates/wifi/crda.tmpl b/data/templates/wifi/crda.tmpl deleted file mode 100644 index 6cd125e37..000000000 --- a/data/templates/wifi/crda.tmpl +++ /dev/null @@ -1 +0,0 @@ -{{ 'REGDOMAIN=' + regdom if regdom is defined }} diff --git a/data/templates/wifi/hostapd.conf.tmpl b/data/templates/wifi/hostapd.conf.j2 index 433e1d36f..f2312d2d4 100644 --- a/data/templates/wifi/hostapd.conf.tmpl +++ b/data/templates/wifi/hostapd.conf.j2 @@ -1,5 +1,6 @@ +{# j2lint: disable=operator-enclosed-by-spaces #} ### Autogenerated by interfaces-wireless.py ### -{% if description %} +{% if description is vyos_defined %} # Description: {{ description }} # User-friendly description of device; up to 32 octets encoded in UTF-8 device_name={{ description | truncate(32, True) }} @@ -11,7 +12,7 @@ device_name={{ description | truncate(32, True) }} # command line parameter. interface={{ ifname }} -{% if is_bridge_member is defined %} +{% if is_bridge_member is vyos_defined %} # In case of atheros and nl80211 driver interfaces, an additional # configuration parameter, bridge, may be used to notify hostapd if the # interface is included in a bridge. This parameter is not used with Host AP @@ -24,9 +25,9 @@ interface={{ ifname }} # has been started to change the interface mode). If needed, the bridge # interface is also created. {# as there can only be one bridge interface it is save to loop #} -{% for bridge in is_bridge_member %} +{% for bridge in is_bridge_member %} bridge={{ bridge }} -{% endfor %} +{% endfor %} {% endif %} # Driver interface type (hostap/wired/none/nl80211/bsd); @@ -72,7 +73,7 @@ ssid={{ ssid }} channel={{ channel }} {% endif %} -{% if mode is defined and mode is not none %} +{% if mode is vyos_defined %} # Operation mode (a = IEEE 802.11a (5 GHz), b = IEEE 802.11b (2.4 GHz), # g = IEEE 802.11g (2.4 GHz), ad = IEEE 802.11ad (60 GHz); a/g options are used # with IEEE 802.11n (HT), too, to specify band). For IEEE 802.11ac (VHT), this @@ -81,15 +82,15 @@ channel={{ channel }} # special value "any" can be used to indicate that any support band can be used. # This special case is currently supported only with drivers with which # offloaded ACS is used. -{% if mode == 'n' %} +{% if mode is vyos_defined('n') %} hw_mode=g -{% elif mode == 'ac' %} +{% elif mode is vyos_defined('ac') %} hw_mode=a ieee80211h=1 ieee80211ac=1 -{% else %} +{% else %} hw_mode={{ mode }} -{% endif %} +{% endif %} {% endif %} # ieee80211w: Whether management frame protection (MFP) is enabled @@ -104,7 +105,7 @@ ieee80211w=1 ieee80211w=2 {% endif %} -{% if capabilities is defined and capabilities.ht is defined %} +{% if capabilities is vyos_defined %} # ht_capab: HT capabilities (list of flags) # LDPC coding capability: [LDPC] = supported # Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary @@ -138,70 +139,70 @@ ieee80211w=2 # DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set) # 40 MHz intolerant [40-INTOLERANT] (not advertised if not set) # L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set) -{% set output = namespace(value='') %} - -{% if capabilities.ht.fourtymhz_incapable is defined %} -{% set output.value = output.value + '[40-INTOLERANT]' %} -{% endif %} -{% if capabilities.ht.delayed_block_ack is defined %} -{% set output.value = output.value + '[DELAYED-BA]' %} -{% endif %} -{% if capabilities.ht.dsss_cck_40 is defined %} -{% set output.value = output.value + '[DSSS_CCK-40]' %} -{% endif %} -{% if capabilities.ht.greenfield is defined %} -{% set output.value = output.value + '[GF]' %} -{% endif %} -{% if capabilities.ht.ldpc is defined %} -{% set output.value = output.value + '[LDPC]' %} -{% endif %} -{% if capabilities.ht.lsig_protection is defined %} -{% set output.value = output.value + '[LSIG-TXOP-PROT]' %} -{% endif %} -{% if capabilities.ht.stbc is defined and capabilities.ht.stbc.tx is defined %} -{% set output.value = output.value + '[TX-STBC]' %} -{% endif %} -{% if capabilities.ht.stbc is defined and capabilities.ht.stbc.rx is defined %} -{% set output.value = output.value + '[RX-STBC-' + capabilities.ht.stbc.rx | upper + ']' %} -{% endif %} -{% if capabilities.ht.max_amsdu is defined %} -{% set output.value = output.value + '[MAX-AMSDU-' + capabilities.ht.max_amsdu + ']' %} -{% endif %} -{% if capabilities.ht.smps is defined %} -{% set output.value = output.value + '[SMPS-' + capabilities.ht.smps | upper + ']' %} -{% endif %} - -{% if capabilities.ht.channel_set_width is defined %} -{% for csw in capabilities.ht.channel_set_width %} -{% set output.value = output.value + '[' + csw | upper + ']' %} -{% endfor %} -{% endif %} +{% set output = namespace(value='') %} -{% if capabilities.ht.short_gi is defined %} -{% for short_gi in capabilities.ht.short_gi %} -{% set output.value = output.value + '[SHORT-GI-' + short_gi | upper + ']' %} -{% endfor %} -{% endif %} +{% if capabilities.ht.fourtymhz_incapable is vyos_defined %} +{% set output.value = output.value ~ '[40-INTOLERANT]' %} +{% endif %} +{% if capabilities.ht.delayed_block_ack is vyos_defined %} +{% set output.value = output.value ~ '[DELAYED-BA]' %} +{% endif %} +{% if capabilities.ht.dsss_cck_40 is vyos_defined %} +{% set output.value = output.value ~ '[DSSS_CCK-40]' %} +{% endif %} +{% if capabilities.ht.greenfield is vyos_defined %} +{% set output.value = output.value ~ '[GF]' %} +{% endif %} +{% if capabilities.ht.ldpc is vyos_defined %} +{% set output.value = output.value ~ '[LDPC]' %} +{% endif %} +{% if capabilities.ht.lsig_protection is vyos_defined %} +{% set output.value = output.value ~ '[LSIG-TXOP-PROT]' %} +{% endif %} +{% if capabilities.ht.stbc.tx is vyos_defined %} +{% set output.value = output.value ~ '[TX-STBC]' %} +{% endif %} +{% if capabilities.ht.stbc.rx is vyos_defined %} +{% set output.value = output.value ~ '[RX-STBC-' ~ capabilities.ht.stbc.rx | upper ~ ']' %} +{% endif %} +{% if capabilities.ht.max_amsdu is vyos_defined %} +{% set output.value = output.value ~ '[MAX-AMSDU-' ~ capabilities.ht.max_amsdu ~ ']' %} +{% endif %} +{% if capabilities.ht.smps is vyos_defined %} +{% set output.value = output.value ~ '[SMPS-' ~ capabilities.ht.smps | upper ~ ']' %} +{% endif %} + +{% if capabilities.ht.channel_set_width is vyos_defined %} +{% for csw in capabilities.ht.channel_set_width %} +{% set output.value = output.value ~ '[' ~ csw | upper ~ ']' %} +{% endfor %} +{% endif %} + +{% if capabilities.ht.short_gi is vyos_defined %} +{% for short_gi in capabilities.ht.short_gi %} +{% set output.value = output.value ~ '[SHORT-GI-' ~ short_gi | upper ~ ']' %} +{% endfor %} +{% endif %} ht_capab={{ output.value }} -{% if capabilities.ht.auto_powersave is defined %} +{% if capabilities.ht.auto_powersave is vyos_defined %} # WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD] # Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver) uapsd_advertisement_enabled=1 -{% endif %} +{% endif %} {% endif %} # Required for full HT and VHT functionality wme_enabled=1 -{% if capabilities is defined and capabilities.require_ht is defined %} +{% if capabilities.require_ht is vyos_defined %} # Require stations to support HT PHY (reject association if they do not) require_ht=1 {% endif %} -{% if capabilities is defined and capabilities.vht is defined %} +{% if capabilities.vht is vyos_defined %} # vht_capab: VHT capabilities (list of flags) # # vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454] @@ -297,7 +298,7 @@ require_ht=1 # Indicates the maximum length of A-MPDU pre-EOF padding that the STA can recv # This field is an integer in the range of 0 to 7. # The length defined by this field is equal to -# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets +# 2 pow(13 ~ Maximum A-MPDU Length Exponent) -1 octets # # VHT Link Adaptation Capable: [VHT-LINK-ADAPT2] [VHT-LINK-ADAPT3] # Indicates whether or not the STA supports link adaptation using VHT variant @@ -320,87 +321,86 @@ require_ht=1 # 0 = Tx antenna pattern might change during the lifetime of an association # 1 = Tx antenna pattern does not change during the lifetime of an -{% if capabilities.vht.center_channel_freq is defined and capabilities.vht.center_channel_freq.freq_1 is defined %} -# center freq = 5 GHz + (5 * index) +{% if capabilities.vht.center_channel_freq.freq_1 is vyos_defined %} +# center freq = 5 GHz ~ (5 * index) # So index 42 gives center freq 5.210 GHz # which is channel 42 in 5G band vht_oper_centr_freq_seg0_idx={{ capabilities.vht.center_channel_freq.freq_1 }} -{% endif %} +{% endif %} -{% if capabilities.vht.center_channel_freq is defined and capabilities.vht.center_channel_freq.freq_2 is defined %} -# center freq = 5 GHz + (5 * index) +{% if capabilities.vht.center_channel_freq.freq_2 is vyos_defined %} +# center freq = 5 GHz ~ (5 * index) # So index 159 gives center freq 5.795 GHz # which is channel 159 in 5G band vht_oper_centr_freq_seg1_idx={{ capabilities.vht.center_channel_freq.freq_2 }} -{% endif %} +{% endif %} -{% if capabilities.vht.channel_set_width is defined %} +{% if capabilities.vht.channel_set_width is vyos_defined %} vht_oper_chwidth={{ capabilities.vht.channel_set_width }} -{% endif %} - -{% set output = namespace(value='') %} -{% if capabilities.vht.stbc is defined and capabilities.vht.stbc.tx is defined %} -{% set output.value = output.value + '[TX-STBC-2BY1]' %} -{% endif %} -{% if capabilities.vht.stbc is defined and capabilities.vht.stbc.rx is defined %} -{% set output.value = output.value + '[RX-STBC-' + capabilities.vht.stbc.rx + ']' %} -{% endif %} -{% if capabilities.vht.ldpc is defined %} -{% set output.value = output.value + '[RXLDPC]' %} -{% endif %} -{% if capabilities.vht.tx_powersave is defined %} -{% set output.value = output.value + '[VHT-TXOP-PS]' %} -{% endif %} -{% if capabilities.vht.vht_cf is defined %} -{% set output.value = output.value + '[HTC-VHT]' %} -{% endif %} -{% if capabilities.vht.antenna_pattern_fixed is defined %} -{% set output.value = output.value + '[RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]' %} -{% endif %} -{% if capabilities.vht.max_mpdu is defined %} -{% set output.value = output.value + '[MAX-MPDU-' + capabilities.vht.max_mpdu + ']' %} -{% endif %} -{% if capabilities.vht.max_mpdu_exp is defined %} -{% set output.value = output.value + '[MAX-A-MPDU-LEN-EXP-' + capabilities.vht.max_mpdu_exp + ']' %} -{% endif %} -{% if capabilities.vht.max_mpdu_exp is defined and capabilities.vht.max_mpdu_exp == '2' %} -{% set output.value = output.value + '[VHT160]' %} -{% endif %} -{% if capabilities.vht.max_mpdu_exp is defined and capabilities.vht.max_mpdu_exp == '3' %} -{% set output.value = output.value + '[VHT160-80PLUS80]' %} -{% endif %} -{% if capabilities.vht.link_adaptation is defined and capabilities.vht.link_adaptation == 'unsolicited' %} -{% set output.value = output.value + '[VHT-LINK-ADAPT2]' %} -{% endif %} -{% if capabilities.vht.link_adaptation is defined and capabilities.vht.link_adaptation == 'both' %} -{% set output.value = output.value + '[VHT-LINK-ADAPT3]' %} -{% endif %} - -{% for short_gi in capabilities.vht.short_gi if capabilities.vht.short_gi is defined %} -{% set output.value = output.value + '[SHORT-GI-' + short_gi | upper + ']' %} -{% endfor %} - -{% for beamform in capabilities.vht.beamform if capabilities.vht.beamform is defined %} -{% set output.value = output.value + '[SU-BEAMFORMER]' if beamform == 'single-user-beamformer' else '' %} -{% set output.value = output.value + '[SU-BEAMFORMEE]' if beamform == 'single-user-beamformee' else '' %} -{% set output.value = output.value + '[MU-BEAMFORMER]' if beamform == 'multi-user-beamformer' else '' %} -{% set output.value = output.value + '[MU-BEAMFORMEE]' if beamform == 'multi-user-beamformee' else '' %} -{% endfor %} - -{% if capabilities.vht.antenna_count is defined and capabilities.vht.antenna_count|int > 1 %} -{% if capabilities.vht.beamform %} -{% if beamform == 'single-user-beamformer' %} -{% if capabilities.vht.antenna_count is defined and capabilities.vht.antenna_count|int > 1 and capabilities.vht.antenna_count|int < 6 %} -{% set output.value = output.value + '[BF-ANTENNA-' + capabilities.vht.antenna_count|int -1 + ']' %} -{% set output.value = output.value + '[SOUNDING-DIMENSION-' + capabilities.vht.antenna_count|int -1 + ']' %} +{% endif %} + +{% set output = namespace(value='') %} +{% if capabilities.vht.stbc.tx is vyos_defined %} +{% set output.value = output.value ~ '[TX-STBC-2BY1]' %} +{% endif %} +{% if capabilities.vht.stbc.rx is vyos_defined %} +{% set output.value = output.value ~ '[RX-STBC-' ~ capabilities.vht.stbc.rx ~ ']' %} +{% endif %} +{% if capabilities.vht.ldpc is vyos_defined %} +{% set output.value = output.value ~ '[RXLDPC]' %} +{% endif %} +{% if capabilities.vht.tx_powersave is vyos_defined %} +{% set output.value = output.value ~ '[VHT-TXOP-PS]' %} +{% endif %} +{% if capabilities.vht.vht_cf is vyos_defined %} +{% set output.value = output.value ~ '[HTC-VHT]' %} +{% endif %} +{% if capabilities.vht.antenna_pattern_fixed is vyos_defined %} +{% set output.value = output.value ~ '[RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]' %} +{% endif %} +{% if capabilities.vht.max_mpdu is vyos_defined %} +{% set output.value = output.value ~ '[MAX-MPDU-' ~ capabilities.vht.max_mpdu ~ ']' %} +{% endif %} +{% if capabilities.vht.max_mpdu_exp is vyos_defined %} +{% set output.value = output.value ~ '[MAX-A-MPDU-LEN-EXP-' ~ capabilities.vht.max_mpdu_exp ~ ']' %} +{% if capabilities.vht.max_mpdu_exp is vyos_defined('2') %} +{% set output.value = output.value ~ '[VHT160]' %} +{% endif %} +{% if capabilities.vht.max_mpdu_exp is vyos_defined('3') %} +{% set output.value = output.value ~ '[VHT160-80PLUS80]' %} +{% endif %} +{% endif %} +{% if capabilities.vht.link_adaptation is vyos_defined('unsolicited') %} +{% set output.value = output.value ~ '[VHT-LINK-ADAPT2]' %} +{% elif capabilities.vht.link_adaptation is vyos_defined('both') %} +{% set output.value = output.value ~ '[VHT-LINK-ADAPT3]' %} +{% endif %} + +{% for short_gi in capabilities.vht.short_gi if capabilities.vht.short_gi is vyos_defined %} +{% set output.value = output.value ~ '[SHORT-GI-' ~ short_gi | upper ~ ']' %} +{% endfor %} + +{% for beamform in capabilities.vht.beamform if capabilities.vht.beamform is vyos_defined %} +{% set output.value = output.value ~ '[SU-BEAMFORMER]' if beamform is vyos_defined('single-user-beamformer') else '' %} +{% set output.value = output.value ~ '[SU-BEAMFORMEE]' if beamform is vyos_defined('single-user-beamformee') else '' %} +{% set output.value = output.value ~ '[MU-BEAMFORMER]' if beamform is vyos_defined('multi-user-beamformer') else '' %} +{% set output.value = output.value ~ '[MU-BEAMFORMEE]' if beamform is vyos_defined('multi-user-beamformee') else '' %} +{% endfor %} + +{% if capabilities.vht.antenna_count is vyos_defined and capabilities.vht.antenna_count | int > 1 %} +{% if capabilities.vht.beamform is vyos_defined %} +{% if capabilities.vht.beamform == 'single-user-beamformer' %} +{% if capabilities.vht.antenna_count is vyos_defined and capabilities.vht.antenna_count | int > 1 and capabilities.vht.antenna_count | int < 6 %} +{% set output.value = output.value ~ '[BF-ANTENNA-' ~ capabilities.vht.antenna_count | int -1 ~ ']' %} +{% set output.value = output.value ~ '[SOUNDING-DIMENSION-' ~ capabilities.vht.antenna_count | int -1 ~ ']' %} +{% endif %} +{% endif %} +{% if capabilities.vht.antenna_count is vyos_defined and capabilities.vht.antenna_count | int > 1 and capabilities.vht.antenna_count | int < 5 %} +{% set output.value = output.value ~ '[BF-ANTENNA-' ~ capabilities.vht.antenna_count ~ ']' %} +{% set output.value = output.value ~ '[SOUNDING-DIMENSION-' ~ capabilities.vht.antenna_count ~ ']' %} +{% endif %} {% endif %} -{% endif %} -{% if capabilities.vht.antenna_count is defined and capabilities.vht.antenna_count|int > 1 and capabilities.vht.antenna_count|int < 5 %} -{% set output.value = output.value + '[BF-ANTENNA-' + capabilities.vht.antenna_count + ']' %} -{% set output.value = output.value + '[SOUNDING-DIMENSION-' + capabilities.vht.antenna_count+ ']' %} -{% endif %} {% endif %} -{% endif %} vht_capab={{ output.value }} {% endif %} @@ -410,19 +410,15 @@ vht_capab={{ output.value }} # 1 = enabled # Note: You will also need to enable WMM for full HT functionality. # Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band. -{% if capabilities is defined and capabilities.require_vht is defined %} +{% if capabilities.require_vht is vyos_defined %} ieee80211n=0 # Require stations to support VHT PHY (reject association if they do not) require_vht=1 {% else %} -{% if 'n' in mode or 'ac' in mode %} -ieee80211n=1 -{% else %} -ieee80211n=0 -{% endif %} +ieee80211n={{ '1' if 'n' in mode or 'ac' in mode else '0' }} {% endif %} -{% if disable_broadcast_ssid is defined %} +{% if disable_broadcast_ssid is vyos_defined %} # Send empty SSID in beacons and ignore probe request frames that do not # specify full SSID, i.e., require stations to know SSID. # default: disabled (0) @@ -443,7 +439,7 @@ ignore_broadcast_ssid=1 # 2 = use external RADIUS server (accept/deny lists are searched first) macaddr_acl=0 -{% if max_stations is defined %} +{% if max_stations is vyos_defined %} # Maximum number of stations allowed in station table. New stations will be # rejected after the station table is full. IEEE 802.11 has a limit of 2007 # different association IDs, so this number should not be larger than that. @@ -451,13 +447,13 @@ macaddr_acl=0 max_num_sta={{ max_stations }} {% endif %} -{% if isolate_stations is defined %} +{% if isolate_stations is vyos_defined %} # Client isolation can be used to prevent low-level bridging of frames between # associated stations in the BSS. By default, this bridging is allowed. ap_isolate=1 {% endif %} -{% if reduce_transmit_power is defined %} +{% if reduce_transmit_power is vyos_defined %} # Add Power Constraint element to Beacon and Probe Response frames # This config option adds Power Constraint element when applicable and Country # element is added. Power Constraint element is required by Transmit Power @@ -466,7 +462,7 @@ ap_isolate=1 local_pwr_constraint={{ reduce_transmit_power }} {% endif %} -{% if expunge_failing_stations is defined %} +{% if expunge_failing_stations is vyos_defined %} # Disassociate stations based on excessive transmission failures or other # indications of connection loss. This depends on the driver capabilities and # may not be available with all drivers. @@ -474,7 +470,7 @@ disassoc_low_ack=1 {% endif %} -{% if security is defined and security.wep is defined %} +{% if security.wep is vyos_defined %} # IEEE 802.11 specifies two authentication algorithms. hostapd can be # configured to allow both of these or only one. Open system authentication # should be used with IEEE 802.1X. @@ -503,14 +499,14 @@ wep_default_key=0 # digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or # 128-bit (152-bit) WEP is used. # Only the default key must be supplied; the others are optional. -{% if security.wep.key is defined %} -{% for key in sec_wep_key %} +{% if security.wep.key is vyos_defined %} +{% for key in sec_wep_key %} wep_key{{ loop.index -1 }}={{ security.wep.key }} -{% endfor %} -{% endif %} +{% endfor %} +{% endif %} -{% elif security is defined and security.wpa is defined %} +{% elif security.wpa is vyos_defined %} ##### WPA/IEEE 802.11i configuration ########################################## # Enable WPA. Setting this variable configures the AP to require WPA (either @@ -527,17 +523,15 @@ wep_key{{ loop.index -1 }}={{ security.wep.key }} # Note that WPA3 is also configured with bit1 since it uses RSN just like WPA2. # In other words, for WPA3, wpa 2 is used the configuration (and # wpa_key_mgmt=SAE for WPA3-Personal instead of wpa_key_mgmt=WPA-PSK). -{% if security.wpa.mode is defined %} -{% if security.wpa.mode == 'wpa+wpa2' %} +{% if security.wpa.mode is vyos_defined('wpa+wpa2') %} wpa=3 -{% elif security.wpa.mode == 'wpa2' or security.wpa.mode == 'wpa3' %} +{% elif security.wpa.mode is vyos_defined('wpa2') or security.wpa.mode is vyos_defined('wpa3') %} wpa=2 -{% elif security.wpa.mode == 'wpa' %} +{% elif security.wpa.mode is vyos_defined('wpa') %} wpa=1 {% endif %} -{% endif %} -{% if security.wpa.cipher is defined %} +{% if security.wpa.cipher is vyos_defined %} # Set of accepted cipher suites (encryption algorithms) for pairwise keys # (unicast packets). This is a space separated list of algorithms: # CCMP = AES in Counter mode with CBC-MAC (CCMP-128) @@ -551,16 +545,16 @@ wpa=1 # TKIP will be used as the group cipher. The optional group_cipher parameter can # be used to override this automatic selection. -{% if security.wpa.mode is defined and security.wpa.mode == 'wpa2' %} +{% if security.wpa.mode is vyos_defined('wpa2') %} # Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value) rsn_pairwise={{ security.wpa.cipher | join(" ") }} -{% else %} +{% else %} # Pairwise cipher for WPA (v1) (default: TKIP) wpa_pairwise={{ security.wpa.cipher | join(" ") }} +{% endif %} {% endif %} -{% endif %} -{% if security.wpa.group_cipher is defined %} +{% if security.wpa.group_cipher is vyos_defined %} # Optional override for automatic group cipher selection # This can be used to select a specific group cipher regardless of which # pairwise ciphers were enabled for WPA and RSN. It should be noted that @@ -568,9 +562,9 @@ wpa_pairwise={{ security.wpa.cipher | join(" ") }} # interoperability issues and in general, this parameter is mainly used for # testing purposes. group_cipher={{ security.wpa.group_cipher | join(" ") }} -{% endif %} +{% endif %} -{% if security.wpa.passphrase is defined %} +{% if security.wpa.passphrase is vyos_defined %} # IEEE 802.11 specifies two authentication algorithms. hostapd can be # configured to allow both of these or only one. Open system authentication # should be used with IEEE 802.1X. @@ -594,13 +588,13 @@ wpa_passphrase={{ security.wpa.passphrase }} # WPA-EAP-SHA256 = WPA2-Enterprise using SHA256 # SAE = SAE (WPA3-Personal) # WPA-EAP-SUITE-B-192 = WPA3-Enterprise with 192-bit security/CNSA suite -{% if security.wpa.mode is defined and security.wpa.mode == 'wpa3' %} +{% if security.wpa.mode is vyos_defined('wpa3') %} wpa_key_mgmt=SAE -{% else %} +{% else %} wpa_key_mgmt=WPA-PSK WPA-PSK-SHA256 -{% endif %} +{% endif %} -{% elif security.wpa.radius is defined %} +{% elif security.wpa.radius is vyos_defined %} ##### IEEE 802.1X-2004 related configuration ################################## # Require IEEE 802.1X authorization ieee8021x=1 @@ -614,43 +608,43 @@ ieee8021x=1 # WPA-EAP-SHA256 = WPA2-Enterprise using SHA256 # SAE = SAE (WPA3-Personal) # WPA-EAP-SUITE-B-192 = WPA3-Enterprise with 192-bit security/CNSA suite -{% if security.wpa.mode is defined and security.wpa.mode == 'wpa3' %} +{% if security.wpa.mode is vyos_defined('wpa3') %} wpa_key_mgmt=WPA-EAP-SUITE-B-192 -{% else %} +{% else %} wpa_key_mgmt=WPA-EAP WPA-EAP-SHA256 -{% endif %} +{% endif %} -{% if security.wpa.radius.server is defined %} +{% if security.wpa.radius.server is vyos_defined %} # RADIUS client forced local IP address for the access point # Normally the local IP address is determined automatically based on configured # IP addresses, but this field can be used to force a specific address to be # used, e.g., when the device has multiple IP addresses. # The own IP address of the access point (used as NAS-IP-Address) -{% if security.wpa.radius.source_address is defined %} +{% if security.wpa.radius.source_address is vyos_defined %} radius_client_addr={{ security.wpa.radius.source_address }} own_ip_addr={{ security.wpa.radius.source_address }} -{% else %} +{% else %} own_ip_addr=127.0.0.1 -{% endif %} +{% endif %} -{% for radius in security.wpa.radius.server if not radius.disabled %} +{% for radius in security.wpa.radius.server if not radius.disabled %} # RADIUS authentication server auth_server_addr={{ radius.server }} auth_server_port={{ radius.port }} auth_server_shared_secret={{ radius.key }} -{% if radius.acc_port %} +{% if radius.acc_port %} # RADIUS accounting server acct_server_addr={{ radius.server }} acct_server_port={{ radius.acc_port }} acct_server_shared_secret={{ radius.key }} -{% endif %} -{% endfor %} -{% else %} +{% endif %} +{% endfor %} +{% else %} # Open system auth_algs=1 +{% endif %} {% endif %} -{% endif %} {% endif %} # TX queue parameters (EDCF / bursting) diff --git a/data/templates/wifi/wpa_supplicant.conf.tmpl b/data/templates/wifi/wpa_supplicant.conf.j2 index 20b4f7976..01e0d632f 100644 --- a/data/templates/wifi/wpa_supplicant.conf.tmpl +++ b/data/templates/wifi/wpa_supplicant.conf.j2 @@ -18,7 +18,7 @@ network={ # this will add latency to scanning, so enable this only when needed) scan_ssid=1 -{% if security is defined and security.wpa is defined and security.wpa.passphrase is defined %} +{% if security.wpa.passphrase is vyos_defined %} # ieee80211w: whether management frame protection is enabled # 0 = disabled (default unless changed with the global pmf parameter) # 1 = optional @@ -59,11 +59,11 @@ network={ # OWE = Opportunistic Wireless Encryption (a.k.a. Enhanced Open) # DPP = Device Provisioning Protocol # If not set, this defaults to: WPA-PSK WPA-EAP -{% if security.wpa.mode is defined and security.wpa.mode == 'wpa3' %} +{% if security.wpa.mode is vyos_defined('wpa3') %} key_mgmt=SAE -{% else %} +{% else %} key_mgmt=WPA-PSK WPA-PSK-SHA256 -{% endif %} +{% endif %} # psk: WPA preshared key; 256-bit pre-shared key # The key used in WPA-PSK mode can be entered either as 64 hex-digits, i.e., diff --git a/data/templates/zone_policy/nftables.j2 b/data/templates/zone_policy/nftables.j2 new file mode 100644 index 000000000..e4c4dd7da --- /dev/null +++ b/data/templates/zone_policy/nftables.j2 @@ -0,0 +1,113 @@ +#!/usr/sbin/nft -f + +{% if cleanup_commands is vyos_defined %} +{% for command in cleanup_commands %} +{{ command }} +{% endfor %} +{% endif %} + +{% if zone is vyos_defined %} +table ip filter { +{% for zone_name, zone_conf in zone.items() if zone_conf.ipv4 %} +{% if zone_conf.local_zone is vyos_defined %} + chain VZONE_{{ zone_name }}_IN { + iifname lo counter return +{% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall.name is vyos_defined %} + iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME_{{ from_conf.firewall.name }} + iifname { {{ zone[from_zone].interface | join(",") }} } counter return +{% endfor %} + counter {{ zone_conf.default_action }} + } + chain VZONE_{{ zone_name }}_OUT { + oifname lo counter return +{% for from_zone, from_conf in zone_conf.from_local.items() if from_conf.firewall.name is vyos_defined %} + oifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME_{{ from_conf.firewall.name }} + oifname { {{ zone[from_zone].interface | join(",") }} } counter return +{% endfor %} + counter {{ zone_conf.default_action }} + } +{% else %} + chain VZONE_{{ zone_name }} { + iifname { {{ zone_conf.interface | join(",") }} } counter {{ zone_conf | nft_intra_zone_action(ipv6=False) }} +{% if zone_conf.intra_zone_filtering is vyos_defined %} + iifname { {{ zone_conf.interface | join(",") }} } counter return +{% endif %} +{% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall.name is vyos_defined %} +{% if zone[from_zone].local_zone is not defined %} + iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME_{{ from_conf.firewall.name }} + iifname { {{ zone[from_zone].interface | join(",") }} } counter return +{% endif %} +{% endfor %} + counter {{ zone_conf.default_action }} + } +{% endif %} +{% endfor %} +} + +table ip6 filter { +{% for zone_name, zone_conf in zone.items() if zone_conf.ipv6 %} +{% if zone_conf.local_zone is vyos_defined %} + chain VZONE6_{{ zone_name }}_IN { + iifname lo counter return +{% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall.ipv6_name is vyos_defined %} + iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME6_{{ from_conf.firewall.ipv6_name }} + iifname { {{ zone[from_zone].interface | join(",") }} } counter return +{% endfor %} + counter {{ zone_conf.default_action }} + } + chain VZONE6_{{ zone_name }}_OUT { + oifname lo counter return +{% for from_zone, from_conf in zone_conf.from_local.items() if from_conf.firewall.ipv6_name is vyos_defined %} + oifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME6_{{ from_conf.firewall.ipv6_name }} + oifname { {{ zone[from_zone].interface | join(",") }} } counter return +{% endfor %} + counter {{ zone_conf.default_action }} + } +{% else %} + chain VZONE6_{{ zone_name }} { + iifname { {{ zone_conf.interface | join(",") }} } counter {{ zone_conf | nft_intra_zone_action(ipv6=True) }} +{% if zone_conf.intra_zone_filtering is vyos_defined %} + iifname { {{ zone_conf.interface | join(",") }} } counter return +{% endif %} +{% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall.ipv6_name is vyos_defined %} +{% if zone[from_zone].local_zone is not defined %} + iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME6_{{ from_conf.firewall.ipv6_name }} + iifname { {{ zone[from_zone].interface | join(",") }} } counter return +{% endif %} +{% endfor %} + counter {{ zone_conf.default_action }} + } +{% endif %} +{% endfor %} +} + +{% for zone_name, zone_conf in zone.items() %} +{% if zone_conf.ipv4 %} +{% if 'local_zone' in zone_conf %} +insert rule ip filter VYOS_FW_LOCAL counter jump VZONE_{{ zone_name }}_IN +insert rule ip filter VYOS_FW_OUTPUT counter jump VZONE_{{ zone_name }}_OUT +{% else %} +insert rule ip filter VYOS_FW_FORWARD oifname { {{ zone_conf.interface | join(',') }} } counter jump VZONE_{{ zone_name }} +{% endif %} +{% endif %} +{% if zone_conf.ipv6 %} +{% if 'local_zone' in zone_conf %} +insert rule ip6 filter VYOS_FW6_LOCAL counter jump VZONE6_{{ zone_name }}_IN +insert rule ip6 filter VYOS_FW6_OUTPUT counter jump VZONE6_{{ zone_name }}_OUT +{% else %} +insert rule ip6 filter VYOS_FW6_FORWARD oifname { {{ zone_conf.interface | join(',') }} } counter jump VZONE6_{{ zone_name }} +{% endif %} +{% endif %} +{% endfor %} + +{# Ensure that state-policy rule is first in the chain #} +{% if firewall.state_policy is vyos_defined %} +{% for chain in ['VYOS_FW_FORWARD', 'VYOS_FW_OUTPUT', 'VYOS_FW_LOCAL'] %} +insert rule ip filter {{ chain }} jump VYOS_STATE_POLICY +{% endfor %} +{% for chain in ['VYOS_FW6_FORWARD', 'VYOS_FW6_OUTPUT', 'VYOS_FW6_LOCAL'] %} +insert rule ip6 filter {{ chain }} jump VYOS_STATE_POLICY6 +{% endfor %} +{% endif %} + +{% endif %} diff --git a/debian/control b/debian/control index 08c04b439..bcd5acfdd 100644 --- a/debian/control +++ b/debian/control @@ -94,6 +94,7 @@ Depends: ndisc6, ndppd, netplug, + nfct, nftables (>= 0.9.3), nginx-light, ntp, @@ -146,11 +147,13 @@ Depends: squid, squidclient, squidguard, + sshguard, ssl-cert, strongswan (>= 5.9), strongswan-swanctl (>= 5.9), sudo, systemd, + telegraf (>= 1.20), tcpdump, tcptraceroute, telnet, @@ -168,7 +171,9 @@ Depends: wide-dhcpv6-client, wireguard-tools, wireless-regdb, - wpasupplicant (>= 0.6.7) + wpasupplicant (>= 0.6.7), + ndppd, + miniupnpd-nftables Description: VyOS configuration scripts and data VyOS configuration scripts, interface definitions, and everything @@ -183,5 +188,6 @@ Description: VyOS configuration scripts and data for VMware Package: vyos-1x-smoketest Architecture: all Depends: + snmp, vyos-1x Description: VyOS build sanity checking toolkit diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install index 29d74390f..493c896eb 100644 --- a/debian/vyos-1x.install +++ b/debian/vyos-1x.install @@ -1,4 +1,3 @@ -etc/cron.d etc/cron.hourly etc/dhcp etc/ipsec.d @@ -12,6 +11,7 @@ etc/security etc/sudoers.d etc/systemd etc/sysctl.d +etc/telegraf etc/udev etc/update-motd.d etc/vyos diff --git a/debian/vyos-1x.postinst b/debian/vyos-1x.postinst index 4b4c4c13e..1ca6687a3 100644 --- a/debian/vyos-1x.postinst +++ b/debian/vyos-1x.postinst @@ -83,3 +83,17 @@ fi if [ -L /etc/init.d/README ]; then rm -f /etc/init.d/README fi + +# Remove unwanted daemon files from /etc +# conntackd +DELETE="/etc/logrotate.d/conntrackd.distrib /etc/init.d/conntrackd /etc/default/conntrackd + /etc/default/pmacctd /etc/pmacct" +for file in $DELETE; do + if [ -f ${file} ]; then + rm -f ${file} + fi +done + +# Remove logrotate items controlled via CLI and VyOS defaults +sed -i '/^\/var\/log\/messages$/d' /etc/logrotate.d/rsyslog +sed -i '/^\/var\/log\/auth.log$/d' /etc/logrotate.d/rsyslog diff --git a/debian/vyos-1x.preinst b/debian/vyos-1x.preinst index 45440bf64..71750b3a1 100644 --- a/debian/vyos-1x.preinst +++ b/debian/vyos-1x.preinst @@ -1,4 +1,4 @@ dpkg-divert --package vyos-1x --add --rename /etc/securetty dpkg-divert --package vyos-1x --add --rename /etc/security/capability.conf dpkg-divert --package vyos-1x --add --rename /lib/systemd/system/lcdproc.service - +dpkg-divert --package vyos-1x --add --rename /etc/logrotate.d/conntrackd diff --git a/interface-definitions/containers.xml.in b/interface-definitions/container.xml.in index 30c7110b8..51171d881 100644 --- a/interface-definitions/containers.xml.in +++ b/interface-definitions/container.xml.in @@ -1,6 +1,6 @@ <?xml version="1.0"?> <interfaceDefinition> - <node name="container" owner="${vyos_conf_scripts_dir}/containers.py"> + <node name="container" owner="${vyos_conf_scripts_dir}/container.py"> <properties> <help>Container applications</help> <priority>1280</priority> @@ -10,7 +10,7 @@ <properties> <help>Container name</help> <constraint> - <regex>^[-a-zA-Z0-9]+$</regex> + <regex>[-a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Container name must be alphanumeric and can contain hyphens</constraintErrorMessage> </properties> @@ -52,18 +52,43 @@ <description>Permission to set system clock</description> </valueHelp> <constraint> - <regex>^(net-admin|net-bind-service|net-raw|setpcap|sys-admin|sys-time)$</regex> + <regex>(net-admin|net-bind-service|net-raw|setpcap|sys-admin|sys-time)</regex> </constraint> <multi/> </properties> </leafNode> #include <include/generic-description.xml.i> + <tagNode name="device"> + <properties> + <help>Add a host device to the container</help> + </properties> + <children> + <leafNode name="source"> + <properties> + <help>Source device (Example: "/dev/x")</help> + <valueHelp> + <format>txt</format> + <description>Source device</description> + </valueHelp> + </properties> + </leafNode> + <leafNode name="destination"> + <properties> + <help>Destination container device (Example: "/dev/x")</help> + <valueHelp> + <format>txt</format> + <description>Destination container device</description> + </valueHelp> + </properties> + </leafNode> + </children> + </tagNode> #include <include/generic-disable-node.xml.i> <tagNode name="environment"> <properties> <help>Add custom environment variables</help> <constraint> - <regex>^[-_a-zA-Z0-9]+$</regex> + <regex>[-_a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Environment variable name must be alphanumeric and can contain hyphen and underscores</constraintErrorMessage> </properties> @@ -86,7 +111,7 @@ </leafNode> <leafNode name="memory"> <properties> - <help>Constrain the memory available to a container (default: 512MB)</help> + <help>Constrain the memory available to a container</help> <valueHelp> <format>u32:0</format> <description>Unlimited</description> @@ -169,7 +194,7 @@ <list>tcp udp</list> </completionHelp> <constraint> - <regex>^(tcp|udp)$</regex> + <regex>(tcp|udp)</regex> </constraint> </properties> </leafNode> @@ -187,14 +212,14 @@ </valueHelp> <valueHelp> <format>on-failure</format> - <description>Restart containers when they exit with a non-zero exit code, retrying indefinitely (default)</description> + <description>Restart containers when they exit with a non-zero exit code, retrying indefinitely</description> </valueHelp> <valueHelp> <format>always</format> <description>Restart containers when they exit, regardless of status, retrying indefinitely</description> </valueHelp> <constraint> - <regex>^(no|on-failure|always)$</regex> + <regex>(no|on-failure|always)</regex> </constraint> </properties> <defaultValue>on-failure</defaultValue> @@ -258,10 +283,10 @@ </tagNode> <leafNode name="registry"> <properties> - <help>Add registry (default docker.io)</help> + <help>Registry Name</help> <multi/> </properties> - <defaultValue>docker.io</defaultValue> + <defaultValue>docker.io quay.io</defaultValue> </leafNode> </children> </node> diff --git a/interface-definitions/dhcp-relay.xml.in b/interface-definitions/dhcp-relay.xml.in index 483e776a7..27d0a3e6c 100644 --- a/interface-definitions/dhcp-relay.xml.in +++ b/interface-definitions/dhcp-relay.xml.in @@ -20,7 +20,7 @@ <help>Policy to discard packets that have reached specified hop-count</help> <valueHelp> <format>u32:1-255</format> - <description>Hop count (default: 10)</description> + <description>Hop count</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-255"/> @@ -34,17 +34,18 @@ <help>Maximum packet size to send to a DHCPv4/BOOTP server</help> <valueHelp> <format>u32:64-1400</format> - <description>Maximum packet size (default: 576)</description> + <description>Maximum packet size</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 64-1400"/> </constraint> <constraintErrorMessage>max-size must be a value between 64 and 1400</constraintErrorMessage> </properties> + <defaultValue>576</defaultValue> </leafNode> <leafNode name="relay-agents-packets"> <properties> - <help>Policy to handle incoming DHCPv4 packets which already contain relay agent options (default: forward)</help> + <help>Policy to handle incoming DHCPv4 packets which already contain relay agent options</help> <completionHelp> <list>append replace forward discard</list> </completionHelp> @@ -65,7 +66,7 @@ <description>discard packet (default action if giaddr not set in packet)</description> </valueHelp> <constraint> - <regex>^(append|replace|forward|discard)$</regex> + <regex>(append|replace|forward|discard)</regex> </constraint> </properties> <defaultValue>forward</defaultValue> diff --git a/interface-definitions/dhcp-server.xml.in b/interface-definitions/dhcp-server.xml.in index d1ed579e9..60e738e01 100644 --- a/interface-definitions/dhcp-server.xml.in +++ b/interface-definitions/dhcp-server.xml.in @@ -58,7 +58,7 @@ <description>Configure this server to be the secondary node</description> </valueHelp> <constraint> - <regex>^(primary|secondary)$</regex> + <regex>(primary|secondary)</regex> </constraint> <constraintErrorMessage>Invalid DHCP failover peer status</constraintErrorMessage> </properties> @@ -142,6 +142,11 @@ boot file is to be loaded</help> </properties> </leafNode> + <leafNode name="bootfile-size"> + <properties> + <help>Bootstrap file size in 512 byte blocks</help> + </properties> + </leafNode> <leafNode name="client-prefix-length"> <properties> <help>Specifies the clients subnet mask as per RFC 950. If unset, subnet declaration is used.</help> @@ -198,7 +203,7 @@ </leafNode> <leafNode name="lease"> <properties> - <help>Lease timeout in seconds (default: 86400)</help> + <help>Lease timeout in seconds</help> <valueHelp> <format>u32</format> <description>DHCP lease time in seconds</description> @@ -254,7 +259,7 @@ <properties> <help>DHCP lease range</help> <constraint> - <regex>^[-_a-zA-Z0-9.]+$</regex> + <regex>[-_a-zA-Z0-9.]+</regex> </constraint> <constraintErrorMessage>Invalid range name, may only be alphanumeric, dot and hyphen</constraintErrorMessage> </properties> @@ -289,7 +294,7 @@ <properties> <help>Name of static mapping</help> <constraint> - <regex>^[-_a-zA-Z0-9.]+$</regex> + <regex>[-_a-zA-Z0-9.]+</regex> </constraint> <constraintErrorMessage>Invalid static mapping name, may only be alphanumeric, dot and hyphen</constraintErrorMessage> </properties> @@ -369,6 +374,18 @@ <leafNode name="tftp-server-name"> <properties> <help>TFTP server name</help> + <valueHelp> + <format>ipv4</format> + <description>TFTP server IPv4 address</description> + </valueHelp> + <valueHelp> + <format>hostname</format> + <description>TFTP server FQDN</description> + </valueHelp> + <constraint> + <validator name="ipv4-address"/> + <validator name="fqdn"/> + </constraint> </properties> </leafNode> <leafNode name="time-offset"> @@ -397,6 +414,32 @@ <multi/> </properties> </leafNode> + <node name="vendor-option"> + <properties> + <help>Vendor Specific Options</help> + </properties> + <children> + <node name="ubiquiti"> + <properties> + <help>Ubiquiti specific parameters</help> + </properties> + <children> + <leafNode name="unifi-controller"> + <properties> + <help>Address of UniFi controller</help> + <valueHelp> + <format>ipv4</format> + <description>IP address of UniFi controller</description> + </valueHelp> + <constraint> + <validator name="ipv4-address"/> + </constraint> + </properties> + </leafNode> + </children> + </node> + </children> + </node> <leafNode name="wins-server"> <properties> <help>IP address for Windows Internet Name Service (WINS) server</help> diff --git a/interface-definitions/dhcpv6-relay.xml.in b/interface-definitions/dhcpv6-relay.xml.in index 7162cf353..5abcbe804 100644 --- a/interface-definitions/dhcpv6-relay.xml.in +++ b/interface-definitions/dhcpv6-relay.xml.in @@ -36,7 +36,7 @@ <help>Maximum hop count for which requests will be processed</help> <valueHelp> <format>u32:1-255</format> - <description>Hop count (default: 10)</description> + <description>Hop count</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-255"/> diff --git a/interface-definitions/dhcpv6-server.xml.in b/interface-definitions/dhcpv6-server.xml.in index fb96571f5..10335b07e 100644 --- a/interface-definitions/dhcpv6-server.xml.in +++ b/interface-definitions/dhcpv6-server.xml.in @@ -338,6 +338,33 @@ </leafNode> </children> </tagNode> + <node name="vendor-option"> + <properties> + <help>Vendor Specific Options</help> + </properties> + <children> + <node name="cisco"> + <properties> + <help>Cisco specific parameters</help> + </properties> + <children> + <leafNode name="tftp-server"> + <properties> + <help>TFTP server name</help> + <valueHelp> + <format>ipv6</format> + <description>TFTP server IPv6 address</description> + </valueHelp> + <constraint> + <validator name="ipv6-address"/> + </constraint> + <multi/> + </properties> + </leafNode> + </children> + </node> + </children> + </node> </children> </tagNode> </children> diff --git a/interface-definitions/dns-domain-name.xml.in b/interface-definitions/dns-domain-name.xml.in index 005a55ab3..0d6418272 100644 --- a/interface-definitions/dns-domain-name.xml.in +++ b/interface-definitions/dns-domain-name.xml.in @@ -29,6 +29,7 @@ </constraint> </properties> </leafNode> + <!-- script does not use XML defaults so far --> <leafNode name="host-name" owner="${vyos_conf_scripts_dir}/host_name.py"> <properties> <help>System host name (default: vyos)</help> @@ -55,7 +56,7 @@ <properties> <help>DNS domain completion order</help> <constraint> - <regex>[-a-zA-Z0-9.]+$</regex> + <regex>[-a-zA-Z0-9.]+</regex> </constraint> <constraintErrorMessage>Invalid domain name</constraintErrorMessage> <multi/> @@ -73,7 +74,7 @@ <properties> <help>Host name for static address mapping</help> <constraint> - <regex>[A-Za-z0-9][-.A-Za-z0-9]*[A-Za-z0-9]$</regex> + <regex>[A-Za-z0-9][-.A-Za-z0-9]*[A-Za-z0-9]</regex> </constraint> <constraintErrorMessage>invalid hostname</constraintErrorMessage> </properties> @@ -82,7 +83,7 @@ <properties> <help>Alias for this address</help> <constraint> - <regex>.{1,63}$</regex> + <regex>.{1,63}</regex> </constraint> <constraintErrorMessage>invalid alias hostname, needs to be between 1 and 63 charactes</constraintErrorMessage> <multi /> diff --git a/interface-definitions/dns-dynamic.xml.in b/interface-definitions/dns-dynamic.xml.in index 64826516e..6bc467b76 100644 --- a/interface-definitions/dns-dynamic.xml.in +++ b/interface-definitions/dns-dynamic.xml.in @@ -120,7 +120,7 @@ <description>zoneedit.com Services</description> </valueHelp> <constraint> - <regex>^(custom|afraid|changeip|cloudflare|dnspark|dslreports|dyndns|easydns|namecheap|noip|sitelutions|zoneedit|\w+)$</regex> + <regex>(custom|afraid|changeip|cloudflare|dnspark|dslreports|dyndns|easydns|namecheap|noip|sitelutions|zoneedit|\w+)</regex> </constraint> <constraintErrorMessage>You can use only predefined list of services or word characters (_, a-z, A-Z, 0-9) as service name</constraintErrorMessage> </properties> @@ -232,7 +232,7 @@ <description>Zoneedit protocol</description> </valueHelp> <constraint> - <regex>^(changeip|cloudflare|dnsmadeeasy|dnspark|dondominio|dslreports1|dtdns|duckdns|dyndns2|easydns|freedns|freemyip|googledomains|hammernode1|namecheap|nfsn|noip|sitelutions|woima|yandex|zoneedit1)$</regex> + <regex>(changeip|cloudflare|dnsmadeeasy|dnspark|dondominio|dslreports1|dtdns|duckdns|dyndns2|easydns|freedns|freemyip|googledomains|hammernode1|namecheap|nfsn|noip|sitelutions|woima|yandex|zoneedit1)</regex> </constraint> <constraintErrorMessage>Please choose from the list of allowed protocols</constraintErrorMessage> </properties> diff --git a/interface-definitions/dns-forwarding.xml.in b/interface-definitions/dns-forwarding.xml.in index 5b0c87597..6ead3e199 100644 --- a/interface-definitions/dns-forwarding.xml.in +++ b/interface-definitions/dns-forwarding.xml.in @@ -16,7 +16,7 @@ <children> <leafNode name="cache-size"> <properties> - <help>DNS forwarding cache size (default: 10000)</help> + <help>DNS forwarding cache size</help> <valueHelp> <format>u32:0-2147483647</format> <description>DNS forwarding cache size</description> @@ -38,7 +38,7 @@ </leafNode> <leafNode name="dnssec"> <properties> - <help>DNSSEC mode (default: process-no-validate)</help> + <help>DNSSEC mode</help> <completionHelp> <list>off process-no-validate process log-fail validate</list> </completionHelp> @@ -63,7 +63,7 @@ <description>Full blown DNSSEC validation. Send SERVFAIL to clients on bogus responses.</description> </valueHelp> <constraint> - <regex>^(off|process-no-validate|process|log-fail|validate)$</regex> + <regex>(off|process-no-validate|process|log-fail|validate)</regex> </constraint> </properties> <defaultValue>process-no-validate</defaultValue> @@ -105,6 +105,456 @@ </leafNode> </children> </tagNode> + <tagNode name="authoritative-domain"> + <properties> + <help>Domain to host authoritative records for</help> + <valueHelp> + <format>text</format> + <description>An absolute DNS name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9.]{1,63}</regex> + </constraint> + </properties> + <children> + <node name="records"> + <properties> + <help>DNS zone records</help> + </properties> + <children> + <tagNode name="a"> + <properties> + <help>"A" record</help> + <valueHelp> + <format>text</format> + <description>A DNS name relative to the root record</description> + </valueHelp> + <valueHelp> + <format>@</format> + <description>Root record</description> + </valueHelp> + <constraint> + <regex>([-_a-zA-Z0-9.]{1,63}|@)(?<!\.)</regex> + </constraint> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv4 address [REQUIRED]</help> + <valueHelp> + <format>ipv4</format> + <description>IPv4 address</description> + </valueHelp> + <multi/> + <constraint> + <validator name="ipv4-address"/> + </constraint> + </properties> + </leafNode> + #include <include/dns/time-to-live.xml.i> + #include <include/generic-disable-node.xml.i> + </children> + </tagNode> + <tagNode name="aaaa"> + <properties> + <help>"AAAA" record</help> + <valueHelp> + <format>text</format> + <description>A DNS name relative to the root record</description> + </valueHelp> + <valueHelp> + <format>@</format> + <description>Root record</description> + </valueHelp> + <constraint> + <regex>([-_a-zA-Z0-9.]{1,63}|@)(?<!\.)</regex> + </constraint> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv6 address [REQUIRED]</help> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address</description> + </valueHelp> + <multi/> + <constraint> + <validator name="ipv6-address"/> + </constraint> + </properties> + </leafNode> + #include <include/dns/time-to-live.xml.i> + #include <include/generic-disable-node.xml.i> + </children> + </tagNode> + <tagNode name="cname"> + <properties> + <help>"CNAME" record</help> + <valueHelp> + <format>text</format> + <description>A DNS name relative to the root record</description> + </valueHelp> + <valueHelp> + <format>@</format> + <description>Root record</description> + </valueHelp> + <constraint> + <regex>([-_a-zA-Z0-9.]{1,63}|@)(?<!\.)</regex> + </constraint> + </properties> + <children> + <leafNode name="target"> + <properties> + <help>Target DNS name [REQUIRED]</help> + <valueHelp> + <format>name.example.com</format> + <description>An absolute DNS name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9.]{1,63}(?<!\.)</regex> + </constraint> + </properties> + </leafNode> + #include <include/dns/time-to-live.xml.i> + #include <include/generic-disable-node.xml.i> + </children> + </tagNode> + <tagNode name="mx"> + <properties> + <help>"MX" record</help> + <valueHelp> + <format>text</format> + <description>A DNS name relative to the root record</description> + </valueHelp> + <valueHelp> + <format>@</format> + <description>Root record</description> + </valueHelp> + <constraint> + <regex>([-_a-zA-Z0-9.]{1,63}|@)(?<!\.)</regex> + </constraint> + </properties> + <children> + <tagNode name="server"> + <properties> + <help>Mail server [REQUIRED]</help> + <valueHelp> + <format>name.example.com</format> + <description>An absolute DNS name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9.]{1,63}(?<!\.)</regex> + </constraint> + </properties> + <children> + <leafNode name="priority"> + <properties> + <help>Server priority</help> + <valueHelp> + <format>u32:1-999</format> + <description>Server priority (lower numbers are higher priority)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-999"/> + </constraint> + </properties> + <defaultValue>10</defaultValue> + </leafNode> + </children> + </tagNode> + #include <include/dns/time-to-live.xml.i> + #include <include/generic-disable-node.xml.i> + </children> + </tagNode> + <tagNode name="ptr"> + <properties> + <help>"PTR" record</help> + <valueHelp> + <format>text</format> + <description>A DNS name relative to the root record</description> + </valueHelp> + <valueHelp> + <format>@</format> + <description>Root record</description> + </valueHelp> + <constraint> + <regex>([-_a-zA-Z0-9.]{1,63}|@)(?<!\.)</regex> + </constraint> + </properties> + <children> + <leafNode name="target"> + <properties> + <help>Target DNS name [REQUIRED]</help> + <valueHelp> + <format>name.example.com</format> + <description>An absolute DNS name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9.]{1,63}(?<!\.)</regex> + </constraint> + </properties> + </leafNode> + #include <include/dns/time-to-live.xml.i> + #include <include/generic-disable-node.xml.i> + </children> + </tagNode> + <tagNode name="txt"> + <properties> + <help>"TXT" record</help> + <valueHelp> + <format>text</format> + <description>A DNS name relative to the root record</description> + </valueHelp> + <valueHelp> + <format>@</format> + <description>Root record</description> + </valueHelp> + <constraint> + <regex>([-_a-zA-Z0-9.]{1,63}|@)(?<!\.)</regex> + </constraint> + </properties> + <children> + <leafNode name="value"> + <properties> + <help>Record contents [REQUIRED]</help> + <valueHelp> + <format>text</format> + <description>Record contents</description> + </valueHelp> + <multi/> + </properties> + </leafNode> + #include <include/dns/time-to-live.xml.i> + #include <include/generic-disable-node.xml.i> + </children> + </tagNode> + <tagNode name="spf"> + <properties> + <help>"SPF" record (type=SPF)</help> + <valueHelp> + <format>text</format> + <description>A DNS name relative to the root record</description> + </valueHelp> + <valueHelp> + <format>@</format> + <description>Root record</description> + </valueHelp> + <constraint> + <regex>([-_a-zA-Z0-9.]{1,63}|@)(?<!\.)</regex> + </constraint> + </properties> + <children> + <leafNode name="value"> + <properties> + <help>Record contents [REQUIRED]</help> + <valueHelp> + <format>text</format> + <description>Record contents</description> + </valueHelp> + </properties> + </leafNode> + #include <include/dns/time-to-live.xml.i> + #include <include/generic-disable-node.xml.i> + </children> + </tagNode> + <tagNode name="srv"> + <properties> + <help>"SRV" record</help> + <valueHelp> + <format>text</format> + <description>A DNS name relative to the root record</description> + </valueHelp> + <valueHelp> + <format>@</format> + <description>Root record</description> + </valueHelp> + <constraint> + <regex>([-_a-zA-Z0-9.]{1,63}|@)(?<!\.)</regex> + </constraint> + </properties> + <children> + <tagNode name="entry"> + <properties> + <help>Service entry [REQUIRED]</help> + <valueHelp> + <format>u32:0-65535</format> + <description>Entry number</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + </properties> + <children> + <leafNode name="hostname"> + <properties> + <help>Server hostname [REQUIRED]</help> + <valueHelp> + <format>name.example.com</format> + <description>An absolute DNS name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9.]{1,63}(?<!\.)</regex> + </constraint> + </properties> + </leafNode> + <leafNode name="port"> + <properties> + <help>Port number [REQUIRED]</help> + <valueHelp> + <format>u32:0-65535</format> + <description>TCP/UDP port number</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65536"/> + </constraint> + </properties> + </leafNode> + <leafNode name="priority"> + <properties> + <help>Entry priority</help> + <valueHelp> + <format>u32:0-65535</format> + <description>Entry priority (lower numbers are higher priority)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + </properties> + <defaultValue>10</defaultValue> + </leafNode> + <leafNode name="weight"> + <properties> + <help>Entry weight</help> + <valueHelp> + <format>u32:0-65535</format> + <description>Entry weight</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + </properties> + <defaultValue>0</defaultValue> + </leafNode> + </children> + </tagNode> + #include <include/dns/time-to-live.xml.i> + #include <include/generic-disable-node.xml.i> + </children> + </tagNode> + <tagNode name="naptr"> + <properties> + <help>"NAPTR" record</help> + <valueHelp> + <format>text</format> + <description>A DNS name relative to the root record</description> + </valueHelp> + <valueHelp> + <format>@</format> + <description>Root record</description> + </valueHelp> + <constraint> + <regex>([-_a-zA-Z0-9.]{1,63}|@)(?<!\.)</regex> + </constraint> + </properties> + <children> + <tagNode name="rule"> + <properties> + <help>NAPTR rule [REQUIRED]</help> + <valueHelp> + <format>u32:0-65535</format> + <description>Rule number</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + </properties> + <children> + <leafNode name="order"> + <properties> + <help>Rule order</help> + <valueHelp> + <format>u32:0-65535</format> + <description>Rule order (lower order is evaluated first)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + </properties> + </leafNode> + <leafNode name="preference"> + <properties> + <help>Rule preference</help> + <valueHelp> + <format>u32:0-65535</format> + <description>Rule preference</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + </properties> + <defaultValue>0</defaultValue> + </leafNode> + <leafNode name="lookup-srv"> + <properties> + <help>"S" flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="lookup-a"> + <properties> + <help>"A" flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="resolve-uri"> + <properties> + <help>"U" flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="protocol-specific"> + <properties> + <help>"P" flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="service"> + <properties> + <help>Service type</help> + <constraint> + <regex>[a-zA-Z][a-zA-Z0-9]{0,31}(\+[a-zA-Z][a-zA-Z0-9]{0,31})?</regex> + </constraint> + </properties> + </leafNode> + <leafNode name="regexp"> + <properties> + <help>Regular expression</help> + </properties> + </leafNode> + <leafNode name="replacement"> + <properties> + <help>Replacement DNS name</help> + <valueHelp> + <format>name.example.com</format> + <description>An absolute DNS name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9.]{1,63}(?<!\.)</regex> + </constraint> + </properties> + </leafNode> + </children> + </tagNode> + #include <include/dns/time-to-live.xml.i> + #include <include/generic-disable-node.xml.i> + </children> + </tagNode> + </children> + </node> + #include <include/generic-disable-node.xml.i> + </children> + </tagNode> <leafNode name="ignore-hosts-file"> <properties> <help>Do not use local /etc/hosts file in name resolution</help> @@ -114,7 +564,7 @@ <leafNode name="no-serve-rfc1918"> <properties> <help>Makes the server authoritatively not aware of RFC1918 addresses</help> - <valueless/> + <valueless/> </properties> </leafNode> <leafNode name="allow-from"> @@ -137,7 +587,7 @@ #include <include/listen-address.xml.i> <leafNode name="negative-ttl"> <properties> - <help>Maximum amount of time negative entries are cached (default: 3600)</help> + <help>Maximum amount of time negative entries are cached</help> <valueHelp> <format>u32:0-7200</format> <description>Seconds to cache NXDOMAIN entries</description> @@ -148,6 +598,19 @@ </properties> <defaultValue>3600</defaultValue> </leafNode> + <leafNode name="timeout"> + <properties> + <help>Number of milliseconds to wait for a remote authoritative server to respond</help> + <valueHelp> + <format>u32:10-60000</format> + <description>Network timeout in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 10-60000"/> + </constraint> + </properties> + <defaultValue>1500</defaultValue> + </leafNode> #include <include/name-server-ipv4-ipv6.xml.i> <leafNode name="source-address"> <properties> diff --git a/interface-definitions/firewall.xml.in b/interface-definitions/firewall.xml.in index f07c619a8..ff8d92a24 100644 --- a/interface-definitions/firewall.xml.in +++ b/interface-definitions/firewall.xml.in @@ -1,6 +1,6 @@ <?xml version="1.0"?> <interfaceDefinition> - <node name="nfirewall" owner="${vyos_conf_scripts_dir}/firewall.py"> + <node name="firewall" owner="${vyos_conf_scripts_dir}/firewall.py"> <properties> <priority>199</priority> <help>Firewall</help> @@ -21,9 +21,10 @@ <description>Disable processing of all IPv4 ICMP echo requests</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>enable</defaultValue> </leafNode> <leafNode name="broadcast-ping"> <properties> @@ -40,9 +41,10 @@ <description>Disable processing of broadcast IPv4 ICMP echo/timestamp requests</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>disable</defaultValue> </leafNode> <leafNode name="config-trap"> <properties> @@ -59,9 +61,10 @@ <description>Disable sending SNMP trap on firewall configuration change</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>disable</defaultValue> </leafNode> <node name="group"> <properties> @@ -71,6 +74,9 @@ <tagNode name="address-group"> <properties> <help>Firewall address-group</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> </properties> <children> <leafNode name="address"> @@ -97,6 +103,9 @@ <tagNode name="ipv6-address-group"> <properties> <help>Firewall ipv6-address-group</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> </properties> <children> <leafNode name="address"> @@ -106,8 +115,13 @@ <format>ipv6</format> <description>IPv6 address to match</description> </valueHelp> + <valueHelp> + <format>ipv6range</format> + <description>IPv6 range to match (e.g. 2002::1-2002::ff)</description> + </valueHelp> <constraint> <validator name="ipv6-address"/> + <validator name="ipv6-range"/> </constraint> <multi/> </properties> @@ -117,7 +131,10 @@ </tagNode> <tagNode name="ipv6-network-group"> <properties> - <help>Network-group member</help> + <help>Firewall ipv6-network-group</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> </properties> <children> #include <include/generic-description.xml.i> @@ -136,9 +153,36 @@ </leafNode> </children> </tagNode> + <tagNode name="mac-group"> + <properties> + <help>Firewall mac-group</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> + </properties> + <children> + #include <include/generic-description.xml.i> + <leafNode name="mac-address"> + <properties> + <help>Mac-group member</help> + <valueHelp> + <format><MAC address></format> + <description>MAC address to match</description> + </valueHelp> + <constraint> + <validator name="mac-address"/> + </constraint> + <multi/> + </properties> + </leafNode> + </children> + </tagNode> <tagNode name="network-group"> <properties> <help>Firewall network-group</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> </properties> <children> #include <include/generic-description.xml.i> @@ -160,6 +204,9 @@ <tagNode name="port-group"> <properties> <help>Firewall port-group</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> </properties> <children> #include <include/generic-description.xml.i> @@ -179,6 +226,9 @@ <description>Numbered port range (e.g. 1001-1050)</description> </valueHelp> <multi/> + <constraint> + <validator name="port-range"/> + </constraint> </properties> </leafNode> </children> @@ -200,13 +250,17 @@ <description>Disable processing of IPv4 packets with source route option</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>disable</defaultValue> </leafNode> <tagNode name="ipv6-name"> <properties> <help>IPv6 firewall rule-set name</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> </properties> <children> #include <include/firewall/name-default-action.xml.i> @@ -214,7 +268,15 @@ #include <include/generic-description.xml.i> <tagNode name="rule"> <properties> - <help>Rule number (1-9999)</help> + <help>Firewall rule number (IPv6)</help> + <valueHelp> + <format>u32:1-999999</format> + <description>Number for this Firewall rule</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-999999"/> + </constraint> + <constraintErrorMessage>Firewall rule number must be between 1 and 999999</constraintErrorMessage> </properties> <children> #include <include/firewall/action.xml.i> @@ -225,7 +287,7 @@ </properties> <children> #include <include/firewall/address-ipv6.xml.i> - #include <include/firewall/source-destination-group.xml.i> + #include <include/firewall/source-destination-group-ipv6.xml.i> #include <include/firewall/port.xml.i> </children> </node> @@ -235,7 +297,7 @@ </properties> <children> #include <include/firewall/address-ipv6.xml.i> - #include <include/firewall/source-destination-group.xml.i> + #include <include/firewall/source-destination-group-ipv6.xml.i> #include <include/firewall/port.xml.i> </children> </node> @@ -288,227 +350,31 @@ <help>ICMPv6 type and code information</help> </properties> <children> - <leafNode name="type"> + <leafNode name="code"> <properties> - <help>ICMP type-name</help> - <completionHelp> - <list>any echo-reply pong destination-unreachable network-unreachable host-unreachable protocol-unreachable port-unreachable fragmentation-needed source-route-failed network-unknown host-unknown network-prohibited host-prohibited TOS-network-unreachable TOS-host-unreachable communication-prohibited host-precedence-violation precedence-cutoff source-quench redirect network-redirect host-redirect TOS-network-redirect TOS host-redirect echo-request ping router-advertisement router-solicitation time-exceeded ttl-exceeded ttl-zero-during-transit ttl-zero-during-reassembly parameter-problem ip-header-bad required-option-missing timestamp-request timestamp-reply address-mask-request address-mask-reply</list> - </completionHelp> - <valueHelp> - <format>any</format> - <description>Any ICMP type/code</description> - </valueHelp> - <valueHelp> - <format>echo-reply</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>pong</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>destination-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>protocol-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>port-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>fragmentation-needed</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>source-route-failed</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-unknown</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-unknown</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-prohibited</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-prohibited</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS-network-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS-host-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>communication-prohibited</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-precedence-violation</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>precedence-cutoff</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>source-quench</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> + <help>ICMPv6 code (0-255)</help> <valueHelp> - <format>host-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS-network-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS host-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>echo-request</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ping</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>router-advertisement</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>router-solicitation</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>time-exceeded</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ttl-exceeded</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ttl-zero-during-transit</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ttl-zero-during-reassembly</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>parameter-problem</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ip-header-bad</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>required-option-missing</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>timestamp-request</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>timestamp-reply</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>address-mask-request</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>address-mask-reply</format> - <description>ICMP type/code name</description> + <format>u32:0-255</format> + <description>ICMPv6 code (0-255)</description> </valueHelp> <constraint> - <regex>^(any|echo-reply|pong|destination-unreachable|network-unreachable|host-unreachable|protocol-unreachable|port-unreachable|fragmentation-needed|source-route-failed|network-unknown|host-unknown|network-prohibited|host-prohibited|TOS-network-unreachable|TOS-host-unreachable|communication-prohibited|host-precedence-violation|precedence-cutoff|source-quench|redirect|network-redirect|host-redirect|TOS-network-redirect|TOS host-redirect|echo-request|ping|router-advertisement|router-solicitation|time-exceeded|ttl-exceeded|ttl-zero-during-transit|ttl-zero-during-reassembly|parameter-problem|ip-header-bad|required-option-missing|timestamp-request|timestamp-reply|address-mask-request|address-mask-reply)$</regex> <validator name="numeric" argument="--range 0-255"/> </constraint> </properties> </leafNode> - </children> - </node> - <node name="p2p"> - <properties> - <help>P2P application packets</help> - </properties> - <children> - <leafNode name="all"> - <properties> - <help>AppleJuice/BitTorrent/Direct Connect/eDonkey/eMule/Gnutella/KaZaA application packets</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="applejuice"> - <properties> - <help>AppleJuice application packets</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="bittorrent"> - <properties> - <help>BitTorrent application packets</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="directconnect"> - <properties> - <help>Direct Connect application packets</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="edonkey"> - <properties> - <help>eDonkey/eMule application packets</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="gnutella"> - <properties> - <help>Gnutella application packets</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="kazaa"> + <leafNode name="type"> <properties> - <help>KaZaA application packets</help> - <valueless/> + <help>ICMPv6 type (0-255)</help> + <valueHelp> + <format>u32:0-255</format> + <description>ICMPv6 type (0-255)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-255"/> + </constraint> </properties> </leafNode> + #include <include/firewall/icmpv6-type-name.xml.i> </children> </node> </children> @@ -530,9 +396,10 @@ <description>Disable processing of received ICMPv6 redirect messages</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>disable</defaultValue> </leafNode> <leafNode name="ipv6-src-route"> <properties> @@ -549,9 +416,10 @@ <description>Disable processing of IPv6 packets with routing header</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>disable</defaultValue> </leafNode> <leafNode name="log-martians"> <properties> @@ -568,13 +436,17 @@ <description>Disable logging of Ipv4 packets with invalid addresses</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>enable</defaultValue> </leafNode> <tagNode name="name"> <properties> <help>IPv4 firewall rule-set name</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> </properties> <children> #include <include/firewall/name-default-action.xml.i> @@ -582,7 +454,15 @@ #include <include/generic-description.xml.i> <tagNode name="rule"> <properties> - <help>Rule number (1-9999)</help> + <help>Firewall rule number (IPv4)</help> + <valueHelp> + <format>u32:1-999999</format> + <description>Number for this Firewall rule</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-999999"/> + </constraint> + <constraintErrorMessage>Firewall rule number must be between 1 and 999999</constraintErrorMessage> </properties> <children> #include <include/firewall/action.xml.i> @@ -659,9 +539,10 @@ <description>Disable processing of received IPv4 ICMP redirect messages</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>disable</defaultValue> </leafNode> <leafNode name="send-redirects"> <properties> @@ -678,9 +559,10 @@ <description>Disable sending IPv4 ICMP redirect messages</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>enable</defaultValue> </leafNode> <leafNode name="source-validation"> <properties> @@ -701,9 +583,10 @@ <description>No source validation</description> </valueHelp> <constraint> - <regex>^(strict|loose|disable)$</regex> + <regex>(strict|loose|disable)</regex> </constraint> </properties> + <defaultValue>disable</defaultValue> </leafNode> <node name="state-policy"> <properties> @@ -754,9 +637,10 @@ <description>Disable use of TCP SYN cookies with IPv4</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>enable</defaultValue> </leafNode> <leafNode name="twa-hazards-protection"> <properties> @@ -773,9 +657,10 @@ <description>Disable RFC1337 TIME-WAIT hazards protection</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>disable</defaultValue> </leafNode> </children> </node> diff --git a/interface-definitions/flow-accounting-conf.xml.in b/interface-definitions/flow-accounting-conf.xml.in index 113c1d849..878566b3f 100644 --- a/interface-definitions/flow-accounting-conf.xml.in +++ b/interface-definitions/flow-accounting-conf.xml.in @@ -17,20 +17,34 @@ <description>Buffer size in MiB</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-4294967295" /> + <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> + <defaultValue>10</defaultValue> + </leafNode> + <leafNode name="packet-length"> + <properties> + <help>Specifies the maximum number of bytes to capture for each packet</help> + <valueHelp> + <format>u32:128-750</format> + <description>Packet length in bytes</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 128-750"/> + </constraint> + </properties> + <defaultValue>128</defaultValue> </leafNode> <leafNode name="enable-egress"> <properties> <help>Enable egress flow accounting</help> - <valueless /> + <valueless/> </properties> </leafNode> <leafNode name="disable-imt"> <properties> <help>Disable in memory table plugin</help> - <valueless /> + <valueless/> </properties> </leafNode> <leafNode name="syslog-facility"> @@ -132,7 +146,7 @@ <description>Authentication and authorization</description> </valueHelp> <constraint> - <regex>^(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)$</regex> + <regex>(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)</regex> </constraint> </properties> </leafNode> @@ -154,7 +168,7 @@ <description>NetFlow engine-id for v9 / IPFIX</description> </valueHelp> <constraint> - <regex>(\d|[1-9]\d{1,8}|[1-3]\d{9}|4[01]\d{8}|42[0-8]\d{7}|429[0-3]\d{6}|4294[0-8]\d{5}|42949[0-5]\d{4}|429496[0-6]\d{3}|4294967[01]\d{2}|42949672[0-8]\d|429496729[0-5])$|^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]):(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$</regex> + <regex>(\d|[1-9]\d{1,8}|[1-3]\d{9}|4[01]\d{8}|42[0-8]\d{7}|429[0-3]\d{6}|4294[0-8]\d{5}|42949[0-5]\d{4}|429496[0-6]\d{3}|4294967[01]\d{2}|42949672[0-8]\d|429496729[0-5])$|^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]):(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])</regex> </constraint> </properties> </leafNode> @@ -166,7 +180,7 @@ <description>NetFlow maximum flows</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-4294967295" /> + <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> </leafNode> @@ -178,27 +192,11 @@ <description>Sampling rate (1 in N packets)</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-4294967295" /> - </constraint> - </properties> - </leafNode> - <leafNode name="source-ip"> - <properties> - <help>IPv4 or IPv6 source address of NetFlow packets</help> - <valueHelp> - <format>ipv4</format> - <description>IPv4 source address of NetFlow packets</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>IPv6 source address of NetFlow packets</description> - </valueHelp> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> + <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> </leafNode> + #include <include/source-address-ipv4-ipv6.xml.i> <leafNode name="version"> <properties> <help>NetFlow version to export</help> @@ -211,17 +209,18 @@ </valueHelp> <valueHelp> <format>9</format> - <description>NetFlow version 9 (default)</description> + <description>NetFlow version 9</description> </valueHelp> <valueHelp> <format>10</format> <description>Internet Protocol Flow Information Export (IPFIX)</description> </valueHelp> </properties> + <defaultValue>9</defaultValue> </leafNode> <tagNode name="server"> <properties> - <help>Server to export NetFlow [REQUIRED]</help> + <help>NetFlow destination server</help> <valueHelp> <format>ipv4</format> <description>IPv4 server to export NetFlow</description> @@ -241,12 +240,13 @@ <help>NetFlow port number</help> <valueHelp> <format>u32:1025-65535</format> - <description>NetFlow port number (default 2055)</description> + <description>NetFlow port number</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 1025-65535" /> + <validator name="numeric" argument="--range 1025-65535"/> </constraint> </properties> + <defaultValue>2055</defaultValue> </leafNode> </children> </tagNode> @@ -260,96 +260,104 @@ <help>Expiry scan interval</help> <valueHelp> <format>u32:0-2147483647</format> - <description>Expiry scan interval (default 60)</description> + <description>Expiry scan interval</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-2147483647" /> + <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>60</defaultValue> </leafNode> <leafNode name="flow-generic"> <properties> <help>Generic flow timeout value</help> <valueHelp> <format>u32:0-2147483647</format> - <description>Generic flow timeout in seconds (default 3600)</description> + <description>Generic flow timeout in seconds</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-2147483647" /> + <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>3600</defaultValue> </leafNode> <leafNode name="icmp"> <properties> <help>ICMP timeout value</help> <valueHelp> <format>u32:0-2147483647</format> - <description>ICMP timeout in seconds (default 300)</description> + <description>ICMP timeout in seconds</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-2147483647" /> + <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>300</defaultValue> </leafNode> <leafNode name="max-active-life"> <properties> <help>Max active timeout value</help> <valueHelp> <format>u32:0-2147483647</format> - <description>Max active timeout in seconds (default 604800)</description> + <description>Max active timeout in seconds</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-2147483647" /> + <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>604800</defaultValue> </leafNode> <leafNode name="tcp-fin"> <properties> <help>TCP finish timeout value</help> <valueHelp> <format>u32:0-2147483647</format> - <description>TCP FIN timeout in seconds (default 300)</description> + <description>TCP FIN timeout in seconds</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-2147483647" /> + <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>300</defaultValue> </leafNode> <leafNode name="tcp-generic"> <properties> <help>TCP generic timeout value</help> <valueHelp> <format>u32:0-2147483647</format> - <description>TCP generic timeout in seconds (default 3600)</description> + <description>TCP generic timeout in seconds</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-2147483647" /> + <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>3600</defaultValue> </leafNode> <leafNode name="tcp-rst"> <properties> <help>TCP reset timeout value</help> <valueHelp> <format>u32:0-2147483647</format> - <description>TCP RST timeout in seconds (default 120)</description> + <description>TCP RST timeout in seconds</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-2147483647" /> + <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>120</defaultValue> </leafNode> <leafNode name="udp"> <properties> <help>UDP timeout value</help> <valueHelp> <format>u32:0-2147483647</format> - <description>UDP timeout in seconds (default 300)</description> + <description>UDP timeout in seconds</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-2147483647" /> + <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>300</defaultValue> </leafNode> </children> </node> @@ -363,17 +371,16 @@ <leafNode name="agent-address"> <properties> <help>sFlow agent IPv4 address</help> - <valueHelp> - <format>auto</format> - <description>auto select sFlow agent-address (default)</description> - </valueHelp> + <completionHelp> + <list>auto</list> + <script>${vyos_completion_dir}/list_local_ips.sh --ipv4</script> + </completionHelp> <valueHelp> <format>ipv4</format> <description>sFlow IPv4 agent address</description> </valueHelp> <constraint> <validator name="ipv4-address"/> - <regex>^auto$</regex> </constraint> </properties> </leafNode> @@ -385,13 +392,13 @@ <description>Sampling rate (1 in N packets)</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-4294967295" /> + <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> </leafNode> <tagNode name="server"> <properties> - <help>Server to export sFlow [REQUIRED]</help> + <help>sFlow destination server</help> <valueHelp> <format>ipv4</format> <description>IPv4 server to export sFlow</description> @@ -411,17 +418,20 @@ <help>sFlow port number</help> <valueHelp> <format>u32:1025-65535</format> - <description>sFlow port number (default 6343)</description> + <description>sFlow port number</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 1025-65535" /> + <validator name="numeric" argument="--range 1025-65535"/> </constraint> </properties> + <defaultValue>6343</defaultValue> </leafNode> </children> </tagNode> + #include <include/source-address-ipv4-ipv6.xml.i> </children> </node> + #include <include/interface/vrf.xml.i> </children> </node> </children> diff --git a/interface-definitions/vrrp.xml.in b/interface-definitions/high-availability.xml.in index 53d79caac..0631acdda 100644 --- a/interface-definitions/vrrp.xml.in +++ b/interface-definitions/high-availability.xml.in @@ -1,13 +1,13 @@ <?xml version="1.0"?> <interfaceDefinition> - <node name="high-availability"> + <node name="high-availability" owner="${vyos_conf_scripts_dir}/high-availability.py"> <properties> + <priority>800</priority> <!-- after all interfaces and conntrack-sync --> <help>High availability settings</help> </properties> <children> - <node name="vrrp" owner="${vyos_conf_scripts_dir}/vrrp.py"> + <node name="vrrp"> <properties> - <priority>800</priority> <!-- after all interfaces and conntrack-sync --> <help>Virtual Router Redundancy Protocol settings</help> </properties> <children> @@ -22,7 +22,7 @@ <help>Advertise interval</help> <valueHelp> <format>u32:1-255</format> - <description>Advertise interval in seconds (default: 1)</description> + <description>Advertise interval in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-255"/> @@ -63,7 +63,7 @@ <description>AH - IPSEC (not recommended)</description> </valueHelp> <constraint> - <regex>^(plaintext-password|ah)$</regex> + <regex>(plaintext-password|ah)</regex> </constraint> <constraintErrorMessage>Authentication type must be plaintext-password or ah</constraintErrorMessage> </properties> @@ -79,7 +79,7 @@ <children> <leafNode name="failure-count"> <properties> - <help>Health check failure count required for transition to fault (default: 3)</help> + <help>Health check failure count required for transition to fault</help> <constraint> <validator name="numeric" argument="--positive" /> </constraint> @@ -88,7 +88,7 @@ </leafNode> <leafNode name="interval"> <properties> - <help>Health check execution interval in seconds (default: 60)</help> + <help>Health check execution interval in seconds</help> <constraint> <validator name="numeric" argument="--positive"/> </constraint> @@ -160,7 +160,7 @@ </leafNode> <leafNode name="priority"> <properties> - <help>Router priority (default: 100)</help> + <help>Router priority</help> <valueHelp> <format>u32:1-255</format> <description>Router priority</description> @@ -177,8 +177,37 @@ <valueless/> </properties> </leafNode> + <node name="track"> + <properties> + <help>Track settings</help> + </properties> + <children> + <leafNode name="exclude-vrrp-interface"> + <properties> + <valueless/> + <help>Disable track state of main interface</help> + </properties> + </leafNode> + <leafNode name="interface"> + <properties> + <help>Interface name state check</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface name</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> + <multi/> + </properties> + </leafNode> + </children> + </node> #include <include/vrrp-transition-script.xml.i> - <leafNode name="address"> + <tagNode name="address"> <properties> <help>Virtual IP address</help> <valueHelp> @@ -193,9 +222,11 @@ <validator name="ipv4-host"/> <validator name="ipv6-host"/> </constraint> - <multi/> </properties> - </leafNode> + <children> + #include <include/generic-interface-broadcast.xml.i> + </children> + </tagNode> <leafNode name="excluded-address"> <properties> <help>Virtual address (If you need additional IPv4 and IPv6 in same group)</help> @@ -252,6 +283,144 @@ </tagNode> </children> </node> + <tagNode name="virtual-server"> + <properties> + <help>Load-balancing virtual server address</help> + </properties> + <children> + <leafNode name="algorithm"> + <properties> + <help>Schedule algorithm (default - least-connection)</help> + <completionHelp> + <list>round-robin weighted-round-robin least-connection weighted-least-connection source-hashing destination-hashing locality-based-least-connection</list> + </completionHelp> + <valueHelp> + <format>round-robin</format> + <description>Round robin</description> + </valueHelp> + <valueHelp> + <format>weighted-round-robin</format> + <description>Weighted round robin</description> + </valueHelp> + <valueHelp> + <format>least-connection</format> + <description>Least connection</description> + </valueHelp> + <valueHelp> + <format>weighted-least-connection</format> + <description>Weighted least connection</description> + </valueHelp> + <valueHelp> + <format>source-hashing</format> + <description>Source hashing</description> + </valueHelp> + <valueHelp> + <format>destination-hashing</format> + <description>Destination hashing</description> + </valueHelp> + <valueHelp> + <format>locality-based-least-connection</format> + <description>Locality-Based least connection</description> + </valueHelp> + <constraint> + <regex>(round-robin|weighted-round-robin|least-connection|weighted-least-connection|source-hashing|destination-hashing|locality-based-least-connection)</regex> + </constraint> + </properties> + <defaultValue>least-connection</defaultValue> + </leafNode> + <leafNode name="delay-loop"> + <properties> + <help>Interval between health-checks (in seconds)</help> + <valueHelp> + <format>u32:1-600</format> + <description>Interval in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-3600"/> + </constraint> + </properties> + <defaultValue>10</defaultValue> + </leafNode> + <leafNode name="forward-method"> + <properties> + <help>Forwarding method</help> + <completionHelp> + <list>direct nat tunnel</list> + </completionHelp> + <valueHelp> + <format>direct</format> + <description>Direct routing</description> + </valueHelp> + <valueHelp> + <format>nat</format> + <description>NAT</description> + </valueHelp> + <valueHelp> + <format>tunnel</format> + <description>Tunneling</description> + </valueHelp> + <constraint> + <regex>(direct|nat|tunnel)</regex> + </constraint> + </properties> + <defaultValue>nat</defaultValue> + </leafNode> + #include <include/port-number.xml.i> + <leafNode name="persistence-timeout"> + <properties> + <help>Timeout for persistent connections</help> + <valueHelp> + <format>u32:1-86400</format> + <description>Timeout for persistent connections</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-86400"/> + </constraint> + </properties> + <defaultValue>300</defaultValue> + </leafNode> + <leafNode name="protocol"> + <properties> + <help>Protocol for port checks</help> + <completionHelp> + <list>tcp udp</list> + </completionHelp> + <valueHelp> + <format>tcp</format> + <description>TCP</description> + </valueHelp> + <valueHelp> + <format>udp</format> + <description>UDP</description> + </valueHelp> + <constraint> + <regex>(tcp|udp)</regex> + </constraint> + </properties> + <defaultValue>tcp</defaultValue> + </leafNode> + <tagNode name="real-server"> + <properties> + <help>Real server address</help> + </properties> + <children> + #include <include/port-number.xml.i> + <leafNode name="connection-timeout"> + <properties> + <help>Server connection timeout</help> + <valueHelp> + <format>u32:1-86400</format> + <description>Connection timeout to remote server</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-86400"/> + </constraint> + </properties> + </leafNode> + </children> + </tagNode> + </children> + </tagNode> </children> </node> </interfaceDefinition> diff --git a/interface-definitions/https.xml.in b/interface-definitions/https.xml.in index f60df7c34..d2c393036 100644 --- a/interface-definitions/https.xml.in +++ b/interface-definitions/https.xml.in @@ -38,7 +38,7 @@ <constraint> <validator name="ipv4-address"/> <validator name="ipv6-address"/> - <regex>\*$</regex> + <regex>\*</regex> </constraint> </properties> </leafNode> @@ -101,6 +101,25 @@ <hidden/> </properties> </leafNode> + <leafNode name="socket"> + <properties> + <help>Run server on Unix domain socket</help> + <valueless/> + </properties> + </leafNode> + <node name="cors"> + <properties> + <help>Set CORS options</help> + </properties> + <children> + <leafNode name="allow-origin"> + <properties> + <help>Allow resource request from origin</help> + <multi/> + </properties> + </leafNode> + </children> + </node> </children> </node> <node name="api-restrict"> @@ -143,6 +162,7 @@ </node> </children> </node> + #include <include/interface/vrf.xml.i> </children> </node> </children> diff --git a/interface-definitions/igmp-proxy.xml.in b/interface-definitions/igmp-proxy.xml.in index 91c912d8b..8e738fa7f 100644 --- a/interface-definitions/igmp-proxy.xml.in +++ b/interface-definitions/igmp-proxy.xml.in @@ -39,7 +39,7 @@ </leafNode> <leafNode name="role"> <properties> - <help>IGMP interface role (default: downstream)</help> + <help>IGMP interface role</help> <completionHelp> <list>upstream downstream disabled</list> </completionHelp> @@ -49,24 +49,24 @@ </valueHelp> <valueHelp> <format>downstream</format> - <description>Downstream interface(s) (default)</description> + <description>Downstream interface(s)</description> </valueHelp> <valueHelp> <format>disabled</format> <description>Disabled interface</description> </valueHelp> <constraint> - <regex>^(upstream|downstream|disabled)$</regex> + <regex>(upstream|downstream|disabled)</regex> </constraint> </properties> <defaultValue>downstream</defaultValue> </leafNode> <leafNode name="threshold"> <properties> - <help>TTL threshold (default: 1)</help> + <help>TTL threshold</help> <valueHelp> <format>u32:1-255</format> - <description>TTL threshold for the interfaces (default: 1)</description> + <description>TTL threshold for the interfaces</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-255"/> diff --git a/interface-definitions/include/accel-ppp/auth-mode.xml.i b/interface-definitions/include/accel-ppp/auth-mode.xml.i index a7711b675..c1a87cfe3 100644 --- a/interface-definitions/include/accel-ppp/auth-mode.xml.i +++ b/interface-definitions/include/accel-ppp/auth-mode.xml.i @@ -11,7 +11,7 @@ <description>Use RADIUS server for user autentication</description> </valueHelp> <constraint> - <regex>^(local|radius)$</regex> + <regex>(local|radius)</regex> </constraint> <completionHelp> <list>local radius</list> diff --git a/interface-definitions/include/accel-ppp/auth-protocols.xml.i b/interface-definitions/include/accel-ppp/auth-protocols.xml.i index 480747f53..d43266152 100644 --- a/interface-definitions/include/accel-ppp/auth-protocols.xml.i +++ b/interface-definitions/include/accel-ppp/auth-protocols.xml.i @@ -22,7 +22,7 @@ <description>Authentication via MS-CHAPv2 (Microsoft Challenge Handshake Authentication Protocol, version 2)</description> </valueHelp> <constraint> - <regex>^(pap|chap|mschap|mschap-v2)$</regex> + <regex>(pap|chap|mschap|mschap-v2)</regex> </constraint> <multi/> </properties> diff --git a/interface-definitions/include/accel-ppp/client-ip-pool-subnet-single.xml.i b/interface-definitions/include/accel-ppp/client-ip-pool-subnet-single.xml.i new file mode 100644 index 000000000..e5918b765 --- /dev/null +++ b/interface-definitions/include/accel-ppp/client-ip-pool-subnet-single.xml.i @@ -0,0 +1,15 @@ +<!-- include start from accel-ppp/client-ip-pool-subnet-single.xml.i --> +<leafNode name="subnet"> + <properties> + <help>Client IP subnet (CIDR notation)</help> + <valueHelp> + <format>ipv4net</format> + <description>IPv4 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ipv4-prefix"/> + </constraint> + <constraintErrorMessage>Not a valid CIDR formatted prefix</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i b/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i index a692f2335..01cf0e040 100644 --- a/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i +++ b/interface-definitions/include/accel-ppp/client-ipv6-pool.xml.i @@ -21,7 +21,7 @@ <help>Prefix length used for individual client</help> <valueHelp> <format>u32:48-128</format> - <description>Client prefix length (default: 64)</description> + <description>Client prefix length</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 48-128"/> diff --git a/interface-definitions/include/accel-ppp/ppp-mppe.xml.i b/interface-definitions/include/accel-ppp/ppp-mppe.xml.i index e8370180b..4c2e84c25 100644 --- a/interface-definitions/include/accel-ppp/ppp-mppe.xml.i +++ b/interface-definitions/include/accel-ppp/ppp-mppe.xml.i @@ -18,7 +18,7 @@ <description>drop all mppe</description> </valueHelp> <constraint> - <regex>^(require|prefer|deny)$</regex> + <regex>(require|prefer|deny)</regex> </constraint> </properties> <defaultValue>prefer</defaultValue> diff --git a/interface-definitions/include/accel-ppp/ppp-options-ipv4.xml.i b/interface-definitions/include/accel-ppp/ppp-options-ipv4.xml.i index 3e065329d..a45390f43 100644 --- a/interface-definitions/include/accel-ppp/ppp-options-ipv4.xml.i +++ b/interface-definitions/include/accel-ppp/ppp-options-ipv4.xml.i @@ -3,7 +3,7 @@ <properties> <help>IPv4 negotiation algorithm</help> <constraint> - <regex>^(deny|allow)$</regex> + <regex>(deny|allow)</regex> </constraint> <constraintErrorMessage>invalid value</constraintErrorMessage> <valueHelp> diff --git a/interface-definitions/include/accel-ppp/ppp-options-ipv6.xml.i b/interface-definitions/include/accel-ppp/ppp-options-ipv6.xml.i index b9fbac5c6..98abc1111 100644 --- a/interface-definitions/include/accel-ppp/ppp-options-ipv6.xml.i +++ b/interface-definitions/include/accel-ppp/ppp-options-ipv6.xml.i @@ -3,7 +3,7 @@ <properties> <help>IPv6 (IPCP6) negotiation algorithm</help> <constraint> - <regex>^(deny|allow|prefer|require)$</regex> + <regex>(deny|allow|prefer|require)</regex> </constraint> <constraintErrorMessage>invalid value</constraintErrorMessage> <valueHelp> diff --git a/interface-definitions/include/accel-ppp/radius-additions-rate-limit.xml.i b/interface-definitions/include/accel-ppp/radius-additions-rate-limit.xml.i index be49fce5a..f44920c3f 100644 --- a/interface-definitions/include/accel-ppp/radius-additions-rate-limit.xml.i +++ b/interface-definitions/include/accel-ppp/radius-additions-rate-limit.xml.i @@ -21,6 +21,20 @@ <valueless /> </properties> </leafNode> + <leafNode name="multiplier"> + <properties> + <help>Shaper multiplier</help> + <valueHelp> + <format><0.001-1000></format> + <description>Shaper multiplier</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0.001-1000 --float"/> + </constraint> + <constraintErrorMessage>Multiplier needs to be between 0.001 and 1000</constraintErrorMessage> + </properties> + <defaultValue>1</defaultValue> + </leafNode> </children> </node> <!-- include end --> diff --git a/interface-definitions/include/accel-ppp/radius-additions.xml.i b/interface-definitions/include/accel-ppp/radius-additions.xml.i index 258ece2b5..441c9dda5 100644 --- a/interface-definitions/include/accel-ppp/radius-additions.xml.i +++ b/interface-definitions/include/accel-ppp/radius-additions.xml.i @@ -21,7 +21,7 @@ <help>Accounting port</help> <valueHelp> <format>u32:1-65535</format> - <description>Numeric IP port (default: 1813)</description> + <description>Numeric IP port</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-65535"/> @@ -62,7 +62,7 @@ </leafNode> <leafNode name="acct-timeout"> <properties> - <help>Timeout for Interim-Update packets, terminate session afterwards (default 3 seconds)</help> + <help>Timeout for Interim-Update packets, terminate session afterwards</help> <valueHelp> <format>u32:0-60</format> <description>Timeout in seconds, 0 to keep active</description> @@ -126,7 +126,7 @@ </leafNode> <leafNode name="port"> <properties> - <help>Port for Dynamic Authorization Extension server (DM/CoA) (default: 1700)</help> + <help>Port for Dynamic Authorization Extension server (DM/CoA)</help> <valueHelp> <format>u32:1-65535</format> <description>TCP port</description> diff --git a/interface-definitions/include/arp-ndp-table-size.xml.i b/interface-definitions/include/arp-ndp-table-size.xml.i new file mode 100644 index 000000000..dec86e91a --- /dev/null +++ b/interface-definitions/include/arp-ndp-table-size.xml.i @@ -0,0 +1,14 @@ +<!-- include start from arp-ndp-table-size.xml.i --> +<leafNode name="table-size"> + <properties> + <help>Maximum number of entries to keep in the cache</help> + <completionHelp> + <list>1024 2048 4096 8192 16384 32768</list> + </completionHelp> + <constraint> + <regex>(1024|2048|4096|8192|16384|32768)</regex> + </constraint> + </properties> + <defaultValue>8192</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/auth-local-users.xml.i b/interface-definitions/include/auth-local-users.xml.i index 8ef09554e..9fb507474 100644 --- a/interface-definitions/include/auth-local-users.xml.i +++ b/interface-definitions/include/auth-local-users.xml.i @@ -7,6 +7,10 @@ <tagNode name="username"> <properties> <help>Username used for authentication</help> + <valueHelp> + <format>txt</format> + <description>Username used for authentication</description> + </valueHelp> </properties> <children> #include <include/generic-disable-node.xml.i> diff --git a/interface-definitions/include/bfd.xml.i b/interface-definitions/include/bfd.xml.i deleted file mode 100644 index 2bc3664e1..000000000 --- a/interface-definitions/include/bfd.xml.i +++ /dev/null @@ -1,8 +0,0 @@ -<!-- include start from bfd.xml.i --> -<leafNode name="bfd"> - <properties> - <help>Enable Bidirectional Forwarding Detection (BFD)</help> - <valueless/> - </properties> -</leafNode> -<!-- include end --> diff --git a/interface-definitions/include/bfd/bfd.xml.i b/interface-definitions/include/bfd/bfd.xml.i new file mode 100644 index 000000000..022956d98 --- /dev/null +++ b/interface-definitions/include/bfd/bfd.xml.i @@ -0,0 +1,10 @@ +<!-- include start from bfd/bfd.xml.i --> +<node name="bfd"> + <properties> + <help>Enable Bidirectional Forwarding Detection (BFD)</help> + </properties> + <children> + #include <include/bfd/profile.xml.i> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/bfd-common.xml.i b/interface-definitions/include/bfd/common.xml.i index 1d6ab5d55..126ab9b9a 100644 --- a/interface-definitions/include/bfd-common.xml.i +++ b/interface-definitions/include/bfd/common.xml.i @@ -1,4 +1,4 @@ -<!-- include start from bfd-common.xml.i --> +<!-- include start from bfd/common.xml.i --> <leafNode name="echo-mode"> <properties> <help>Enables the echo transmission mode</help> @@ -63,6 +63,12 @@ </leafNode> </children> </node> +<leafNode name="passive"> + <properties> + <help>Do not attempt to start sessions</help> + <valueless/> + </properties> +</leafNode> <leafNode name="shutdown"> <properties> <help>Disable this peer</help> diff --git a/interface-definitions/include/bfd/profile.xml.i b/interface-definitions/include/bfd/profile.xml.i new file mode 100644 index 000000000..5ff057286 --- /dev/null +++ b/interface-definitions/include/bfd/profile.xml.i @@ -0,0 +1,14 @@ +<!-- include start from bfd/profile.xml.i --> +<leafNode name="profile"> + <properties> + <help>Use settings from BFD profile</help> + <completionHelp> + <path>protocols bfd profile</path> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>BFD profile name</description> + </valueHelp> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/bgp/afi-ipv4-prefix-list.xml.i b/interface-definitions/include/bgp/afi-ipv4-prefix-list.xml.i index de42eeac9..34b5ec7d7 100644 --- a/interface-definitions/include/bgp/afi-ipv4-prefix-list.xml.i +++ b/interface-definitions/include/bgp/afi-ipv4-prefix-list.xml.i @@ -15,7 +15,7 @@ <description>Name of IPv4 prefix-list</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9]+$</regex> + <regex>[-_a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Name of prefix-list can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> @@ -31,7 +31,7 @@ <description>Name of IPv4 prefix-list</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9]+$</regex> + <regex>[-_a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Name of prefix-list can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> diff --git a/interface-definitions/include/bgp/afi-ipv6-prefix-list.xml.i b/interface-definitions/include/bgp/afi-ipv6-prefix-list.xml.i index 2bf4753be..06c661a90 100644 --- a/interface-definitions/include/bgp/afi-ipv6-prefix-list.xml.i +++ b/interface-definitions/include/bgp/afi-ipv6-prefix-list.xml.i @@ -15,7 +15,7 @@ <description>Name of IPv6 prefix-list</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9]+$</regex> + <regex>[-_a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Name of prefix-list6 can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> @@ -31,7 +31,7 @@ <description>Name of IPv6 prefix-list</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9]+$</regex> + <regex>[-_a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Name of prefix-list6 can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> diff --git a/interface-definitions/include/bgp/afi-l2vpn-common.xml.i b/interface-definitions/include/bgp/afi-l2vpn-common.xml.i index 8deb189ab..d586635c8 100644 --- a/interface-definitions/include/bgp/afi-l2vpn-common.xml.i +++ b/interface-definitions/include/bgp/afi-l2vpn-common.xml.i @@ -25,7 +25,7 @@ <description>Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> </valueHelp> <constraint> - <validator name="bgp-route-target" argument="--single"/> + <validator name="bgp-rd-rt" argument="--route-target"/> </constraint> </properties> </leafNode> @@ -37,7 +37,7 @@ <description>Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> </valueHelp> <constraint> - <validator name="bgp-route-target" argument="--single"/> + <validator name="bgp-rd-rt" argument="--route-target"/> </constraint> </properties> </leafNode> @@ -49,7 +49,7 @@ <description>Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> </valueHelp> <constraint> - <validator name="bgp-route-target" argument="--single"/> + <validator name="bgp-rd-rt" argument="--route-target"/> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/bgp/afi-label.xml.i b/interface-definitions/include/bgp/afi-label.xml.i index f7a1f609f..9535d19e8 100644 --- a/interface-definitions/include/bgp/afi-label.xml.i +++ b/interface-definitions/include/bgp/afi-label.xml.i @@ -25,7 +25,7 @@ </valueHelp> <constraint> <validator name="numeric" argument="--range 0-1048575"/> - <regex>^(auto)$</regex> + <regex>(auto)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/bgp/afi-rd.xml.i b/interface-definitions/include/bgp/afi-rd.xml.i index c4d29268c..767502094 100644 --- a/interface-definitions/include/bgp/afi-rd.xml.i +++ b/interface-definitions/include/bgp/afi-rd.xml.i @@ -17,7 +17,7 @@ <description>Route Distinguisher, (x.x.x.x:yyy|xxxx:yyyy)</description> </valueHelp> <constraint> - <regex>^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$</regex> + <regex>((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/bgp/afi-route-map-export-import.xml.i b/interface-definitions/include/bgp/afi-route-map-export-import.xml.i index eae10d312..c218937c8 100644 --- a/interface-definitions/include/bgp/afi-route-map-export-import.xml.i +++ b/interface-definitions/include/bgp/afi-route-map-export-import.xml.i @@ -10,7 +10,7 @@ <description>Route map name</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9.]+$</regex> + <regex>[-_a-zA-Z0-9.]+</regex> </constraint> <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> @@ -26,7 +26,7 @@ <description>Route map name</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9.]+$</regex> + <regex>[-_a-zA-Z0-9.]+</regex> </constraint> <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> diff --git a/interface-definitions/include/bgp/afi-route-target-vpn.xml.i b/interface-definitions/include/bgp/afi-route-target-vpn.xml.i index 0cd0fdd76..5784f9eac 100644 --- a/interface-definitions/include/bgp/afi-route-target-vpn.xml.i +++ b/interface-definitions/include/bgp/afi-route-target-vpn.xml.i @@ -17,7 +17,7 @@ <description>Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> </valueHelp> <constraint> - <validator name="bgp-route-target" argument="--multi"/> + <validator name="bgp-rd-rt" argument="--route-target-multi"/> </constraint> </properties> </leafNode> @@ -29,7 +29,7 @@ <description>Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> </valueHelp> <constraint> - <validator name="bgp-route-target" argument="--multi"/> + <validator name="bgp-rd-rt" argument="--route-target-multi"/> </constraint> </properties> </leafNode> @@ -41,7 +41,7 @@ <description>Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> </valueHelp> <constraint> - <validator name="bgp-route-target" argument="--multi"/> + <validator name="bgp-rd-rt" argument="--route-target-multi"/> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/bgp/afi-common.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i index 62beff40c..75221a348 100644 --- a/interface-definitions/include/bgp/afi-common.xml.i +++ b/interface-definitions/include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i @@ -1,4 +1,4 @@ -<!-- include start from bgp/afi-common.xml.i --> +<!-- include start from bgp/neighbor-afi-ipv4-ipv6-common.xml.i --> <leafNode name="addpath-tx-all"> <properties> <help>Use addpath to advertise all paths to a neighbor</help> @@ -11,10 +11,65 @@ <valueless/> </properties> </leafNode> +<node name="conditionally-advertise"> + <properties> + <help>Use route-map to conditionally advertise routes</help> + </properties> + <children> + <leafNode name="advertise-map"> + <properties> + <help>Route-map to conditionally advertise routes</help> + <completionHelp> + <path>policy route-map</path> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Route map name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9.]+</regex> + </constraint> + <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="exist-map"> + <properties> + <help>Advertise routes only if prefixes in exist-map are installed in BGP table</help> + <completionHelp> + <path>policy route-map</path> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Route map name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9.]+</regex> + </constraint> + <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="non-exist-map"> + <properties> + <help>Advertise routes only if prefixes in non-exist-map are not installed in BGP table</help> + <completionHelp> + <path>policy route-map</path> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Route map name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9.]+</regex> + </constraint> + <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> + </properties> + </leafNode> + </children> +</node> #include <include/bgp/afi-allowas-in.xml.i> <leafNode name="as-override"> <properties> - <help>AS for routes sent to this peer to be the local AS</help> + <help>Override ASN in outbound updates to configured neighbor local-as</help> <valueless/> </properties> </leafNode> @@ -122,7 +177,7 @@ <description>Route map name</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9.]+$</regex> + <regex>[-_a-zA-Z0-9.]+</regex> </constraint> <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> diff --git a/interface-definitions/include/bgp/neighbor-afi-ipv4-labeled-unicast.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv4-labeled-unicast.xml.i index 45a440fd8..0eae29f5e 100644 --- a/interface-definitions/include/bgp/neighbor-afi-ipv4-labeled-unicast.xml.i +++ b/interface-definitions/include/bgp/neighbor-afi-ipv4-labeled-unicast.xml.i @@ -13,7 +13,7 @@ </children> </node> #include <include/bgp/afi-ipv4-prefix-list.xml.i> - #include <include/bgp/afi-common.xml.i> + #include <include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i> #include <include/bgp/afi-default-originate.xml.i> </children> </node> diff --git a/interface-definitions/include/bgp/neighbor-afi-ipv4-multicast.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv4-multicast.xml.i index 6526169ca..4bb6df7c3 100644 --- a/interface-definitions/include/bgp/neighbor-afi-ipv4-multicast.xml.i +++ b/interface-definitions/include/bgp/neighbor-afi-ipv4-multicast.xml.i @@ -13,7 +13,7 @@ </children> </node> #include <include/bgp/afi-ipv4-prefix-list.xml.i> - #include <include/bgp/afi-common.xml.i> + #include <include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i> #include <include/bgp/afi-default-originate.xml.i> </children> </node> diff --git a/interface-definitions/include/bgp/neighbor-afi-ipv4-unicast.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv4-unicast.xml.i index b7b7ca5b5..0094ce874 100644 --- a/interface-definitions/include/bgp/neighbor-afi-ipv4-unicast.xml.i +++ b/interface-definitions/include/bgp/neighbor-afi-ipv4-unicast.xml.i @@ -13,7 +13,7 @@ </children> </node> #include <include/bgp/afi-ipv4-prefix-list.xml.i> - #include <include/bgp/afi-common.xml.i> + #include <include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i> #include <include/bgp/afi-default-originate.xml.i> </children> </node> diff --git a/interface-definitions/include/bgp/neighbor-afi-ipv4-vpn.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv4-vpn.xml.i index 838327bc9..220f22fe3 100644 --- a/interface-definitions/include/bgp/neighbor-afi-ipv4-vpn.xml.i +++ b/interface-definitions/include/bgp/neighbor-afi-ipv4-vpn.xml.i @@ -5,7 +5,7 @@ </properties> <children> #include <include/bgp/afi-ipv4-prefix-list.xml.i> - #include <include/bgp/afi-common.xml.i> + #include <include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i> </children> </node> <!-- include end --> diff --git a/interface-definitions/include/bgp/neighbor-afi-ipv6-labeled-unicast.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv6-labeled-unicast.xml.i index f680b7357..995183571 100644 --- a/interface-definitions/include/bgp/neighbor-afi-ipv6-labeled-unicast.xml.i +++ b/interface-definitions/include/bgp/neighbor-afi-ipv6-labeled-unicast.xml.i @@ -14,7 +14,7 @@ </node> #include <include/bgp/afi-ipv6-nexthop-local.xml.i> #include <include/bgp/afi-ipv6-prefix-list.xml.i> - #include <include/bgp/afi-common.xml.i> + #include <include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i> #include <include/bgp/afi-default-originate.xml.i> </children> </node> diff --git a/interface-definitions/include/bgp/neighbor-afi-ipv6-multicast.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv6-multicast.xml.i index 1f8db8361..bb713c313 100644 --- a/interface-definitions/include/bgp/neighbor-afi-ipv6-multicast.xml.i +++ b/interface-definitions/include/bgp/neighbor-afi-ipv6-multicast.xml.i @@ -6,7 +6,7 @@ <children> #include <include/bgp/afi-ipv6-nexthop-local.xml.i> #include <include/bgp/afi-ipv6-prefix-list.xml.i> - #include <include/bgp/afi-common.xml.i> + #include <include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i> #include <include/bgp/afi-default-originate.xml.i> </children> </node> diff --git a/interface-definitions/include/bgp/neighbor-afi-ipv6-unicast.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv6-unicast.xml.i index f6b812c28..26a5e7090 100644 --- a/interface-definitions/include/bgp/neighbor-afi-ipv6-unicast.xml.i +++ b/interface-definitions/include/bgp/neighbor-afi-ipv6-unicast.xml.i @@ -14,7 +14,7 @@ </node> #include <include/bgp/afi-ipv6-nexthop-local.xml.i> #include <include/bgp/afi-ipv6-prefix-list.xml.i> - #include <include/bgp/afi-common.xml.i> + #include <include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i> #include <include/bgp/afi-default-originate.xml.i> </children> </node> diff --git a/interface-definitions/include/bgp/neighbor-afi-ipv6-vpn.xml.i b/interface-definitions/include/bgp/neighbor-afi-ipv6-vpn.xml.i index c0df71cf3..5c6811986 100644 --- a/interface-definitions/include/bgp/neighbor-afi-ipv6-vpn.xml.i +++ b/interface-definitions/include/bgp/neighbor-afi-ipv6-vpn.xml.i @@ -6,7 +6,7 @@ <children> #include <include/bgp/afi-ipv6-nexthop-local.xml.i> #include <include/bgp/afi-ipv6-prefix-list.xml.i> - #include <include/bgp/afi-common.xml.i> + #include <include/bgp/neighbor-afi-ipv4-ipv6-common.xml.i> </children> </node> <!-- include end --> diff --git a/interface-definitions/include/bgp/neighbor-bfd.xml.i b/interface-definitions/include/bgp/neighbor-bfd.xml.i index d486bdd8a..fac2a1166 100644 --- a/interface-definitions/include/bgp/neighbor-bfd.xml.i +++ b/interface-definitions/include/bgp/neighbor-bfd.xml.i @@ -4,6 +4,7 @@ <help>Enable Bidirectional Forwarding Detection (BFD) support</help> </properties> <children> + #include <include/bfd/profile.xml.i> <leafNode name="check-control-plane-failure"> <properties> <help>Allow to write CBIT independence in BFD outgoing packets and read both C-BIT value of BFD and lookup BGP peer status</help> diff --git a/interface-definitions/include/bgp/neighbor-graceful-restart.xml.i b/interface-definitions/include/bgp/neighbor-graceful-restart.xml.i index 25558cd5c..4399d7988 100644 --- a/interface-definitions/include/bgp/neighbor-graceful-restart.xml.i +++ b/interface-definitions/include/bgp/neighbor-graceful-restart.xml.i @@ -18,7 +18,7 @@ <description>Enable BGP graceful restart helper only functionality</description> </valueHelp> <constraint> - <regex>^(enable|disable|restart-helper)$</regex> + <regex>(enable|disable|restart-helper)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/bgp/neighbor-shutdown.xml.i b/interface-definitions/include/bgp/neighbor-shutdown.xml.i index 6d15899a6..acc7bc5a9 100644 --- a/interface-definitions/include/bgp/neighbor-shutdown.xml.i +++ b/interface-definitions/include/bgp/neighbor-shutdown.xml.i @@ -1,7 +1,7 @@ <!-- include start from bgp/neighbor-shutdown.xml.i --> <leafNode name="shutdown"> <properties> - <help>Administratively shut down this neighbor</help> + <help>Administratively shutdown this neighbor</help> <valueless/> </properties> </leafNode> diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i index 2dfae517e..abaff5232 100644 --- a/interface-definitions/include/bgp/protocol-common-config.xml.i +++ b/interface-definitions/include/bgp/protocol-common-config.xml.i @@ -1106,7 +1106,7 @@ <description>Ignore paths without link bandwidth for ECMP (if other paths have it)</description> </valueHelp> <constraint> - <regex>^(default-weight-for-missing|ignore|skip-missing)$</regex> + <regex>(default-weight-for-missing|ignore|skip-missing)</regex> </constraint> </properties> </leafNode> @@ -1181,6 +1181,26 @@ </leafNode> </children> </node> + <node name="conditional-advertisement"> + <properties> + <help>Conditional advertisement settings</help> + </properties> + <children> + <leafNode name="timer"> + <properties> + <help>Set period to rescan BGP table to check if condition is met</help> + <valueHelp> + <format>u32:5-240</format> + <description>Period to rerun the conditional advertisement scanner process</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 5-240"/> + </constraint> + </properties> + <defaultValue>60</defaultValue> + </leafNode> + </children> + </node> <node name="dampening"> <properties> <help>Enable route-flap dampening</help> @@ -1343,6 +1363,12 @@ <valueless/> </properties> </leafNode> + <leafNode name="fast-convergence"> + <properties> + <help>Teardown sessions immediately whenever peer becomes unreachable</help> + <valueless/> + </properties> + </leafNode> <node name="graceful-restart"> <properties> <help>Graceful restart capability parameters</help> @@ -1374,6 +1400,18 @@ <valueless/> </properties> </leafNode> + <leafNode name="minimum-holdtime"> + <properties> + <help>BGP minimum holdtime</help> + <valueHelp> + <format>u32:1-65535</format> + <description>Minimum holdtime in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-65535"/> + </constraint> + </properties> + </leafNode> <leafNode name="network-import-check"> <properties> <help>Enable IGP route check for network statements</help> @@ -1392,6 +1430,30 @@ <valueless/> </properties> </leafNode> + <leafNode name="no-suppress-duplicates"> + <properties> + <help>Disable suppress duplicate updates if the route actually not changed</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="reject-as-sets"> + <properties> + <help>Reject routes with AS_SET or AS_CONFED_SET flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="shutdown"> + <properties> + <help>Administrative shutdown of the BGP instance</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="suppress-fib-pending"> + <properties> + <help>Advertise only routes that are programmed in kernel to peers</help> + <valueless/> + </properties> + </leafNode> #include <include/router-id.xml.i> </children> </node> @@ -1399,7 +1461,7 @@ <properties> <help>Name of peer-group</help> <constraint> - <regex>^[-_a-zA-Z0-9]+$</regex> + <regex>[-_a-zA-Z0-9]+</regex> </constraint> </properties> <children> @@ -1441,4 +1503,4 @@ #include <include/bgp/timers-keepalive.xml.i> </children> </node> -<!-- include end -->
\ No newline at end of file +<!-- include end --> diff --git a/interface-definitions/include/bgp/remote-as.xml.i b/interface-definitions/include/bgp/remote-as.xml.i index 11eb7c256..58595b3b9 100644 --- a/interface-definitions/include/bgp/remote-as.xml.i +++ b/interface-definitions/include/bgp/remote-as.xml.i @@ -19,7 +19,7 @@ </valueHelp> <constraint> <validator name="numeric" argument="--range 1-4294967294"/> - <regex>^(external|internal)$</regex> + <regex>(external|internal)</regex> </constraint> <constraintErrorMessage>Invalid AS number</constraintErrorMessage> </properties> diff --git a/interface-definitions/include/bgp/route-distinguisher.xml.i b/interface-definitions/include/bgp/route-distinguisher.xml.i index 6d0aa3ef1..8bc5b452e 100644 --- a/interface-definitions/include/bgp/route-distinguisher.xml.i +++ b/interface-definitions/include/bgp/route-distinguisher.xml.i @@ -7,7 +7,7 @@ <description>Route Distinguisher, (x.x.x.x:yyy|xxxx:yyyy)</description> </valueHelp> <constraint> - <regex>^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$</regex> + <validator name="bgp-rd-rt" argument="--route-distinguisher"/> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/bgp/timers-keepalive.xml.i b/interface-definitions/include/bgp/timers-keepalive.xml.i index b2771e326..b23f96ec8 100644 --- a/interface-definitions/include/bgp/timers-keepalive.xml.i +++ b/interface-definitions/include/bgp/timers-keepalive.xml.i @@ -4,7 +4,7 @@ <help>BGP keepalive interval for this neighbor</help> <valueHelp> <format>u32:1-65535</format> - <description>Keepalive interval in seconds (default 60)</description> + <description>Keepalive interval in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-65535"/> diff --git a/interface-definitions/include/conntrack/log-common.xml.i b/interface-definitions/include/conntrack/log-common.xml.i new file mode 100644 index 000000000..38799f8f4 --- /dev/null +++ b/interface-definitions/include/conntrack/log-common.xml.i @@ -0,0 +1,20 @@ +<!-- include start from conntrack/log-common.xml.i --> +<leafNode name="destroy"> + <properties> + <help>Log connection deletion</help> + <valueless/> + </properties> +</leafNode> +<leafNode name="new"> + <properties> + <help>Log connection creation</help> + <valueless/> + </properties> +</leafNode> +<leafNode name="update"> + <properties> + <help>Log connection updates</help> + <valueless/> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/conntrack/timeout-common-protocols.xml.i b/interface-definitions/include/conntrack/timeout-common-protocols.xml.i new file mode 100644 index 000000000..2676d846e --- /dev/null +++ b/interface-definitions/include/conntrack/timeout-common-protocols.xml.i @@ -0,0 +1,172 @@ +<!-- include start from conntrack/timeout-common-protocols.xml.i --> +<leafNode name="icmp"> + <properties> + <help>ICMP timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>ICMP timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>30</defaultValue> +</leafNode> +<leafNode name="other"> + <properties> + <help>Generic connection timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>Generic connection timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>600</defaultValue> +</leafNode> +<node name="tcp"> + <properties> + <help>TCP connection timeout options</help> + </properties> + <children> + <leafNode name="close-wait"> + <properties> + <help>TCP CLOSE-WAIT timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>TCP CLOSE-WAIT timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>60</defaultValue> + </leafNode> + <leafNode name="close"> + <properties> + <help>TCP CLOSE timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>TCP CLOSE timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>10</defaultValue> + </leafNode> + <leafNode name="established"> + <properties> + <help>TCP ESTABLISHED timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>TCP ESTABLISHED timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>432000</defaultValue> + </leafNode> + <leafNode name="fin-wait"> + <properties> + <help>TCP FIN-WAIT timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>TCP FIN-WAIT timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>120</defaultValue> + </leafNode> + <leafNode name="last-ack"> + <properties> + <help>TCP LAST-ACK timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>TCP LAST-ACK timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>30</defaultValue> + </leafNode> + <leafNode name="syn-recv"> + <properties> + <help>TCP SYN-RECEIVED timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>TCP SYN-RECEIVED timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>60</defaultValue> + </leafNode> + <leafNode name="syn-sent"> + <properties> + <help>TCP SYN-SENT timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>TCP SYN-SENT timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>120</defaultValue> + </leafNode> + <leafNode name="time-wait"> + <properties> + <help>TCP TIME-WAIT timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>TCP TIME-WAIT timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>120</defaultValue> + </leafNode> + </children> +</node> +<node name="udp"> + <properties> + <help>UDP timeout options</help> + </properties> + <children> + <leafNode name="other"> + <properties> + <help>UDP generic timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>UDP generic timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>30</defaultValue> + </leafNode> + <leafNode name="stream"> + <properties> + <help>UDP stream timeout in seconds</help> + <valueHelp> + <format>u32:1-21474836</format> + <description>UDP stream timeout in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-21474836"/> + </constraint> + </properties> + <defaultValue>180</defaultValue> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/dhcp/ntp-server.xml.i b/interface-definitions/include/dhcp/ntp-server.xml.i index 32d8207e5..4d7235aa1 100644 --- a/interface-definitions/include/dhcp/ntp-server.xml.i +++ b/interface-definitions/include/dhcp/ntp-server.xml.i @@ -1,15 +1,15 @@ <!-- include start from dhcp/ntp-server.xml.i --> - <leafNode name="ntp-server"> - <properties> - <help>IP address of NTP server</help> - <valueHelp> - <format>ipv4</format> - <description>NTP server IPv4 address</description> - </valueHelp> - <constraint> - <validator name="ipv4-address"/> - </constraint> - <multi/> - </properties> - </leafNode> +<leafNode name="ntp-server"> + <properties> + <help>IP address of NTP server</help> + <valueHelp> + <format>ipv4</format> + <description>NTP server IPv4 address</description> + </valueHelp> + <constraint> + <validator name="ipv4-address"/> + </constraint> + <multi/> + </properties> +</leafNode> <!-- include end --> diff --git a/interface-definitions/include/dns/time-to-live.xml.i b/interface-definitions/include/dns/time-to-live.xml.i new file mode 100644 index 000000000..5c1a1472d --- /dev/null +++ b/interface-definitions/include/dns/time-to-live.xml.i @@ -0,0 +1,15 @@ +<!-- include start from dns/time-to-live.xml.i --> +<leafNode name="ttl"> + <properties> + <help>Time-to-live (TTL)</help> + <valueHelp> + <format>u32:0-2147483647</format> + <description>TTL in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-2147483647"/> + </constraint> + </properties> + <defaultValue>300</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/firewall/action-accept-drop-reject.xml.i b/interface-definitions/include/firewall/action-accept-drop-reject.xml.i index 9f8baa884..7fd52319a 100644 --- a/interface-definitions/include/firewall/action-accept-drop-reject.xml.i +++ b/interface-definitions/include/firewall/action-accept-drop-reject.xml.i @@ -18,7 +18,7 @@ <description>Action to reject</description> </valueHelp> <constraint> - <regex>^(accept|drop|reject)$</regex> + <regex>(accept|drop|reject)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/firewall/action.xml.i b/interface-definitions/include/firewall/action.xml.i index 230f590cb..0f60e3c38 100644 --- a/interface-definitions/include/firewall/action.xml.i +++ b/interface-definitions/include/firewall/action.xml.i @@ -3,18 +3,22 @@ <properties> <help>Rule action [REQUIRED]</help> <completionHelp> - <list>permit deny</list> + <list>accept reject drop</list> </completionHelp> <valueHelp> - <format>permit</format> - <description>Permit matching entries</description> + <format>accept</format> + <description>Accept matching entries</description> </valueHelp> <valueHelp> - <format>deny</format> - <description>Deny matching entries</description> + <format>reject</format> + <description>Reject matching entries</description> + </valueHelp> + <valueHelp> + <format>drop</format> + <description>Drop matching entries</description> </valueHelp> <constraint> - <regex>^(permit|deny)$</regex> + <regex>(accept|reject|drop)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/firewall/common-rule.xml.i b/interface-definitions/include/firewall/common-rule.xml.i index a59c0b390..2a5137dbf 100644 --- a/interface-definitions/include/firewall/common-rule.xml.i +++ b/interface-definitions/include/firewall/common-rule.xml.i @@ -55,7 +55,7 @@ <help>Maximum number of packets to allow in excess of rate</help> <valueHelp> <format>u32:0-4294967295</format> - <description>burst__change_me</description> + <description>Maximum number of packets to allow in excess of rate</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> @@ -66,11 +66,11 @@ <properties> <help>Maximum average matching rate</help> <valueHelp> - <format>u32:0-4294967295</format> - <description>rate__change_me</description> + <format>txt</format> + <description>integer/unit (Example: 5/minute)</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-4294967295"/> + <regex>\d+/(second|minute|hour|day)</regex> </constraint> </properties> </leafNode> @@ -91,15 +91,42 @@ <description>Disable log</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> </leafNode> +<node name="connection-status"> + <properties> + <help>Connection status</help> + </properties> + <children> + <leafNode name="nat"> + <properties> + <help>NAT connection status</help> + <completionHelp> + <list>destination source</list> + </completionHelp> + <valueHelp> + <format>destination</format> + <description>Match connections that are subject to destination NAT</description> + </valueHelp> + <valueHelp> + <format>source</format> + <description>Match connections that are subject to source NAT</description> + </valueHelp> + <constraint> + <regex>^(destination|source)$</regex> + </constraint> + </properties> + </leafNode> + </children> +</node> <leafNode name="protocol"> <properties> <help>Protocol to match (protocol name, number, or "all")</help> <completionHelp> - <script>cat /etc/protocols | sed -e '/^#.*/d' | awk '{ print $1 }'</script> + <script>${vyos_completion_dir}/list_protocols.sh</script> + <list>all tcp_udp</list> </completionHelp> <valueHelp> <format>all</format> @@ -114,14 +141,17 @@ <description>IP protocol number</description> </valueHelp> <valueHelp> + <format><protocol></format> + <description>IP protocol name</description> + </valueHelp> + <valueHelp> <format>!<protocol></format> - <description>IP protocol number</description> + <description>IP protocol name</description> </valueHelp> <constraint> <validator name="ip-protocol"/> </constraint> </properties> - <defaultValue>all</defaultValue> </leafNode> <node name="recent"> <properties> @@ -142,13 +172,24 @@ </leafNode> <leafNode name="time"> <properties> - <help>Source addresses seen in the last N seconds</help> + <help>Source addresses seen in the last second/minute/hour</help> + <completionHelp> + <list>second minute hour</list> + </completionHelp> <valueHelp> - <format>u32:0-4294967295</format> - <description>Source addresses seen in the last N seconds</description> + <format>second</format> + <description>Source addresses seen COUNT times in the last second</description> + </valueHelp> + <valueHelp> + <format>minute</format> + <description>Source addresses seen COUNT times in the last minute</description> + </valueHelp> + <valueHelp> + <format>hour</format> + <description>Source addresses seen COUNT times in the last hour</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 0-4294967295"/> + <regex>(second|minute|hour)</regex> </constraint> </properties> </leafNode> @@ -172,6 +213,9 @@ <format>!<MAC address></format> <description>Match everything except the specified MAC address</description> </valueHelp> + <constraint> + <validator name="mac-address-firewall"/> + </constraint> </properties> </leafNode> #include <include/firewall/port.xml.i> @@ -197,7 +241,7 @@ <description>Disable</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> </leafNode> @@ -216,7 +260,7 @@ <description>Disable</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> </leafNode> @@ -235,7 +279,7 @@ <description>Disable</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> </leafNode> @@ -254,71 +298,77 @@ <description>Disable</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> </leafNode> </children> </node> -<node name="tcp"> - <properties> - <help>TCP flags to match</help> - </properties> - <children> - <leafNode name="flags"> - <properties> - <help>TCP flags to match</help> - <valueHelp> - <format>txt</format> - <description>TCP flags to match</description> - </valueHelp> - <valueHelp> - <format> </format> - <description>\n\n Allowed values for TCP flags : SYN ACK FIN RST URG PSH ALL\n When specifying more than one flag, flags should be comma-separated.\n For example : value of 'SYN,!ACK,!FIN,!RST' will only match packets with\n the SYN flag set, and the ACK, FIN and RST flags unset</description> - </valueHelp> - </properties> - </leafNode> - </children> -</node> +#include <include/firewall/tcp-flags.xml.i> <node name="time"> <properties> <help>Time to match rule</help> </properties> <children> - <leafNode name="monthdays"> - <properties> - <help>Monthdays to match rule on</help> - </properties> - </leafNode> <leafNode name="startdate"> <properties> <help>Date to start matching rule</help> + <valueHelp> + <format>txt</format> + <description>Enter date using following notation - YYYY-MM-DD</description> + </valueHelp> + <constraint> + <regex>(\d{4}\-\d{2}\-\d{2})</regex> + </constraint> </properties> </leafNode> <leafNode name="starttime"> <properties> <help>Time of day to start matching rule</help> + <valueHelp> + <format>txt</format> + <description>Enter time using using 24 hour notation - hh:mm:ss</description> + </valueHelp> + <constraint> + <regex>([0-2][0-9](\:[0-5][0-9]){1,2})</regex> + </constraint> </properties> </leafNode> <leafNode name="stopdate"> <properties> <help>Date to stop matching rule</help> + <valueHelp> + <format>txt</format> + <description>Enter date using following notation - YYYY-MM-DD</description> + </valueHelp> + <constraint> + <regex>(\d{4}\-\d{2}\-\d{2})</regex> + </constraint> </properties> </leafNode> <leafNode name="stoptime"> <properties> <help>Time of day to stop matching rule</help> - </properties> - </leafNode> - <leafNode name="utc"> - <properties> - <help>Interpret times for startdate, stopdate, starttime and stoptime to be UTC</help> - <valueless/> + <valueHelp> + <format>txt</format> + <description>Enter time using using 24 hour notation - hh:mm:ss</description> + </valueHelp> + <constraint> + <regex>([0-2][0-9](\:[0-5][0-9]){1,2})</regex> + </constraint> </properties> </leafNode> <leafNode name="weekdays"> <properties> - <help>Weekdays to match rule on</help> + <help>Comma separated weekdays to match rule on</help> + <valueHelp> + <format>txt</format> + <description>Name of day (Monday, Tuesday, Wednesday, Thursdays, Friday, Saturday, Sunday)</description> + </valueHelp> + <valueHelp> + <format>u32:0-6</format> + <description>Day number (0 = Sunday ... 6 = Saturday)</description> + </valueHelp> </properties> </leafNode> </children> diff --git a/interface-definitions/include/firewall/icmp-type-name.xml.i b/interface-definitions/include/firewall/icmp-type-name.xml.i index b45fb619b..d4197cf82 100644 --- a/interface-definitions/include/firewall/icmp-type-name.xml.i +++ b/interface-definitions/include/firewall/icmp-type-name.xml.i @@ -3,170 +3,70 @@ <properties> <help>ICMP type-name</help> <completionHelp> - <list>any echo-reply pong destination-unreachable network-unreachable host-unreachable protocol-unreachable port-unreachable fragmentation-needed source-route-failed network-unknown host-unknown network-prohibited host-prohibited TOS-network-unreachable TOS-host-unreachable communication-prohibited host-precedence-violation precedence-cutoff source-quench redirect network-redirect host-redirect TOS-network-redirect TOS host-redirect echo-request ping router-advertisement router-solicitation time-exceeded ttl-exceeded ttl-zero-during-transit ttl-zero-during-reassembly parameter-problem ip-header-bad required-option-missing timestamp-request timestamp-reply address-mask-request address-mask-reply</list> + <list>echo-reply destination-unreachable source-quench redirect echo-request router-advertisement router-solicitation time-exceeded parameter-problem timestamp-request timestamp-reply info-request info-reply address-mask-request address-mask-reply</list> </completionHelp> <valueHelp> - <format>any</format> - <description>Any ICMP type/code</description> - </valueHelp> - <valueHelp> <format>echo-reply</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>pong</format> - <description>ICMP type/code name</description> + <description>ICMP type 0: echo-reply</description> </valueHelp> <valueHelp> <format>destination-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>protocol-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>port-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>fragmentation-needed</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>source-route-failed</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-unknown</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-unknown</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-prohibited</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-prohibited</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS-network-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS-host-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>communication-prohibited</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-precedence-violation</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>precedence-cutoff</format> - <description>ICMP type/code name</description> + <description>ICMP type 3: destination-unreachable</description> </valueHelp> <valueHelp> <format>source-quench</format> - <description>ICMP type/code name</description> + <description>ICMP type 4: source-quench</description> </valueHelp> <valueHelp> <format>redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS-network-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS host-redirect</format> - <description>ICMP type/code name</description> + <description>ICMP type 5: redirect</description> </valueHelp> <valueHelp> <format>echo-request</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ping</format> - <description>ICMP type/code name</description> + <description>ICMP type 8: echo-request</description> </valueHelp> <valueHelp> <format>router-advertisement</format> - <description>ICMP type/code name</description> + <description>ICMP type 9: router-advertisement</description> </valueHelp> <valueHelp> <format>router-solicitation</format> - <description>ICMP type/code name</description> + <description>ICMP type 10: router-solicitation</description> </valueHelp> <valueHelp> <format>time-exceeded</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ttl-exceeded</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ttl-zero-during-transit</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ttl-zero-during-reassembly</format> - <description>ICMP type/code name</description> + <description>ICMP type 11: time-exceeded</description> </valueHelp> <valueHelp> <format>parameter-problem</format> - <description>ICMP type/code name</description> + <description>ICMP type 12: parameter-problem</description> </valueHelp> <valueHelp> - <format>ip-header-bad</format> - <description>ICMP type/code name</description> + <format>timestamp-request</format> + <description>ICMP type 13: timestamp-request</description> </valueHelp> <valueHelp> - <format>required-option-missing</format> - <description>ICMP type/code name</description> + <format>timestamp-reply</format> + <description>ICMP type 14: timestamp-reply</description> </valueHelp> <valueHelp> - <format>timestamp-request</format> - <description>ICMP type/code name</description> + <format>info-request</format> + <description>ICMP type 15: info-request</description> </valueHelp> <valueHelp> - <format>timestamp-reply</format> - <description>ICMP type/code name</description> + <format>info-reply</format> + <description>ICMP type 16: info-reply</description> </valueHelp> <valueHelp> <format>address-mask-request</format> - <description>ICMP type/code name</description> + <description>ICMP type 17: address-mask-request</description> </valueHelp> <valueHelp> <format>address-mask-reply</format> - <description>ICMP type/code name</description> + <description>ICMP type 18: address-mask-reply</description> </valueHelp> <constraint> - <regex>^(any|echo-reply|pong|destination-unreachable|network-unreachable|host-unreachable|protocol-unreachable|port-unreachable|fragmentation-needed|source-route-failed|network-unknown|host-unknown|network-prohibited|host-prohibited|TOS-network-unreachable|TOS-host-unreachable|communication-prohibited|host-precedence-violation|precedence-cutoff|source-quench|redirect|network-redirect|host-redirect|TOS-network-redirect|TOS host-redirect|echo-request|ping|router-advertisement|router-solicitation|time-exceeded|ttl-exceeded|ttl-zero-during-transit|ttl-zero-during-reassembly|parameter-problem|ip-header-bad|required-option-missing|timestamp-request|timestamp-reply|address-mask-request|address-mask-reply)$</regex> + <regex>(echo-reply|destination-unreachable|source-quench|redirect|echo-request|router-advertisement|router-solicitation|time-exceeded|parameter-problem|timestamp-request|timestamp-reply|info-request|info-reply|address-mask-request|address-mask-reply)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/firewall/icmpv6-type-name.xml.i b/interface-definitions/include/firewall/icmpv6-type-name.xml.i new file mode 100644 index 000000000..a2e68abfb --- /dev/null +++ b/interface-definitions/include/firewall/icmpv6-type-name.xml.i @@ -0,0 +1,73 @@ +<!-- include start from firewall/icmpv6-type-name.xml.i --> +<leafNode name="type-name"> + <properties> + <help>ICMPv6 type-name</help> + <completionHelp> + <list>destination-unreachable packet-too-big time-exceeded echo-request echo-reply mld-listener-query mld-listener-report mld-listener-reduction nd-router-solicit nd-router-advert nd-neighbor-solicit nd-neighbor-advert nd-redirect parameter-problem router-renumbering</list> + </completionHelp> + <valueHelp> + <format>destination-unreachable</format> + <description>ICMPv6 type 1: destination-unreachable</description> + </valueHelp> + <valueHelp> + <format>packet-too-big</format> + <description>ICMPv6 type 2: packet-too-big</description> + </valueHelp> + <valueHelp> + <format>time-exceeded</format> + <description>ICMPv6 type 3: time-exceeded</description> + </valueHelp> + <valueHelp> + <format>echo-request</format> + <description>ICMPv6 type 128: echo-request</description> + </valueHelp> + <valueHelp> + <format>echo-reply</format> + <description>ICMPv6 type 129: echo-reply</description> + </valueHelp> + <valueHelp> + <format>mld-listener-query</format> + <description>ICMPv6 type 130: mld-listener-query</description> + </valueHelp> + <valueHelp> + <format>mld-listener-report</format> + <description>ICMPv6 type 131: mld-listener-report</description> + </valueHelp> + <valueHelp> + <format>mld-listener-reduction</format> + <description>ICMPv6 type 132: mld-listener-reduction</description> + </valueHelp> + <valueHelp> + <format>nd-router-solicit</format> + <description>ICMPv6 type 133: nd-router-solicit</description> + </valueHelp> + <valueHelp> + <format>nd-router-advert</format> + <description>ICMPv6 type 134: nd-router-advert</description> + </valueHelp> + <valueHelp> + <format>nd-neighbor-solicit</format> + <description>ICMPv6 type 135: nd-neighbor-solicit</description> + </valueHelp> + <valueHelp> + <format>nd-neighbor-advert</format> + <description>ICMPv6 type 136: nd-neighbor-advert</description> + </valueHelp> + <valueHelp> + <format>nd-redirect</format> + <description>ICMPv6 type 137: nd-redirect</description> + </valueHelp> + <valueHelp> + <format>parameter-problem</format> + <description>ICMPv6 type 4: parameter-problem</description> + </valueHelp> + <valueHelp> + <format>router-renumbering</format> + <description>ICMPv6 type 138: router-renumbering</description> + </valueHelp> + <constraint> + <regex>(destination-unreachable|packet-too-big|time-exceeded|echo-request|echo-reply|mld-listener-query|mld-listener-report|mld-listener-reduction|nd-router-solicit|nd-router-advert|nd-neighbor-solicit|nd-neighbor-advert|nd-redirect|parameter-problem|router-renumbering)</regex> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/firewall/mac-group.xml.i b/interface-definitions/include/firewall/mac-group.xml.i new file mode 100644 index 000000000..dbce3fc88 --- /dev/null +++ b/interface-definitions/include/firewall/mac-group.xml.i @@ -0,0 +1,10 @@ +<!-- include start from firewall/mac-group.xml.i --> +<leafNode name="mac-group"> + <properties> + <help>Group of MAC addresses</help> + <completionHelp> + <path>firewall group mac-group</path> + </completionHelp> + </properties> +</leafNode> +<!-- include start from firewall/mac-group.xml.i -->
\ No newline at end of file diff --git a/interface-definitions/include/firewall/name-default-action.xml.i b/interface-definitions/include/firewall/name-default-action.xml.i index 1b61b076f..512b0296f 100644 --- a/interface-definitions/include/firewall/name-default-action.xml.i +++ b/interface-definitions/include/firewall/name-default-action.xml.i @@ -7,7 +7,7 @@ </completionHelp> <valueHelp> <format>drop</format> - <description>Drop if no prior rules are hit (default)</description> + <description>Drop if no prior rules are hit</description> </valueHelp> <valueHelp> <format>reject</format> @@ -18,7 +18,7 @@ <description>Accept if no prior rules are hit</description> </valueHelp> <constraint> - <regex>^(drop|reject|accept)$</regex> + <regex>(drop|reject|accept)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/firewall/port.xml.i b/interface-definitions/include/firewall/port.xml.i index 59d92978b..3bacafff8 100644 --- a/interface-definitions/include/firewall/port.xml.i +++ b/interface-definitions/include/firewall/port.xml.i @@ -16,8 +16,11 @@ </valueHelp> <valueHelp> <format> </format> - <description>\n\n Multiple destination ports can be specified as a comma-separated list.\n The whole list can also be negated using '!'.\n For example: '!22,telnet,http,123,1001-1005'</description> + <description>\n\n Multiple destination ports can be specified as a comma-separated list.\n For example: 'telnet,http,123,1001-1005'</description> </valueHelp> + <constraint> + <validator name="port-multi"/> + </constraint> </properties> </leafNode> <!-- include end --> diff --git a/interface-definitions/include/firewall/source-destination-group-ipv6.xml.i b/interface-definitions/include/firewall/source-destination-group-ipv6.xml.i new file mode 100644 index 000000000..c2cc7edb3 --- /dev/null +++ b/interface-definitions/include/firewall/source-destination-group-ipv6.xml.i @@ -0,0 +1,34 @@ +<!-- include start from firewall/source-destination-group-ipv6.xml.i --> +<node name="group"> + <properties> + <help>Group</help> + </properties> + <children> + <leafNode name="address-group"> + <properties> + <help>Group of addresses</help> + <completionHelp> + <path>firewall group ipv6-address-group</path> + </completionHelp> + </properties> + </leafNode> + #include <include/firewall/mac-group.xml.i> + <leafNode name="network-group"> + <properties> + <help>Group of networks</help> + <completionHelp> + <path>firewall group ipv6-network-group</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="port-group"> + <properties> + <help>Group of ports</help> + <completionHelp> + <path>firewall group port-group</path> + </completionHelp> + </properties> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/firewall/source-destination-group.xml.i b/interface-definitions/include/firewall/source-destination-group.xml.i index 30226b0d8..ab11e89e9 100644 --- a/interface-definitions/include/firewall/source-destination-group.xml.i +++ b/interface-definitions/include/firewall/source-destination-group.xml.i @@ -7,16 +7,26 @@ <leafNode name="address-group"> <properties> <help>Group of addresses</help> + <completionHelp> + <path>firewall group address-group</path> + </completionHelp> </properties> </leafNode> + #include <include/firewall/mac-group.xml.i> <leafNode name="network-group"> <properties> <help>Group of networks</help> + <completionHelp> + <path>firewall group network-group</path> + </completionHelp> </properties> </leafNode> <leafNode name="port-group"> <properties> <help>Group of ports</help> + <completionHelp> + <path>firewall group port-group</path> + </completionHelp> </properties> </leafNode> </children> diff --git a/interface-definitions/include/firewall/tcp-flags.xml.i b/interface-definitions/include/firewall/tcp-flags.xml.i new file mode 100644 index 000000000..b99896687 --- /dev/null +++ b/interface-definitions/include/firewall/tcp-flags.xml.i @@ -0,0 +1,119 @@ +<!-- include start from firewall/tcp-flags.xml.i --> +<node name="tcp"> + <properties> + <help>TCP flags to match</help> + </properties> + <children> + <node name="flags"> + <properties> + <help>TCP flags to match</help> + </properties> + <children> + <leafNode name="syn"> + <properties> + <help>Synchronise flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="ack"> + <properties> + <help>Acknowledge flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="fin"> + <properties> + <help>Finish flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="rst"> + <properties> + <help>Reset flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="urg"> + <properties> + <help>Urgent flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="psh"> + <properties> + <help>Push flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="ecn"> + <properties> + <help>Explicit Congestion Notification flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="cwr"> + <properties> + <help>Congestion Window Reduced flag</help> + <valueless/> + </properties> + </leafNode> + <node name="not"> + <properties> + <help>Match flags not set</help> + </properties> + <children> + <leafNode name="syn"> + <properties> + <help>Synchronise flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="ack"> + <properties> + <help>Acknowledge flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="fin"> + <properties> + <help>Finish flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="rst"> + <properties> + <help>Reset flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="urg"> + <properties> + <help>Urgent flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="psh"> + <properties> + <help>Push flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="ecn"> + <properties> + <help>Explicit Congestion Notification flag</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="cwr"> + <properties> + <help>Congestion Window Reduced flag</help> + <valueless/> + </properties> + </leafNode> + </children> + </node> + </children> + </node> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/generic-disable-node.xml.i b/interface-definitions/include/generic-disable-node.xml.i index bb4fa5c4b..97a328ecc 100644 --- a/interface-definitions/include/generic-disable-node.xml.i +++ b/interface-definitions/include/generic-disable-node.xml.i @@ -1,7 +1,7 @@ <!-- include start from generic-disable-node.xml.i --> <leafNode name="disable"> <properties> - <help>Temporary disable</help> + <help>Disable instance</help> <valueless/> </properties> </leafNode> diff --git a/interface-definitions/include/interface/address-ipv4-ipv6-dhcp.xml.i b/interface-definitions/include/interface/address-ipv4-ipv6-dhcp.xml.i index 123590c08..b9dd59bea 100644 --- a/interface-definitions/include/interface/address-ipv4-ipv6-dhcp.xml.i +++ b/interface-definitions/include/interface/address-ipv4-ipv6-dhcp.xml.i @@ -23,7 +23,7 @@ </valueHelp> <constraint> <validator name="ip-host"/> - <regex>^(dhcp|dhcpv6)$</regex> + <regex>(dhcp|dhcpv6)</regex> </constraint> <multi/> </properties> diff --git a/interface-definitions/include/interface/adjust-mss.xml.i b/interface-definitions/include/interface/adjust-mss.xml.i index 57019f02c..41140ffe1 100644 --- a/interface-definitions/include/interface/adjust-mss.xml.i +++ b/interface-definitions/include/interface/adjust-mss.xml.i @@ -16,7 +16,7 @@ </valueHelp> <constraint> <validator name="numeric" argument="--range 500-65535"/> - <regex>^(clamp-mss-to-pmtu)$</regex> + <regex>(clamp-mss-to-pmtu)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/interface/arp-cache-timeout.xml.i b/interface-definitions/include/interface/arp-cache-timeout.xml.i index cb01d0525..06d7ffe96 100644 --- a/interface-definitions/include/interface/arp-cache-timeout.xml.i +++ b/interface-definitions/include/interface/arp-cache-timeout.xml.i @@ -4,7 +4,7 @@ <help>ARP cache entry timeout in seconds</help> <valueHelp> <format>u32:1-86400</format> - <description>ARP cache entry timout in seconds (default 30)</description> + <description>ARP cache entry timout in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-86400"/> diff --git a/interface-definitions/include/interface/default-route-distance.xml.i b/interface-definitions/include/interface/default-route-distance.xml.i new file mode 100644 index 000000000..6eda52c91 --- /dev/null +++ b/interface-definitions/include/interface/default-route-distance.xml.i @@ -0,0 +1,15 @@ +<!-- include start from interface/default-route-distance.xml.i --> +<leafNode name="default-route-distance"> + <properties> + <help>Distance for installed default route</help> + <valueHelp> + <format>u32:1-255</format> + <description>Distance for the default route from DHCP server</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-255"/> + </constraint> + </properties> + <defaultValue>210</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/interface/description.xml.i b/interface-definitions/include/interface/description.xml.i index 8579cf7d1..de01d22ca 100644 --- a/interface-definitions/include/interface/description.xml.i +++ b/interface-definitions/include/interface/description.xml.i @@ -3,7 +3,7 @@ <properties> <help>Interface specific description</help> <constraint> - <regex>.{1,256}$</regex> + <regex>.{1,256}</regex> </constraint> <constraintErrorMessage>Description too long (limit 256 characters)</constraintErrorMessage> </properties> diff --git a/interface-definitions/include/interface/dhcp-options.xml.i b/interface-definitions/include/interface/dhcp-options.xml.i index b65b0802a..914b60503 100644 --- a/interface-definitions/include/interface/dhcp-options.xml.i +++ b/interface-definitions/include/interface/dhcp-options.xml.i @@ -19,24 +19,8 @@ <help>Identify the vendor client type to the DHCP server</help> </properties> </leafNode> - <leafNode name="no-default-route"> - <properties> - <help>Do not request routers from DHCP server</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="default-route-distance"> - <properties> - <help>Distance for the default route from DHCP server</help> - <valueHelp> - <format>u32:1-255</format> - <description>Distance for the default route from DHCP server (default 210)</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-255"/> - </constraint> - </properties> - </leafNode> + #include <include/interface/no-default-route.xml.i> + #include <include/interface/default-route-distance.xml.i> <leafNode name="reject"> <properties> <help>IP addresses or subnets from which to reject DHCP leases</help> diff --git a/interface-definitions/include/interface/dhcpv6-options.xml.i b/interface-definitions/include/interface/dhcpv6-options.xml.i index d1abf4a90..08e4f5e0a 100644 --- a/interface-definitions/include/interface/dhcpv6-options.xml.i +++ b/interface-definitions/include/interface/dhcpv6-options.xml.i @@ -57,10 +57,10 @@ <children> <leafNode name="address"> <properties> - <help>Local interface address assigned to interface</help> + <help>Local interface address assigned to interface (default: EUI-64)</help> <valueHelp> <format>>0</format> - <description>Used to form IPv6 interface address (default: EUI-64)</description> + <description>Used to form IPv6 interface address</description> </valueHelp> <constraint> <validator name="numeric" argument="--non-negative"/> diff --git a/interface-definitions/include/interface/inbound-interface.xml.i b/interface-definitions/include/interface/inbound-interface.xml.i new file mode 100644 index 000000000..5a8d47280 --- /dev/null +++ b/interface-definitions/include/interface/inbound-interface.xml.i @@ -0,0 +1,10 @@ +<!-- include start from interface/inbound-interface.xml.i --> +<leafNode name="inbound-interface"> + <properties> + <help>Inbound Interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/interface/interface-firewall-vif-c.xml.i b/interface-definitions/include/interface/interface-firewall-vif-c.xml.i new file mode 100644 index 000000000..1bc235fcb --- /dev/null +++ b/interface-definitions/include/interface/interface-firewall-vif-c.xml.i @@ -0,0 +1,79 @@ +<!-- include start from interface/interface-firewall-vif-c.xml.i --> +<node name="firewall" owner="${vyos_conf_scripts_dir}/firewall-interface.py $VAR(../../../@).$VAR(../../@).$VAR(../@)"> + <properties> + <priority>615</priority> + <help>Firewall options</help> + </properties> + <children> + <node name="in"> + <properties> + <help>forwarded packets on inbound interface</help> + </properties> + <children> + <leafNode name="name"> + <properties> + <help>Inbound IPv4 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="ipv6-name"> + <properties> + <help>Inbound IPv6 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + <node name="out"> + <properties> + <help>forwarded packets on outbound interface</help> + </properties> + <children> + <leafNode name="name"> + <properties> + <help>Outbound IPv4 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="ipv6-name"> + <properties> + <help>Outbound IPv6 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + <node name="local"> + <properties> + <help>packets destined for this router</help> + </properties> + <children> + <leafNode name="name"> + <properties> + <help>Local IPv4 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="ipv6-name"> + <properties> + <help>Local IPv6 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/interface/interface-firewall-vif.xml.i b/interface-definitions/include/interface/interface-firewall-vif.xml.i new file mode 100644 index 000000000..a37ac5c4a --- /dev/null +++ b/interface-definitions/include/interface/interface-firewall-vif.xml.i @@ -0,0 +1,79 @@ +<!-- include start from interface/interface-firewall-vif.xml.i --> +<node name="firewall" owner="${vyos_conf_scripts_dir}/firewall-interface.py $VAR(../../@).$VAR(../@)"> + <properties> + <priority>615</priority> + <help>Firewall options</help> + </properties> + <children> + <node name="in"> + <properties> + <help>forwarded packets on inbound interface</help> + </properties> + <children> + <leafNode name="name"> + <properties> + <help>Inbound IPv4 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="ipv6-name"> + <properties> + <help>Inbound IPv6 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + <node name="out"> + <properties> + <help>forwarded packets on outbound interface</help> + </properties> + <children> + <leafNode name="name"> + <properties> + <help>Outbound IPv4 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="ipv6-name"> + <properties> + <help>Outbound IPv6 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + <node name="local"> + <properties> + <help>packets destined for this router</help> + </properties> + <children> + <leafNode name="name"> + <properties> + <help>Local IPv4 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="ipv6-name"> + <properties> + <help>Local IPv6 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/interface/interface-firewall.xml.i b/interface-definitions/include/interface/interface-firewall.xml.i new file mode 100644 index 000000000..b3f20c3bf --- /dev/null +++ b/interface-definitions/include/interface/interface-firewall.xml.i @@ -0,0 +1,79 @@ +<!-- include start from interface/interface-firewall.xml.i --> +<node name="firewall" owner="${vyos_conf_scripts_dir}/firewall-interface.py $VAR(../@)"> + <properties> + <priority>615</priority> + <help>Firewall options</help> + </properties> + <children> + <node name="in"> + <properties> + <help>forwarded packets on inbound interface</help> + </properties> + <children> + <leafNode name="name"> + <properties> + <help>Inbound IPv4 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="ipv6-name"> + <properties> + <help>Inbound IPv6 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + <node name="out"> + <properties> + <help>forwarded packets on outbound interface</help> + </properties> + <children> + <leafNode name="name"> + <properties> + <help>Outbound IPv4 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="ipv6-name"> + <properties> + <help>Outbound IPv6 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + <node name="local"> + <properties> + <help>packets destined for this router</help> + </properties> + <children> + <leafNode name="name"> + <properties> + <help>Local IPv4 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="ipv6-name"> + <properties> + <help>Local IPv6 firewall ruleset name for interface</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/interface/interface-policy-vif-c.xml.i b/interface-definitions/include/interface/interface-policy-vif-c.xml.i new file mode 100644 index 000000000..866fcd5c0 --- /dev/null +++ b/interface-definitions/include/interface/interface-policy-vif-c.xml.i @@ -0,0 +1,26 @@ +<!-- include start from interface/interface-policy-vif-c.xml.i --> +<node name="policy" owner="${vyos_conf_scripts_dir}/policy-route-interface.py $VAR(../../../@).$VAR(../../@).$VAR(../@)"> + <properties> + <priority>620</priority> + <help>Policy route options</help> + </properties> + <children> + <leafNode name="route"> + <properties> + <help>IPv4 policy route ruleset for interface</help> + <completionHelp> + <path>policy route</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="route6"> + <properties> + <help>IPv6 policy route ruleset for interface</help> + <completionHelp> + <path>policy route6</path> + </completionHelp> + </properties> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/interface/interface-policy-vif.xml.i b/interface-definitions/include/interface/interface-policy-vif.xml.i new file mode 100644 index 000000000..83510fe59 --- /dev/null +++ b/interface-definitions/include/interface/interface-policy-vif.xml.i @@ -0,0 +1,26 @@ +<!-- include start from interface/interface-policy-vif.xml.i --> +<node name="policy" owner="${vyos_conf_scripts_dir}/policy-route-interface.py $VAR(../../@).$VAR(../@)"> + <properties> + <priority>620</priority> + <help>Policy route options</help> + </properties> + <children> + <leafNode name="route"> + <properties> + <help>IPv4 policy route ruleset for interface</help> + <completionHelp> + <path>policy route</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="route6"> + <properties> + <help>IPv6 policy route ruleset for interface</help> + <completionHelp> + <path>policy route6</path> + </completionHelp> + </properties> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/interface/interface-policy.xml.i b/interface-definitions/include/interface/interface-policy.xml.i new file mode 100644 index 000000000..42a8fd009 --- /dev/null +++ b/interface-definitions/include/interface/interface-policy.xml.i @@ -0,0 +1,26 @@ +<!-- include start from interface/interface-policy.xml.i --> +<node name="policy" owner="${vyos_conf_scripts_dir}/policy-route-interface.py $VAR(../@)"> + <properties> + <priority>620</priority> + <help>Policy route options</help> + </properties> + <children> + <leafNode name="route"> + <properties> + <help>IPv4 policy route ruleset for interface</help> + <completionHelp> + <path>policy route</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="route6"> + <properties> + <help>IPv6 policy route ruleset for interface</help> + <completionHelp> + <path>policy route6</path> + </completionHelp> + </properties> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/interface/netns.xml.i b/interface-definitions/include/interface/netns.xml.i new file mode 100644 index 000000000..39f9118fa --- /dev/null +++ b/interface-definitions/include/interface/netns.xml.i @@ -0,0 +1,14 @@ +<!-- include start from interface/netns.xml.i --> +<leafNode name="netns"> + <properties> + <help>Network namespace name</help> + <valueHelp> + <format>text</format> + <description>Network namespace name</description> + </valueHelp> + <completionHelp> + <path>netns name</path> + </completionHelp> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/interface/no-default-route.xml.i b/interface-definitions/include/interface/no-default-route.xml.i new file mode 100644 index 000000000..307fcff1e --- /dev/null +++ b/interface-definitions/include/interface/no-default-route.xml.i @@ -0,0 +1,8 @@ +<!-- include start from interface/dhcp-options.xml.i --> +<leafNode name="no-default-route"> + <properties> + <help>Do not install default route to system</help> + <valueless/> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/interface/parameters-df.xml.i b/interface-definitions/include/interface/parameters-df.xml.i new file mode 100644 index 000000000..82436b5e4 --- /dev/null +++ b/interface-definitions/include/interface/parameters-df.xml.i @@ -0,0 +1,26 @@ +<!-- include start from interface/parameters-df.xml.i --> +<leafNode name="df"> + <properties> + <help>Usage of the DF (don't Fragment) bit in outgoing packets</help> + <completionHelp> + <list>set unset inherit</list> + </completionHelp> + <valueHelp> + <format>set</format> + <description>Always set DF (don't fragment) bit</description> + </valueHelp> + <valueHelp> + <format>unset</format> + <description>Always unset DF (don't fragment) bit</description> + </valueHelp> + <valueHelp> + <format>inherit</format> + <description>Copy from the original IP header</description> + </valueHelp> + <constraint> + <regex>(set|unset|inherit)</regex> + </constraint> + </properties> + <defaultValue>unset</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/interface/parameters-dont-fragment.xml.i b/interface-definitions/include/interface/parameters-dont-fragment.xml.i deleted file mode 100644 index d34f0a97b..000000000 --- a/interface-definitions/include/interface/parameters-dont-fragment.xml.i +++ /dev/null @@ -1,8 +0,0 @@ -<!-- include start from interface/parameters-df.xml.i --> -<leafNode name="dont-fragment"> - <properties> - <help>Specifies the usage of the dont fragment (DF) bit</help> - <valueless/> - </properties> -</leafNode> -<!-- include end --> diff --git a/interface-definitions/include/interface/parameters-flowlabel.xml.i b/interface-definitions/include/interface/parameters-flowlabel.xml.i index bd0d1e070..b2e88215b 100644 --- a/interface-definitions/include/interface/parameters-flowlabel.xml.i +++ b/interface-definitions/include/interface/parameters-flowlabel.xml.i @@ -14,7 +14,7 @@ <description>Tunnel key, or hex value</description> </valueHelp> <constraint> - <regex>^((0x){0,1}(0?[0-9A-Fa-f]{1,5})|inherit)$</regex> + <regex>((0x){0,1}(0?[0-9A-Fa-f]{1,5})|inherit)</regex> </constraint> <constraintErrorMessage>Must be 'inherit' or a number</constraintErrorMessage> </properties> diff --git a/interface-definitions/include/interface/redirect.xml.i b/interface-definitions/include/interface/redirect.xml.i new file mode 100644 index 000000000..3be9ee16b --- /dev/null +++ b/interface-definitions/include/interface/redirect.xml.i @@ -0,0 +1,17 @@ +<!-- include start from interface/redirect.xml.i --> +<leafNode name="redirect"> + <properties> + <help>Incoming packet redirection destination</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface name</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/interface/source-validation.xml.i b/interface-definitions/include/interface/source-validation.xml.i index f38065f4d..fc9a7d376 100644 --- a/interface-definitions/include/interface/source-validation.xml.i +++ b/interface-definitions/include/interface/source-validation.xml.i @@ -18,7 +18,7 @@ <description>No source validation</description> </valueHelp> <constraint> - <regex>^(strict|loose|disable)$</regex> + <regex>(strict|loose|disable)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/interface/tunnel-remote-multi.xml.i b/interface-definitions/include/interface/tunnel-remote-multi.xml.i new file mode 100644 index 000000000..f672087a4 --- /dev/null +++ b/interface-definitions/include/interface/tunnel-remote-multi.xml.i @@ -0,0 +1,19 @@ +<!-- include start from interface/tunnel-remote-multi.xml.i --> +<leafNode name="remote"> + <properties> + <help>Tunnel remote address</help> + <valueHelp> + <format>ipv4</format> + <description>Tunnel remote IPv4 address</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>Tunnel remote IPv6 address</description> + </valueHelp> + <constraint> + <validator name="ip-address"/> + </constraint> + <multi/> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/interface/tunnel-remote.xml.i b/interface-definitions/include/interface/tunnel-remote.xml.i index 1ba9b0382..2a8891b85 100644 --- a/interface-definitions/include/interface/tunnel-remote.xml.i +++ b/interface-definitions/include/interface/tunnel-remote.xml.i @@ -1,4 +1,4 @@ -<!-- include start from rip/tunnel-remote.xml.i --> +<!-- include start from interface/tunnel-remote.xml.i --> <leafNode name="remote"> <properties> <help>Tunnel remote address</help> diff --git a/interface-definitions/include/interface/vif-s.xml.i b/interface-definitions/include/interface/vif-s.xml.i index e7ba6d193..c1af9f9e3 100644 --- a/interface-definitions/include/interface/vif-s.xml.i +++ b/interface-definitions/include/interface/vif-s.xml.i @@ -18,6 +18,8 @@ #include <include/interface/dhcpv6-options.xml.i> #include <include/interface/disable-link-detect.xml.i> #include <include/interface/disable.xml.i> + #include <include/interface/interface-firewall-vif.xml.i> + #include <include/interface/interface-policy-vif.xml.i> <leafNode name="protocol"> <properties> <help>Protocol used for service VLAN (default: 802.1ad)</help> @@ -33,7 +35,7 @@ <description>VLAN-tagged frame (IEEE 802.1q), ethertype 0x8100</description> </valueHelp> <constraint> - <regex>^(802.1q|802.1ad)$</regex> + <regex>(802.1q|802.1ad)</regex> </constraint> <constraintErrorMessage>Ethertype must be 802.1ad or 802.1q</constraintErrorMessage> </properties> @@ -42,6 +44,7 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-16000.xml.i> <tagNode name="vif-c"> <properties> @@ -61,10 +64,15 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/redirect.xml.i> #include <include/interface/vrf.xml.i> + #include <include/interface/interface-firewall-vif-c.xml.i> + #include <include/interface/interface-policy-vif-c.xml.i> </children> </tagNode> + #include <include/interface/redirect.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/include/interface/vif.xml.i b/interface-definitions/include/interface/vif.xml.i index 5644c554f..57ef8d64c 100644 --- a/interface-definitions/include/interface/vif.xml.i +++ b/interface-definitions/include/interface/vif.xml.i @@ -18,7 +18,8 @@ #include <include/interface/dhcpv6-options.xml.i> #include <include/interface/disable-link-detect.xml.i> #include <include/interface/disable.xml.i> - #include <include/interface/vrf.xml.i> + #include <include/interface/interface-firewall-vif.xml.i> + #include <include/interface/interface-policy-vif.xml.i> <leafNode name="egress-qos"> <properties> <help>VLAN egress QoS</help> @@ -27,7 +28,7 @@ <description>Format for qos mapping, e.g.: '0:1 1:6 7:6'</description> </valueHelp> <constraint> - <regex>[:0-7 ]+$</regex> + <regex>[:0-7 ]+</regex> </constraint> <constraintErrorMessage>QoS mapping should be in the format of '0:7 2:3' with numbers 0-9</constraintErrorMessage> </properties> @@ -40,7 +41,7 @@ <description>Format for qos mapping, e.g.: '0:1 1:6 7:6'</description> </valueHelp> <constraint> - <regex>[:0-7 ]+$</regex> + <regex>[:0-7 ]+</regex> </constraint> <constraintErrorMessage>QoS mapping should be in the format of '0:7 2:3' with numbers 0-9</constraintErrorMessage> </properties> @@ -48,7 +49,10 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/vrf.xml.i> </children> </tagNode> <!-- include end --> diff --git a/interface-definitions/include/interface/vrf.xml.i b/interface-definitions/include/interface/vrf.xml.i index 5ad978a27..8605f56e8 100644 --- a/interface-definitions/include/interface/vrf.xml.i +++ b/interface-definitions/include/interface/vrf.xml.i @@ -3,7 +3,7 @@ <properties> <help>VRF instance name</help> <valueHelp> - <format>text</format> + <format>txt</format> <description>VRF instance name</description> </valueHelp> <completionHelp> diff --git a/interface-definitions/include/ipsec/local-address.xml.i b/interface-definitions/include/ipsec/local-address.xml.i index 2de6ecb1f..9d267f3f7 100644 --- a/interface-definitions/include/ipsec/local-address.xml.i +++ b/interface-definitions/include/ipsec/local-address.xml.i @@ -4,6 +4,7 @@ <help>IPv4 or IPv6 address of a local interface to use for VPN</help> <completionHelp> <list>any</list> + <script>${vyos_completion_dir}/list_local_ips.sh --both</script> </completionHelp> <valueHelp> <format>ipv4</format> @@ -20,7 +21,7 @@ <constraint> <validator name="ipv4-address"/> <validator name="ipv6-address"/> - <regex>^(any)$</regex> + <regex>(any)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/ipsec/local-traffic-selector.xml.i b/interface-definitions/include/ipsec/local-traffic-selector.xml.i index d30a6d11a..9ae67f583 100644 --- a/interface-definitions/include/ipsec/local-traffic-selector.xml.i +++ b/interface-definitions/include/ipsec/local-traffic-selector.xml.i @@ -9,11 +9,11 @@ <properties> <help>Local IPv4 or IPv6 prefix</help> <valueHelp> - <format>ipv4</format> + <format>ipv4net</format> <description>Local IPv4 prefix</description> </valueHelp> <valueHelp> - <format>ipv6</format> + <format>ipv6net</format> <description>Local IPv6 prefix</description> </valueHelp> <constraint> diff --git a/interface-definitions/include/isis/high-low-label-value.xml.i b/interface-definitions/include/isis/high-low-label-value.xml.i new file mode 100644 index 000000000..adc28417d --- /dev/null +++ b/interface-definitions/include/isis/high-low-label-value.xml.i @@ -0,0 +1,26 @@ +<!-- include start from isis/high-low-label-value.xml.i --> +<leafNode name="low-label-value"> + <properties> + <help>MPLS label lower bound</help> + <valueHelp> + <format>u32:16-1048575</format> + <description>Label value</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 16-1048575"/> + </constraint> + </properties> +</leafNode> +<leafNode name="high-label-value"> + <properties> + <help>MPLS label upper bound</help> + <valueHelp> + <format>u32:16-1048575</format> + <description>Label value</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 16-1048575"/> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/isis/password.xml.i b/interface-definitions/include/isis/password.xml.i new file mode 100644 index 000000000..27c3b0fa0 --- /dev/null +++ b/interface-definitions/include/isis/password.xml.i @@ -0,0 +1,20 @@ +<!-- include start from isis/password.xml.i --> +<leafNode name="plaintext-password"> + <properties> + <help>Plain-text authentication type</help> + <valueHelp> + <format>txt</format> + <description>Circuit password</description> + </valueHelp> + </properties> +</leafNode> +<leafNode name="md5"> + <properties> + <help>MD5 authentication type</help> + <valueHelp> + <format>txt</format> + <description>Level-wide password</description> + </valueHelp> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i index 84e2f7bb2..75a0355d4 100644 --- a/interface-definitions/include/isis/protocol-common-config.xml.i +++ b/interface-definitions/include/isis/protocol-common-config.xml.i @@ -4,24 +4,7 @@ <help>Configure the authentication password for an area</help> </properties> <children> - <leafNode name="plaintext-password"> - <properties> - <help>Plain-text authentication type</help> - <valueHelp> - <format>txt</format> - <description>Level-wide password</description> - </valueHelp> - </properties> - </leafNode> - <leafNode name="md5"> - <properties> - <help>MD5 authentication type</help> - <valueHelp> - <format>txt</format> - <description>Level-wide password</description> - </valueHelp> - </properties> - </leafNode> + #include <include/isis/password.xml.i> </children> </node> <node name="default-information"> @@ -59,24 +42,7 @@ <help>Set the authentication password for a routing domain</help> </properties> <children> - <leafNode name="plaintext-password"> - <properties> - <help>Plain-text authentication type</help> - <valueHelp> - <format>txt</format> - <description>Level-wide password</description> - </valueHelp> - </properties> - </leafNode> - <leafNode name="md5"> - <properties> - <help>MD5 authentication type</help> - <valueHelp> - <format>txt</format> - <description>Level-wide password</description> - </valueHelp> - </properties> - </leafNode> + #include <include/isis/password.xml.i> </children> </node> <leafNode name="dynamic-hostname"> @@ -104,7 +70,7 @@ <description>Act as an area router</description> </valueHelp> <constraint> - <regex>^(level-1|level-1-2|level-2)$</regex> + <regex>(level-1|level-1-2|level-2)</regex> </constraint> </properties> </leafNode> @@ -182,7 +148,7 @@ <description>Use new style of TLVs to carry wider metric</description> </valueHelp> <constraint> - <regex>^(narrow|transition|wide)$</regex> + <regex>(narrow|transition|wide)</regex> </constraint> </properties> </leafNode> @@ -275,68 +241,20 @@ </leafNode> <node name="global-block"> <properties> - <help>Global block label range</help> + <help>Segment Routing Global Block label range</help> </properties> <children> - <leafNode name="low-label-value"> - <properties> - <help>The lower bound of the global block</help> - <valueHelp> - <format>u32:16-1048575</format> - <description>MPLS label value</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 16-1048575"/> - </constraint> - </properties> - </leafNode> - <leafNode name="high-label-value"> - <properties> - <help>The upper bound of the global block</help> - <valueHelp> - <format>u32:16-1048575</format> - <description>MPLS label value</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 16-1048575"/> - </constraint> - </properties> - </leafNode> + #include <include/isis/high-low-label-value.xml.i> </children> </node> -<!-- <node name="local-block"> <properties> - <help>Local Block label range</help> + <help>Segment Routing Local Block label range</help> </properties> <children> - <leafNode name="low-label-value"> - <properties> - <help>The lower bound of the local block</help> - <valueHelp> - <format>u32:16-1048575</format> - <description>MPLS label value</description> - </valueHelp> - <constraint> - <validator name="numeric" argument=" range 16-1048575"/> - </constraint> - </properties> - </leafNode> - <leafNode name="high-label-value"> - <properties> - <help>The upper bound of the local block</help> - <valueHelp> - <format>u32:16-1048575</format> - <description>MPLS label value</description> - </valueHelp> - <constraint> - <validator name="numeric" argument=" range 16-1048575"/> - </constraint> - </properties> - </leafNode> + #include <include/isis/high-low-label-value.xml.i> </children> </node> ---> <leafNode name="maximum-label-depth"> <properties> <help>Maximum MPLS labels allowed for this router</help> @@ -648,7 +566,7 @@ </completionHelp> </properties> <children> - #include <include/bfd.xml.i> + #include <include/bfd/bfd.xml.i> <leafNode name="circuit-type"> <properties> <help>Configure circuit type for interface</help> @@ -668,7 +586,7 @@ <description>Level-2 only adjacencies are formed</description> </valueHelp> <constraint> - <regex>^(level-1|level-1-2|level-2-only)$</regex> + <regex>(level-1|level-1-2|level-2-only)</regex> </constraint> </properties> </leafNode> @@ -722,15 +640,7 @@ <help>Configure the authentication password for a circuit</help> </properties> <children> - <leafNode name="plaintext-password"> - <properties> - <help>Plain-text authentication type</help> - <valueHelp> - <format>txt</format> - <description>Circuit password</description> - </valueHelp> - </properties> - </leafNode> + #include <include/isis/password.xml.i> </children> </node> <leafNode name="priority"> diff --git a/interface-definitions/include/listen-address-ipv4.xml.i b/interface-definitions/include/listen-address-ipv4.xml.i index ee52cebe8..9cca297a0 100644 --- a/interface-definitions/include/listen-address-ipv4.xml.i +++ b/interface-definitions/include/listen-address-ipv4.xml.i @@ -1,13 +1,13 @@ <!-- include start from listen-address-ipv4.xml.i --> <leafNode name="listen-address"> <properties> - <help>Local IPv4 addresses for service to listen on</help> + <help>Local IPv4 addresses to listen on</help> <completionHelp> <script>${vyos_completion_dir}/list_local_ips.sh --ipv4</script> </completionHelp> <valueHelp> <format>ipv4</format> - <description>IP address to listen for incoming connections</description> + <description>IPv4 address to listen for incoming connections</description> </valueHelp> <multi/> <constraint> diff --git a/interface-definitions/include/listen-address-vrf.xml.i b/interface-definitions/include/listen-address-vrf.xml.i new file mode 100644 index 000000000..8c2bdce70 --- /dev/null +++ b/interface-definitions/include/listen-address-vrf.xml.i @@ -0,0 +1,25 @@ +<!-- include start from listen-address-vrf.xml.i --> +<tagNode name="listen-address"> + <properties> + <help>Local IP addresses to listen on</help> + <completionHelp> + <script>${vyos_completion_dir}/list_local_ips.sh --both</script> + </completionHelp> + <valueHelp> + <format>ipv4</format> + <description>IPv4 address to listen for incoming connections</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address to listen for incoming connections</description> + </valueHelp> + <constraint> + <validator name="ipv4-address"/> + <validator name="ipv6-address"/> + </constraint> + </properties> + <children> + #include <include/interface/vrf.xml.i> + </children> +</tagNode> +<!-- include end --> diff --git a/interface-definitions/include/listen-address.xml.i b/interface-definitions/include/listen-address.xml.i index 9b86851c7..48003dbf2 100644 --- a/interface-definitions/include/listen-address.xml.i +++ b/interface-definitions/include/listen-address.xml.i @@ -1,13 +1,13 @@ <!-- include start from listen-address.xml.i --> <leafNode name="listen-address"> <properties> - <help>Local IP addresses for service to listen on</help> + <help>Local IP addresses to listen on</help> <completionHelp> <script>${vyos_completion_dir}/list_local_ips.sh --both</script> </completionHelp> <valueHelp> <format>ipv4</format> - <description>IP address to listen for incoming connections</description> + <description>IPv4 address to listen for incoming connections</description> </valueHelp> <valueHelp> <format>ipv6</format> @@ -17,6 +17,7 @@ <constraint> <validator name="ipv4-address"/> <validator name="ipv6-address"/> + <validator name="ipv6-link-local"/> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/monitoring/url.xml.i b/interface-definitions/include/monitoring/url.xml.i new file mode 100644 index 000000000..32c81122d --- /dev/null +++ b/interface-definitions/include/monitoring/url.xml.i @@ -0,0 +1,15 @@ +<!-- include start from monitoring/url.xml.i --> +<leafNode name="url"> + <properties> + <help>Remote URL [REQUIRED]</help> + <valueHelp> + <format>url</format> + <description>Remote URL</description> + </valueHelp> + <constraint> + <regex>(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}?(\/.*)?</regex> + </constraint> + <constraintErrorMessage>Incorrect URL format</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/nat-port.xml.i b/interface-definitions/include/nat-port.xml.i index ebba43712..5f762cfb3 100644 --- a/interface-definitions/include/nat-port.xml.i +++ b/interface-definitions/include/nat-port.xml.i @@ -3,6 +3,10 @@ <properties> <help>Port number</help> <valueHelp> + <format>txt</format> + <description>Named port (any name in /etc/services, e.g., http)</description> + </valueHelp> + <valueHelp> <format>u32:1-65535</format> <description>Numeric IP port</description> </valueHelp> @@ -11,9 +15,12 @@ <description>Numbered port range (e.g. 1001-1005)</description> </valueHelp> <valueHelp> - <format> </format> + <format/> <description>\n\nMultiple destination ports can be specified as a comma-separated list.\nThe whole list can also be negated using '!'.\nFor example: '!22,telnet,http,123,1001-1005'</description> </valueHelp> + <constraint> + <validator name="port-multi"/> + </constraint> </properties> </leafNode> <!-- include end --> diff --git a/interface-definitions/include/nat-rule.xml.i b/interface-definitions/include/nat-rule.xml.i index 084f1f722..bdb86ed9b 100644 --- a/interface-definitions/include/nat-rule.xml.i +++ b/interface-definitions/include/nat-rule.xml.i @@ -4,7 +4,7 @@ <help>Rule number for NAT</help> <valueHelp> <format>u32:1-999999</format> - <description>Number for this NAT rule</description> + <description>Number of NAT rule</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-999999"/> @@ -12,11 +12,7 @@ <constraintErrorMessage>NAT rule number must be between 1 and 999999</constraintErrorMessage> </properties> <children> - <leafNode name="description"> - <properties> - <help>Rule description</help> - </properties> - </leafNode> + #include <include/generic-description.xml.i> <node name="destination"> <properties> <help>NAT destination parameters</help> diff --git a/interface-definitions/include/nat-translation-options.xml.i b/interface-definitions/include/nat-translation-options.xml.i index df2f76397..6b95de045 100644 --- a/interface-definitions/include/nat-translation-options.xml.i +++ b/interface-definitions/include/nat-translation-options.xml.i @@ -16,13 +16,14 @@ </valueHelp> <valueHelp> <format>random</format> - <description>Random source or destination address allocation for each connection (default)</description> + <description>Random source or destination address allocation for each connection</description> </valueHelp> <constraint> - <regex>^(persistent|random)$</regex> + <regex>(persistent|random)</regex> </constraint> </properties> - </leafNode> + <defaultValue>random</defaultValue> + </leafNode> <leafNode name="port-mapping"> <properties> <help>Port mapping options</help> @@ -39,13 +40,14 @@ </valueHelp> <valueHelp> <format>none</format> - <description>Do not apply port randomization (default)</description> + <description>Do not apply port randomization</description> </valueHelp> <constraint> - <regex>^(random|fully-random|none)$</regex> + <regex>(random|fully-random|none)</regex> </constraint> </properties> - </leafNode> + <defaultValue>none</defaultValue> + </leafNode> </children> </node> <!-- include end --> diff --git a/interface-definitions/include/nat-translation-port.xml.i b/interface-definitions/include/nat-translation-port.xml.i index 6e507353c..6f17df3d9 100644 --- a/interface-definitions/include/nat-translation-port.xml.i +++ b/interface-definitions/include/nat-translation-port.xml.i @@ -10,6 +10,9 @@ <format>range</format> <description>Numbered port range (e.g., 1001-1005)</description> </valueHelp> + <constraint> + <validator name="port-range"/> + </constraint> </properties> </leafNode> <!-- include end --> diff --git a/interface-definitions/include/ospf/authentication.xml.i b/interface-definitions/include/ospf/authentication.xml.i index 1e6050b97..8e8cad067 100644 --- a/interface-definitions/include/ospf/authentication.xml.i +++ b/interface-definitions/include/ospf/authentication.xml.i @@ -29,7 +29,7 @@ <description>MD5 Key (16 characters or less)</description> </valueHelp> <constraint> - <regex>^[^[:space:]]{1,16}$</regex> + <regex>[^[:space:]]{1,16}</regex> </constraint> <constraintErrorMessage>Password must be 16 characters or less</constraintErrorMessage> </properties> @@ -46,7 +46,7 @@ <description>Plain text password (8 characters or less)</description> </valueHelp> <constraint> - <regex>^[^[:space:]]{1,8}$</regex> + <regex>[^[:space:]]{1,8}</regex> </constraint> <constraintErrorMessage>Password must be 8 characters or less</constraintErrorMessage> </properties> diff --git a/interface-definitions/include/ospf/auto-cost.xml.i b/interface-definitions/include/ospf/auto-cost.xml.i new file mode 100644 index 000000000..da6483a00 --- /dev/null +++ b/interface-definitions/include/ospf/auto-cost.xml.i @@ -0,0 +1,22 @@ +<!-- include start from ospf/auto-cost.xml.i --> +<node name="auto-cost"> + <properties> + <help>Calculate interface cost according to bandwidth</help> + </properties> + <children> + <leafNode name="reference-bandwidth"> + <properties> + <help>Reference bandwidth method to assign cost</help> + <valueHelp> + <format>u32:1-4294967</format> + <description>Reference bandwidth cost in Mbits/sec</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4294967"/> + </constraint> + </properties> + <defaultValue>100</defaultValue> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/ospf/default-information.xml.i b/interface-definitions/include/ospf/default-information.xml.i new file mode 100644 index 000000000..50cda54a4 --- /dev/null +++ b/interface-definitions/include/ospf/default-information.xml.i @@ -0,0 +1,25 @@ +<!-- include start from ospf/intervals.xml.i --> +<node name="default-information"> + <properties> + <help>Default route advertisment settings</help> + </properties> + <children> + <node name="originate"> + <properties> + <help>Distribute a default route</help> + </properties> + <children> + <leafNode name="always"> + <properties> + <help>Always advertise a default route</help> + <valueless/> + </properties> + </leafNode> + #include <include/ospf/metric.xml.i> + #include <include/ospf/metric-type.xml.i> + #include <include/route-map.xml.i> + </children> + </node> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/ospf/interface-common.xml.i b/interface-definitions/include/ospf/interface-common.xml.i index 4b0aef380..9c8b94f0b 100644 --- a/interface-definitions/include/ospf/interface-common.xml.i +++ b/interface-definitions/include/ospf/interface-common.xml.i @@ -1,5 +1,5 @@ <!-- include start from ospf/interface-common.xml.i --> -#include <include/bfd.xml.i> +#include <include/bfd/bfd.xml.i> <leafNode name="cost"> <properties> <help>Interface cost</help> @@ -20,7 +20,7 @@ </leafNode> <leafNode name="priority"> <properties> - <help>Router priority (default: 1)</help> + <help>Router priority</help> <valueHelp> <format>u32:0-255</format> <description>OSPF router priority cost</description> diff --git a/interface-definitions/include/ospf/intervals.xml.i b/interface-definitions/include/ospf/intervals.xml.i index fad1a6305..9f6e5df69 100644 --- a/interface-definitions/include/ospf/intervals.xml.i +++ b/interface-definitions/include/ospf/intervals.xml.i @@ -1,7 +1,7 @@ <!-- include start from ospf/intervals.xml.i --> <leafNode name="dead-interval"> <properties> - <help>Interval after which a neighbor is declared dead (default: 40)</help> + <help>Interval after which a neighbor is declared dead</help> <valueHelp> <format>u32:1-65535</format> <description>Neighbor dead interval (seconds)</description> @@ -14,7 +14,7 @@ </leafNode> <leafNode name="hello-interval"> <properties> - <help>Interval between hello packets (default: 10)</help> + <help>Interval between hello packets</help> <valueHelp> <format>u32:1-65535</format> <description>Hello interval (seconds)</description> @@ -27,7 +27,7 @@ </leafNode> <leafNode name="retransmit-interval"> <properties> - <help>Interval between retransmitting lost link state advertisements (default: 5)</help> + <help>Interval between retransmitting lost link state advertisements</help> <valueHelp> <format>u32:1-65535</format> <description>Retransmit interval (seconds)</description> @@ -40,7 +40,7 @@ </leafNode> <leafNode name="transmit-delay"> <properties> - <help>Link state transmit delay (default: 1)</help> + <help>Link state transmit delay</help> <valueHelp> <format>u32:1-65535</format> <description>Link state transmit delay (seconds)</description> diff --git a/interface-definitions/include/ospf/metric-type.xml.i b/interface-definitions/include/ospf/metric-type.xml.i index ef9fd8ac0..de55c7645 100644 --- a/interface-definitions/include/ospf/metric-type.xml.i +++ b/interface-definitions/include/ospf/metric-type.xml.i @@ -1,7 +1,7 @@ <!-- include start from ospf/metric-type.xml.i --> <leafNode name="metric-type"> <properties> - <help>OSPF metric type for default routes (default: 2)</help> + <help>OSPF metric type for default routes</help> <valueHelp> <format>u32:1-2</format> <description>Set OSPF External Type 1/2 metrics</description> diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i index 982e519a9..c156d5b1c 100644 --- a/interface-definitions/include/ospf/protocol-common-config.xml.i +++ b/interface-definitions/include/ospf/protocol-common-config.xml.i @@ -45,7 +45,7 @@ <description>Filter static routes</description> </valueHelp> <constraint> - <regex>^(bgp|connected|isis|kernel|rip|static)$</regex> + <regex>(bgp|connected|isis|kernel|rip|static)</regex> </constraint> <constraintErrorMessage>Must be bgp, connected, kernel, rip, or static</constraintErrorMessage> <multi/> @@ -106,7 +106,7 @@ </leafNode> <leafNode name="translate"> <properties> - <help>Configure NSSA-ABR (default: candidate)</help> + <help>Configure NSSA-ABR</help> <completionHelp> <list>always candidate never</list> </completionHelp> @@ -116,14 +116,14 @@ </valueHelp> <valueHelp> <format>candidate</format> - <description>Translate for election (default)</description> + <description>Translate for election</description> </valueHelp> <valueHelp> <format>never</format> <description>Never translate LSA types</description> </valueHelp> <constraint> - <regex>^(always|candidate|never)$</regex> + <regex>(always|candidate|never)</regex> </constraint> </properties> <defaultValue>candidate</defaultValue> @@ -172,7 +172,7 @@ <description>Use MD5 authentication</description> </valueHelp> <constraint> - <regex>^(plaintext-password|md5)$</regex> + <regex>(plaintext-password|md5)</regex> </constraint> </properties> </leafNode> @@ -252,72 +252,61 @@ <description>Enable shortcutting mode</description> </valueHelp> <constraint> - <regex>^(default|disable|enable)$</regex> + <regex>(default|disable|enable)</regex> </constraint> </properties> </leafNode> - <tagNode name="virtual-link"> + <leafNode name="export-list"> <properties> - <help>Virtual link</help> + <help>Set the filter for networks announced to other areas</help> + <completionHelp> + <path>policy access-list</path> + </completionHelp> <valueHelp> - <format>ipv4</format> - <description>OSPF area in dotted decimal notation</description> + <format>u32</format> + <description>Access-list number</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> - <validator name="ip-address"/> </constraint> </properties> - <children> - #include <include/ospf/authentication.xml.i> - #include <include/ospf/intervals.xml.i> - </children> - </tagNode> - </children> -</tagNode> -<node name="auto-cost"> - <properties> - <help>Calculate OSPF interface cost according to bandwidth (default: 100)</help> - </properties> - <children> - <leafNode name="reference-bandwidth"> + </leafNode> + <leafNode name="import-list"> <properties> - <help>Reference bandwidth method to assign OSPF cost</help> + <help>Set the filter for networks from other areas announced</help> + <completionHelp> + <path>policy access-list</path> + </completionHelp> <valueHelp> - <format>u32:1-4294967</format> - <description>Reference bandwidth cost in Mbits/sec</description> + <format>u32</format> + <description>Access-list number</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 1-4294967"/> + <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> - <defaultValue>100</defaultValue> </leafNode> - </children> -</node> -<node name="default-information"> - <properties> - <help>Default route advertisment settings</help> - </properties> - <children> - <node name="originate"> + <tagNode name="virtual-link"> <properties> - <help>Distribute a default route</help> + <help>Virtual link</help> + <valueHelp> + <format>ipv4</format> + <description>OSPF area in dotted decimal notation</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + <validator name="ip-address"/> + </constraint> </properties> <children> - <leafNode name="always"> - <properties> - <help>Always advertise a default route</help> - <valueless/> - </properties> - </leafNode> - #include <include/ospf/metric.xml.i> - #include <include/ospf/metric-type.xml.i> - #include <include/route-map.xml.i> + #include <include/ospf/authentication.xml.i> + #include <include/ospf/intervals.xml.i> </children> - </node> + </tagNode> </children> -</node> +</tagNode> +#include <include/ospf/auto-cost.xml.i> +#include <include/ospf/default-information.xml.i> <leafNode name="default-metric"> <properties> <help>Metric of redistributed routes</help> @@ -330,6 +319,18 @@ </constraint> </properties> </leafNode> +<leafNode name="maximum-paths"> + <properties> + <help>Maximum multiple paths (ECMP)</help> + <valueHelp> + <format>u32:1-64</format> + <description>Maximum multiple paths (ECMP)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-64"/> + </constraint> + </properties> +</leafNode> <node name="distance"> <properties> <help>Administrative distance</help> @@ -431,11 +432,19 @@ <description>Point-to-point network type</description> </valueHelp> <constraint> - <regex>^(broadcast|non-broadcast|point-to-multipoint|point-to-point)$</regex> + <regex>(broadcast|non-broadcast|point-to-multipoint|point-to-point)</regex> </constraint> <constraintErrorMessage>Must be broadcast, non-broadcast, point-to-multipoint or point-to-point</constraintErrorMessage> </properties> </leafNode> + <node name="passive"> + <properties> + <help>Suppress routing updates on an interface</help> + </properties> + <children> + #include <include/generic-disable-node.xml.i> + </children> + </node> </children> </tagNode> #include <include/ospf/log-adjacency-changes.xml.i> @@ -523,7 +532,7 @@ <children> <leafNode name="poll-interval"> <properties> - <help>Dead neighbor polling interval (default: 60)</help> + <help>Dead neighbor polling interval</help> <valueHelp> <format>u32:1-65535</format> <description>Seconds between dead neighbor polling interval</description> @@ -536,7 +545,7 @@ </leafNode> <leafNode name="priority"> <properties> - <help>Neighbor priority in seconds (default: 0)</help> + <help>Neighbor priority in seconds</help> <valueHelp> <format>u32:0-255</format> <description>Neighbor priority</description> @@ -556,13 +565,13 @@ <children> <leafNode name="abr-type"> <properties> - <help>OSPF ABR type (default: cisco)</help> + <help>OSPF ABR type</help> <completionHelp> <list>cisco ibm shortcut standard</list> </completionHelp> <valueHelp> <format>cisco</format> - <description>Cisco ABR type (default)</description> + <description>Cisco ABR type</description> </valueHelp> <valueHelp> <format>ibm</format> @@ -577,7 +586,7 @@ <description>Standard ABR type</description> </valueHelp> <constraint> - <regex>^(cisco|ibm|shortcut|standard)$</regex> + <regex>(cisco|ibm|shortcut|standard)</regex> </constraint> </properties> <defaultValue>cisco</defaultValue> @@ -597,26 +606,19 @@ #include <include/router-id.xml.i> </children> </node> -#include <include/routing-passive-interface.xml.i> -<leafNode name="passive-interface-exclude"> +<leafNode name="passive-interface"> <properties> - <help>Interface to exclude when using 'passive-interface default'</help> + <help>Suppress routing updates on an interface</help> <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> + <list>default</list> </completionHelp> <valueHelp> - <format>txt</format> - <description>Interface to exclude when suppressing routing updates</description> - </valueHelp> - <valueHelp> - <format>vlinkN</format> - <description>Virtual-link interface to exclude when suppressing routing updates</description> + <format>default</format> + <description>Default to suppress routing updates on all interfaces</description> </valueHelp> <constraint> - <validator name="interface-name"/> - <regex>^(vlink[0-9]+)$</regex> + <regex>(default)</regex> </constraint> - <multi/> </properties> </leafNode> <node name="redistribute"> @@ -740,7 +742,7 @@ <children> <leafNode name="delay"> <properties> - <help>Delay from the first change received to SPF calculation (default: 200)</help> + <help>Delay from the first change received to SPF calculation</help> <valueHelp> <format>u32:0-600000</format> <description>Delay in milliseconds</description> @@ -753,7 +755,7 @@ </leafNode> <leafNode name="initial-holdtime"> <properties> - <help>Initial hold time between consecutive SPF calculations (default: 1000)</help> + <help>Initial hold time between consecutive SPF calculations</help> <valueHelp> <format>u32:0-600000</format> <description>Initial hold time in milliseconds</description> @@ -766,7 +768,7 @@ </leafNode> <leafNode name="max-holdtime"> <properties> - <help>Maximum hold time (default: 10000)</help> + <help>Maximum hold time</help> <valueHelp> <format>u32:0-600000</format> <description>Max hold time in milliseconds</description> diff --git a/interface-definitions/include/ospfv3/no-summary.xml.i b/interface-definitions/include/ospfv3/no-summary.xml.i new file mode 100644 index 000000000..a6afda3e0 --- /dev/null +++ b/interface-definitions/include/ospfv3/no-summary.xml.i @@ -0,0 +1,8 @@ +<!-- include start from ospfv3/no-summary.xml.i --> +<leafNode name="no-summary"> + <properties> + <help>Do not inject inter-area routes into the stub</help> + <valueless/> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/ospfv3/protocol-common-config.xml.i b/interface-definitions/include/ospfv3/protocol-common-config.xml.i new file mode 100644 index 000000000..630534eea --- /dev/null +++ b/interface-definitions/include/ospfv3/protocol-common-config.xml.i @@ -0,0 +1,252 @@ +<!-- include start from ospfv3/protocol-common-config.xml.i --> +<tagNode name="area"> + <properties> + <help>OSPFv3 Area</help> + <valueHelp> + <format>u32</format> + <description>Area ID as a decimal value</description> + </valueHelp> + <valueHelp> + <format>ipv4</format> + <description>Area ID in IP address forma</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + <validator name="ip-address"/> + </constraint> + </properties> + <children> + <node name="area-type"> + <properties> + <help>OSPFv3 Area type</help> + </properties> + <children> + <node name="nssa"> + <properties> + <help>NSSA OSPFv3 area</help> + </properties> + <children> + <leafNode name="default-information-originate"> + <properties> + <help>Originate Type 7 default into NSSA area</help> + <valueless/> + </properties> + </leafNode> + #include <include/ospfv3/no-summary.xml.i> + </children> + </node> + <node name="stub"> + <properties> + <help>Stub OSPFv3 area</help> + </properties> + <children> + #include <include/ospfv3/no-summary.xml.i> + </children> + </node> + </children> + </node> + <leafNode name="export-list"> + <properties> + <help>Name of export-list</help> + <completionHelp> + <path>policy access-list6</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="import-list"> + <properties> + <help>Name of import-list</help> + <completionHelp> + <path>policy access-list6</path> + </completionHelp> + </properties> + </leafNode> + <tagNode name="range"> + <properties> + <help>Specify IPv6 prefix (border routers only)</help> + <valueHelp> + <format>ipv6net</format> + <description>Specify IPv6 prefix (border routers only)</description> + </valueHelp> + <constraint> + <validator name="ipv6-prefix"/> + </constraint> + </properties> + <children> + <leafNode name="advertise"> + <properties> + <help>Advertise this range</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="not-advertise"> + <properties> + <help>Do not advertise this range</help> + <valueless/> + </properties> + </leafNode> + </children> + </tagNode> + </children> +</tagNode> +#include <include/ospf/auto-cost.xml.i> +#include <include/ospf/default-information.xml.i> +<node name="distance"> + <properties> + <help>Administrative distance</help> + </properties> + <children> + #include <include/ospf/distance-global.xml.i> + <node name="ospfv3"> + <properties> + <help>OSPFv3 administrative distance</help> + </properties> + <children> + #include <include/ospf/distance-per-protocol.xml.i> + </children> + </node> + </children> +</node> +<tagNode name="interface"> + <properties> + <help>Enable routing on an IPv6 interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface used for routing information exchange</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> + </properties> + <children> + <leafNode name="area"> + <properties> + <help>Enable OSPF on this interface</help> + <completionHelp> + <path>protocols ospfv3 area</path> + </completionHelp> + <valueHelp> + <format>u32</format> + <description>OSPF area ID as decimal notation</description> + </valueHelp> + <valueHelp> + <format>ipv4</format> + <description>OSPF area ID in IP address notation</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + <validator name="ip-address"/> + </constraint> + </properties> + </leafNode> + #include <include/ospf/intervals.xml.i> + #include <include/ospf/interface-common.xml.i> + <leafNode name="ifmtu"> + <properties> + <help>Interface MTU</help> + <valueHelp> + <format>u32:1-65535</format> + <description>Interface MTU</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-65535"/> + </constraint> + </properties> + </leafNode> + <leafNode name="instance-id"> + <properties> + <help>Instance ID</help> + <valueHelp> + <format>u32:0-255</format> + <description>Instance Id</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-255"/> + </constraint> + </properties> + <defaultValue>0</defaultValue> + </leafNode> + <leafNode name="network"> + <properties> + <help>Network type</help> + <completionHelp> + <list>broadcast point-to-point</list> + </completionHelp> + <valueHelp> + <format>broadcast</format> + <description>Broadcast network type</description> + </valueHelp> + <valueHelp> + <format>point-to-point</format> + <description>Point-to-point network type</description> + </valueHelp> + <constraint> + <regex>(broadcast|point-to-point)</regex> + </constraint> + <constraintErrorMessage>Must be broadcast or point-to-point</constraintErrorMessage> + </properties> + </leafNode> + #include <include/isis/passive.xml.i> + </children> +</tagNode> +#include <include/ospf/log-adjacency-changes.xml.i> +<node name="parameters"> + <properties> + <help>OSPFv3 specific parameters</help> + </properties> + <children> + #include <include/router-id.xml.i> + </children> +</node> +<node name="redistribute"> + <properties> + <help>Redistribute information from another routing protocol</help> + </properties> + <children> + <node name="bgp"> + <properties> + <help>Redistribute BGP routes</help> + </properties> + <children> + #include <include/route-map.xml.i> + </children> + </node> + <node name="connected"> + <properties> + <help>Redistribute connected routes</help> + </properties> + <children> + #include <include/route-map.xml.i> + </children> + </node> + <node name="kernel"> + <properties> + <help>Redistribute kernel routes</help> + </properties> + <children> + #include <include/route-map.xml.i> + </children> + </node> + <node name="ripng"> + <properties> + <help>Redistribute RIPNG routes</help> + </properties> + <children> + #include <include/route-map.xml.i> + </children> + </node> + <node name="static"> + <properties> + <help>Redistribute static routes</help> + </properties> + <children> + #include <include/route-map.xml.i> + </children> + </node> + </children> +</node> +#include <include/route-map.xml.i> +<!-- include end --> diff --git a/interface-definitions/include/policy/action.xml.i b/interface-definitions/include/policy/action.xml.i index 3b9b458d4..0a3dc158a 100644 --- a/interface-definitions/include/policy/action.xml.i +++ b/interface-definitions/include/policy/action.xml.i @@ -14,7 +14,7 @@ <description>Deny matching entries</description> </valueHelp> <constraint> - <regex>^(permit|deny)$</regex> + <regex>(permit|deny)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/include/policy/route-common-rule-ipv6.xml.i b/interface-definitions/include/policy/route-common-rule-ipv6.xml.i new file mode 100644 index 000000000..cfeba1a6c --- /dev/null +++ b/interface-definitions/include/policy/route-common-rule-ipv6.xml.i @@ -0,0 +1,553 @@ +<!-- include start from policy/route-common-rule.xml.i --> +#include <include/policy/route-rule-action.xml.i> +#include <include/generic-description.xml.i> +<leafNode name="disable"> + <properties> + <help>Option to disable firewall rule</help> + <valueless/> + </properties> +</leafNode> +<node name="fragment"> + <properties> + <help>IP fragment match</help> + </properties> + <children> + <leafNode name="match-frag"> + <properties> + <help>Second and further fragments of fragmented packets</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="match-non-frag"> + <properties> + <help>Head fragments or unfragmented packets</help> + <valueless/> + </properties> + </leafNode> + </children> +</node> +<node name="ipsec"> + <properties> + <help>Inbound IPsec packets</help> + </properties> + <children> + <leafNode name="match-ipsec"> + <properties> + <help>Inbound IPsec packets</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="match-none"> + <properties> + <help>Inbound non-IPsec packets</help> + <valueless/> + </properties> + </leafNode> + </children> +</node> +<node name="limit"> + <properties> + <help>Rate limit using a token bucket filter</help> + </properties> + <children> + <leafNode name="burst"> + <properties> + <help>Maximum number of packets to allow in excess of rate</help> + <valueHelp> + <format>u32:0-4294967295</format> + <description>Maximum number of packets to allow in excess of rate</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + </properties> + </leafNode> + <leafNode name="rate"> + <properties> + <help>Maximum average matching rate</help> + <valueHelp> + <format>u32:0-4294967295</format> + <description>Maximum average matching rate</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + </properties> + </leafNode> + </children> +</node> +<leafNode name="log"> + <properties> + <help>Option to log packets matching rule</help> + <completionHelp> + <list>enable disable</list> + </completionHelp> + <valueHelp> + <format>enable</format> + <description>Enable log</description> + </valueHelp> + <valueHelp> + <format>disable</format> + <description>Disable log</description> + </valueHelp> + <constraint> + <regex>(enable|disable)</regex> + </constraint> + </properties> +</leafNode> +<leafNode name="protocol"> + <properties> + <help>Protocol to match (protocol name, number, or "all")</help> + <completionHelp> + <script>cat /etc/protocols | sed -e '/^#.*/d' | awk '{ print $1 }'</script> + </completionHelp> + <valueHelp> + <format>all</format> + <description>All IP protocols</description> + </valueHelp> + <valueHelp> + <format>tcp_udp</format> + <description>Both TCP and UDP</description> + </valueHelp> + <valueHelp> + <format>0-255</format> + <description>IP protocol number</description> + </valueHelp> + <valueHelp> + <format>!<protocol></format> + <description>IP protocol number</description> + </valueHelp> + <constraint> + <validator name="ip-protocol"/> + </constraint> + </properties> + <defaultValue>all</defaultValue> +</leafNode> +<node name="recent"> + <properties> + <help>Parameters for matching recently seen sources</help> + </properties> + <children> + <leafNode name="count"> + <properties> + <help>Source addresses seen more than N times</help> + <valueHelp> + <format>u32:1-255</format> + <description>Source addresses seen more than N times</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-255"/> + </constraint> + </properties> + </leafNode> + <leafNode name="time"> + <properties> + <help>Source addresses seen in the last N seconds</help> + <valueHelp> + <format>u32:0-4294967295</format> + <description>Source addresses seen in the last N seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + </properties> + </leafNode> + </children> +</node> +<node name="set"> + <properties> + <help>Packet modifications</help> + </properties> + <children> + <leafNode name="dscp"> + <properties> + <help>Packet Differentiated Services Codepoint (DSCP)</help> + <valueHelp> + <format>u32:0-63</format> + <description>DSCP number</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-63"/> + </constraint> + </properties> + </leafNode> + <leafNode name="mark"> + <properties> + <help>Packet marking</help> + <valueHelp> + <format>u32:1-2147483647</format> + <description>Packet marking</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-2147483647"/> + </constraint> + </properties> + </leafNode> + <leafNode name="table"> + <properties> + <help>Routing table to forward packet with</help> + <valueHelp> + <format>u32:1-200</format> + <description>Table number</description> + </valueHelp> + <valueHelp> + <format>main</format> + <description>Main table</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-200"/> + <regex>(main)</regex> + </constraint> + </properties> + </leafNode> + <leafNode name="tcp-mss"> + <properties> + <help>TCP Maximum Segment Size</help> + <valueHelp> + <format>u32:500-1460</format> + <description>Explicitly set TCP MSS value</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 500-1460"/> + </constraint> + </properties> + </leafNode> + </children> +</node> +<node name="source"> + <properties> + <help>Source parameters</help> + </properties> + <children> + #include <include/firewall/address-ipv6.xml.i> + #include <include/firewall/source-destination-group.xml.i> + <leafNode name="mac-address"> + <properties> + <help>Source MAC address</help> + <valueHelp> + <format><MAC address></format> + <description>MAC address to match</description> + </valueHelp> + <valueHelp> + <format>!<MAC address></format> + <description>Match everything except the specified MAC address</description> + </valueHelp> + <constraint> + <validator name="mac-address-firewall"/> + </constraint> + </properties> + </leafNode> + #include <include/firewall/port.xml.i> + </children> +</node> +<node name="state"> + <properties> + <help>Session state</help> + </properties> + <children> + <leafNode name="established"> + <properties> + <help>Established state</help> + <completionHelp> + <list>enable disable</list> + </completionHelp> + <valueHelp> + <format>enable</format> + <description>Enable</description> + </valueHelp> + <valueHelp> + <format>disable</format> + <description>Disable</description> + </valueHelp> + <constraint> + <regex>(enable|disable)</regex> + </constraint> + </properties> + </leafNode> + <leafNode name="invalid"> + <properties> + <help>Invalid state</help> + <completionHelp> + <list>enable disable</list> + </completionHelp> + <valueHelp> + <format>enable</format> + <description>Enable</description> + </valueHelp> + <valueHelp> + <format>disable</format> + <description>Disable</description> + </valueHelp> + <constraint> + <regex>(enable|disable)</regex> + </constraint> + </properties> + </leafNode> + <leafNode name="new"> + <properties> + <help>New state</help> + <completionHelp> + <list>enable disable</list> + </completionHelp> + <valueHelp> + <format>enable</format> + <description>Enable</description> + </valueHelp> + <valueHelp> + <format>disable</format> + <description>Disable</description> + </valueHelp> + <constraint> + <regex>(enable|disable)</regex> + </constraint> + </properties> + </leafNode> + <leafNode name="related"> + <properties> + <help>Related state</help> + <completionHelp> + <list>enable disable</list> + </completionHelp> + <valueHelp> + <format>enable</format> + <description>Enable</description> + </valueHelp> + <valueHelp> + <format>disable</format> + <description>Disable</description> + </valueHelp> + <constraint> + <regex>(enable|disable)</regex> + </constraint> + </properties> + </leafNode> + </children> +</node> +#include <include/firewall/tcp-flags.xml.i> +<node name="time"> + <properties> + <help>Time to match rule</help> + </properties> + <children> + <leafNode name="monthdays"> + <properties> + <help>Monthdays to match rule on</help> + </properties> + </leafNode> + <leafNode name="startdate"> + <properties> + <help>Date to start matching rule</help> + </properties> + </leafNode> + <leafNode name="starttime"> + <properties> + <help>Time of day to start matching rule</help> + </properties> + </leafNode> + <leafNode name="stopdate"> + <properties> + <help>Date to stop matching rule</help> + </properties> + </leafNode> + <leafNode name="stoptime"> + <properties> + <help>Time of day to stop matching rule</help> + </properties> + </leafNode> + <leafNode name="utc"> + <properties> + <help>Interpret times for startdate, stopdate, starttime and stoptime to be UTC</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="weekdays"> + <properties> + <help>Weekdays to match rule on</help> + </properties> + </leafNode> + </children> +</node> +<node name="icmpv6"> + <properties> + <help>ICMPv6 type and code information</help> + </properties> + <children> + <leafNode name="type"> + <properties> + <help>ICMP type-name</help> + <completionHelp> + <list>any echo-reply pong destination-unreachable network-unreachable host-unreachable protocol-unreachable port-unreachable fragmentation-needed source-route-failed network-unknown host-unknown network-prohibited host-prohibited TOS-network-unreachable TOS-host-unreachable communication-prohibited host-precedence-violation precedence-cutoff source-quench redirect network-redirect host-redirect TOS-network-redirect TOS host-redirect echo-request ping router-advertisement router-solicitation time-exceeded ttl-exceeded ttl-zero-during-transit ttl-zero-during-reassembly parameter-problem ip-header-bad required-option-missing timestamp-request timestamp-reply address-mask-request address-mask-reply packet-too-big</list> + </completionHelp> + <valueHelp> + <format>any</format> + <description>Any ICMP type/code</description> + </valueHelp> + <valueHelp> + <format>echo-reply</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>pong</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>destination-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>network-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>host-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>protocol-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>port-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>fragmentation-needed</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>source-route-failed</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>network-unknown</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>host-unknown</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>network-prohibited</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>host-prohibited</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>TOS-network-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>TOS-host-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>communication-prohibited</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>host-precedence-violation</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>precedence-cutoff</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>source-quench</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>redirect</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>network-redirect</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>host-redirect</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>TOS-network-redirect</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>TOS host-redirect</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>echo-request</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>ping</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>router-advertisement</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>router-solicitation</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>time-exceeded</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>ttl-exceeded</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>ttl-zero-during-transit</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>ttl-zero-during-reassembly</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>parameter-problem</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>ip-header-bad</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>required-option-missing</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>timestamp-request</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>timestamp-reply</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>address-mask-request</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>address-mask-reply</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>packet-too-big</format> + <description>ICMP type/code name</description> + </valueHelp> + <constraint> + <regex>(any|echo-reply|pong|destination-unreachable|network-unreachable|host-unreachable|protocol-unreachable|port-unreachable|fragmentation-needed|source-route-failed|network-unknown|host-unknown|network-prohibited|host-prohibited|TOS-network-unreachable|TOS-host-unreachable|communication-prohibited|host-precedence-violation|precedence-cutoff|source-quench|redirect|network-redirect|host-redirect|TOS-network-redirect|TOS host-redirect|echo-request|ping|router-advertisement|router-solicitation|time-exceeded|ttl-exceeded|ttl-zero-during-transit|ttl-zero-during-reassembly|parameter-problem|ip-header-bad|required-option-missing|timestamp-request|timestamp-reply|address-mask-request|address-mask-reply|packet-too-big)</regex> + <validator name="numeric" argument="--range 0-255"/> + </constraint> + </properties> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/policy/route-common-rule.xml.i b/interface-definitions/include/policy/route-common-rule.xml.i new file mode 100644 index 000000000..5a17dbc95 --- /dev/null +++ b/interface-definitions/include/policy/route-common-rule.xml.i @@ -0,0 +1,402 @@ +<!-- include start from policy/route-common-rule.xml.i --> +#include <include/policy/route-rule-action.xml.i> +#include <include/generic-description.xml.i> +<leafNode name="disable"> + <properties> + <help>Option to disable firewall rule</help> + <valueless/> + </properties> +</leafNode> +<node name="fragment"> + <properties> + <help>IP fragment match</help> + </properties> + <children> + <leafNode name="match-frag"> + <properties> + <help>Second and further fragments of fragmented packets</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="match-non-frag"> + <properties> + <help>Head fragments or unfragmented packets</help> + <valueless/> + </properties> + </leafNode> + </children> +</node> +<node name="ipsec"> + <properties> + <help>Inbound IPsec packets</help> + </properties> + <children> + <leafNode name="match-ipsec"> + <properties> + <help>Inbound IPsec packets</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="match-none"> + <properties> + <help>Inbound non-IPsec packets</help> + <valueless/> + </properties> + </leafNode> + </children> +</node> +<node name="limit"> + <properties> + <help>Rate limit using a token bucket filter</help> + </properties> + <children> + <leafNode name="burst"> + <properties> + <help>Maximum number of packets to allow in excess of rate</help> + <valueHelp> + <format>u32:0-4294967295</format> + <description>Maximum number of packets to allow in excess of rate</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + </properties> + </leafNode> + <leafNode name="rate"> + <properties> + <help>Maximum average matching rate</help> + <valueHelp> + <format>u32:0-4294967295</format> + <description>Maximum average matching rate</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + </properties> + </leafNode> + </children> +</node> +<leafNode name="log"> + <properties> + <help>Option to log packets matching rule</help> + <completionHelp> + <list>enable disable</list> + </completionHelp> + <valueHelp> + <format>enable</format> + <description>Enable log</description> + </valueHelp> + <valueHelp> + <format>disable</format> + <description>Disable log</description> + </valueHelp> + <constraint> + <regex>(enable|disable)</regex> + </constraint> + </properties> +</leafNode> +<leafNode name="protocol"> + <properties> + <help>Protocol to match (protocol name, number, or "all")</help> + <completionHelp> + <script>cat /etc/protocols | sed -e '/^#.*/d' | awk '{ print $1 }'</script> + </completionHelp> + <valueHelp> + <format>all</format> + <description>All IP protocols</description> + </valueHelp> + <valueHelp> + <format>tcp_udp</format> + <description>Both TCP and UDP</description> + </valueHelp> + <valueHelp> + <format>0-255</format> + <description>IP protocol number</description> + </valueHelp> + <valueHelp> + <format>!<protocol></format> + <description>IP protocol number</description> + </valueHelp> + <constraint> + <validator name="ip-protocol"/> + </constraint> + </properties> + <defaultValue>all</defaultValue> +</leafNode> +<node name="recent"> + <properties> + <help>Parameters for matching recently seen sources</help> + </properties> + <children> + <leafNode name="count"> + <properties> + <help>Source addresses seen more than N times</help> + <valueHelp> + <format>u32:1-255</format> + <description>Source addresses seen more than N times</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-255"/> + </constraint> + </properties> + </leafNode> + <leafNode name="time"> + <properties> + <help>Source addresses seen in the last N seconds</help> + <valueHelp> + <format>u32:0-4294967295</format> + <description>Source addresses seen in the last N seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + </properties> + </leafNode> + </children> +</node> +<node name="set"> + <properties> + <help>Packet modifications</help> + </properties> + <children> + <leafNode name="dscp"> + <properties> + <help>Packet Differentiated Services Codepoint (DSCP)</help> + <valueHelp> + <format>u32:0-63</format> + <description>DSCP number</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-63"/> + </constraint> + </properties> + </leafNode> + <leafNode name="mark"> + <properties> + <help>Packet marking</help> + <valueHelp> + <format>u32:1-2147483647</format> + <description>Packet marking</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-2147483647"/> + </constraint> + </properties> + </leafNode> + <leafNode name="table"> + <properties> + <help>Routing table to forward packet with</help> + <valueHelp> + <format>u32:1-200</format> + <description>Table number</description> + </valueHelp> + <valueHelp> + <format>main</format> + <description>Main table</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-200"/> + <regex>(main)</regex> + </constraint> + </properties> + </leafNode> + <leafNode name="tcp-mss"> + <properties> + <help>TCP Maximum Segment Size</help> + <valueHelp> + <format>u32:500-1460</format> + <description>Explicitly set TCP MSS value</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 500-1460"/> + </constraint> + </properties> + </leafNode> + </children> +</node> +<node name="source"> + <properties> + <help>Source parameters</help> + </properties> + <children> + #include <include/firewall/address.xml.i> + #include <include/firewall/source-destination-group.xml.i> + <leafNode name="mac-address"> + <properties> + <help>Source MAC address</help> + <valueHelp> + <format><MAC address></format> + <description>MAC address to match</description> + </valueHelp> + <valueHelp> + <format>!<MAC address></format> + <description>Match everything except the specified MAC address</description> + </valueHelp> + <constraint> + <validator name="mac-address-firewall"/> + </constraint> + </properties> + </leafNode> + #include <include/firewall/port.xml.i> + </children> +</node> +<node name="state"> + <properties> + <help>Session state</help> + </properties> + <children> + <leafNode name="established"> + <properties> + <help>Established state</help> + <completionHelp> + <list>enable disable</list> + </completionHelp> + <valueHelp> + <format>enable</format> + <description>Enable</description> + </valueHelp> + <valueHelp> + <format>disable</format> + <description>Disable</description> + </valueHelp> + <constraint> + <regex>(enable|disable)</regex> + </constraint> + </properties> + </leafNode> + <leafNode name="invalid"> + <properties> + <help>Invalid state</help> + <completionHelp> + <list>enable disable</list> + </completionHelp> + <valueHelp> + <format>enable</format> + <description>Enable</description> + </valueHelp> + <valueHelp> + <format>disable</format> + <description>Disable</description> + </valueHelp> + <constraint> + <regex>(enable|disable)</regex> + </constraint> + </properties> + </leafNode> + <leafNode name="new"> + <properties> + <help>New state</help> + <completionHelp> + <list>enable disable</list> + </completionHelp> + <valueHelp> + <format>enable</format> + <description>Enable</description> + </valueHelp> + <valueHelp> + <format>disable</format> + <description>Disable</description> + </valueHelp> + <constraint> + <regex>(enable|disable)</regex> + </constraint> + </properties> + </leafNode> + <leafNode name="related"> + <properties> + <help>Related state</help> + <completionHelp> + <list>enable disable</list> + </completionHelp> + <valueHelp> + <format>enable</format> + <description>Enable</description> + </valueHelp> + <valueHelp> + <format>disable</format> + <description>Disable</description> + </valueHelp> + <constraint> + <regex>(enable|disable)</regex> + </constraint> + </properties> + </leafNode> + </children> +</node> +#include <include/firewall/tcp-flags.xml.i> +<node name="time"> + <properties> + <help>Time to match rule</help> + </properties> + <children> + <leafNode name="monthdays"> + <properties> + <help>Monthdays to match rule on</help> + </properties> + </leafNode> + <leafNode name="startdate"> + <properties> + <help>Date to start matching rule</help> + </properties> + </leafNode> + <leafNode name="starttime"> + <properties> + <help>Time of day to start matching rule</help> + </properties> + </leafNode> + <leafNode name="stopdate"> + <properties> + <help>Date to stop matching rule</help> + </properties> + </leafNode> + <leafNode name="stoptime"> + <properties> + <help>Time of day to stop matching rule</help> + </properties> + </leafNode> + <leafNode name="utc"> + <properties> + <help>Interpret times for startdate, stopdate, starttime and stoptime to be UTC</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="weekdays"> + <properties> + <help>Weekdays to match rule on</help> + </properties> + </leafNode> + </children> +</node> +<node name="icmp"> + <properties> + <help>ICMP type and code information</help> + </properties> + <children> + <leafNode name="code"> + <properties> + <help>ICMP code (0-255)</help> + <valueHelp> + <format>u32:0-255</format> + <description>ICMP code (0-255)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-255"/> + </constraint> + </properties> + </leafNode> + <leafNode name="type"> + <properties> + <help>ICMP type (0-255)</help> + <valueHelp> + <format>u32:0-255</format> + <description>ICMP type (0-255)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-255"/> + </constraint> + </properties> + </leafNode> + #include <include/firewall/icmp-type-name.xml.i> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/policy/route-rule-action.xml.i b/interface-definitions/include/policy/route-rule-action.xml.i new file mode 100644 index 000000000..1217055f2 --- /dev/null +++ b/interface-definitions/include/policy/route-rule-action.xml.i @@ -0,0 +1,17 @@ +<!-- include start from policy/route-rule-action.xml.i --> +<leafNode name="action"> + <properties> + <help>Rule action [REQUIRED]</help> + <completionHelp> + <list>drop</list> + </completionHelp> + <valueHelp> + <format>drop</format> + <description>Drop matching entries</description> + </valueHelp> + <constraint> + <regex>(drop)</regex> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/bandwidth.xml.i b/interface-definitions/include/qos/bandwidth.xml.i new file mode 100644 index 000000000..82af22f42 --- /dev/null +++ b/interface-definitions/include/qos/bandwidth.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/bandwidth.xml.i --> +<leafNode name="bandwidth"> + <properties> + <help>Traffic-limit used for this class</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number><suffix></format> + <description>Rate with scaling suffix (mbit, mbps, ...)</description> + </valueHelp> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/burst.xml.i b/interface-definitions/include/qos/burst.xml.i new file mode 100644 index 000000000..761618027 --- /dev/null +++ b/interface-definitions/include/qos/burst.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/burst.xml.i --> +<leafNode name="burst"> + <properties> + <help>Burst size for this class</help> + <valueHelp> + <format><number></format> + <description>Bytes</description> + </valueHelp> + <valueHelp> + <format><number><suffix></format> + <description>Bytes with scaling suffix (kb, mb, gb)</description> + </valueHelp> + </properties> + <defaultValue>15k</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/codel-quantum.xml.i b/interface-definitions/include/qos/codel-quantum.xml.i new file mode 100644 index 000000000..bc24630b6 --- /dev/null +++ b/interface-definitions/include/qos/codel-quantum.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/codel-quantum.xml.i --> +<leafNode name="codel-quantum"> + <properties> + <help>Deficit in the fair queuing algorithm</help> + <valueHelp> + <format>u32:0-1048576</format> + <description>Number of bytes used as 'deficit'</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-1048576"/> + </constraint> + <constraintErrorMessage>Interval must be in range 0 to 1048576</constraintErrorMessage> + </properties> + <defaultValue>1514</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/dscp.xml.i b/interface-definitions/include/qos/dscp.xml.i new file mode 100644 index 000000000..bb90850ac --- /dev/null +++ b/interface-definitions/include/qos/dscp.xml.i @@ -0,0 +1,143 @@ +<!-- include start from qos/dscp.xml.i --> +<leafNode name="dscp"> + <properties> + <help>Match on Differentiated Services Codepoint (DSCP)</help> + <completionHelp> + <list>default reliability throughput lowdelay priority immediate flash flash-override critical internet network AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43 CS1 CS2 CS3 CS4 CS5 CS6 CS7 EF</list> + </completionHelp> + <valueHelp> + <format>u32:0-63</format> + <description>Differentiated Services Codepoint (DSCP) value </description> + </valueHelp> + <valueHelp> + <format>default</format> + <description>match DSCP (000000)</description> + </valueHelp> + <valueHelp> + <format>reliability</format> + <description>match DSCP (000001)</description> + </valueHelp> + <valueHelp> + <format>throughput</format> + <description>match DSCP (000010)</description> + </valueHelp> + <valueHelp> + <format>lowdelay</format> + <description>match DSCP (000100)</description> + </valueHelp> + <valueHelp> + <format>priority</format> + <description>match DSCP (001000)</description> + </valueHelp> + <valueHelp> + <format>immediate</format> + <description>match DSCP (010000)</description> + </valueHelp> + <valueHelp> + <format>flash</format> + <description>match DSCP (011000)</description> + </valueHelp> + <valueHelp> + <format>flash-override</format> + <description>match DSCP (100000)</description> + </valueHelp> + <valueHelp> + <format>critical</format> + <description>match DSCP (101000)</description> + </valueHelp> + <valueHelp> + <format>internet</format> + <description>match DSCP (110000)</description> + </valueHelp> + <valueHelp> + <format>network</format> + <description>match DSCP (111000)</description> + </valueHelp> + <valueHelp> + <format>AF11</format> + <description>High-throughput data</description> + </valueHelp> + <valueHelp> + <format>AF12</format> + <description>High-throughput data</description> + </valueHelp> + <valueHelp> + <format>AF13</format> + <description>High-throughput data</description> + </valueHelp> + <valueHelp> + <format>AF21</format> + <description>Low-latency data</description> + </valueHelp> + <valueHelp> + <format>AF22</format> + <description>Low-latency data</description> + </valueHelp> + <valueHelp> + <format>AF23</format> + <description>Low-latency data</description> + </valueHelp> + <valueHelp> + <format>AF31</format> + <description>Multimedia streaming</description> + </valueHelp> + <valueHelp> + <format>AF32</format> + <description>Multimedia streaming</description> + </valueHelp> + <valueHelp> + <format>AF33</format> + <description>Multimedia streaming</description> + </valueHelp> + <valueHelp> + <format>AF41</format> + <description>Multimedia conferencing</description> + </valueHelp> + <valueHelp> + <format>AF42</format> + <description>Multimedia conferencing</description> + </valueHelp> + <valueHelp> + <format>AF43</format> + <description>Multimedia conferencing</description> + </valueHelp> + <valueHelp> + <format>CS1</format> + <description>Low-priority data</description> + </valueHelp> + <valueHelp> + <format>CS2</format> + <description>OAM</description> + </valueHelp> + <valueHelp> + <format>CS3</format> + <description>Broadcast video</description> + </valueHelp> + <valueHelp> + <format>CS4</format> + <description>Real-time interactive</description> + </valueHelp> + <valueHelp> + <format>CS5</format> + <description>Signaling</description> + </valueHelp> + <valueHelp> + <format>CS6</format> + <description>Network control</description> + </valueHelp> + <valueHelp> + <format>CS7</format> + <description></description> + </valueHelp> + <valueHelp> + <format>EF</format> + <description>Expedited Forwarding</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-63"/> + <regex>(default|reliability|throughput|lowdelay|priority|immediate|flash|flash-override|critical|internet|network|AF11|AF12|AF13|AF21|AF22|AF23|AF31|AF32|AF33|AF41|AF42|AF43|CS1|CS2|CS3|CS4|CS5|CS6|CS7|EF)</regex> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 63</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/flows.xml.i b/interface-definitions/include/qos/flows.xml.i new file mode 100644 index 000000000..a7d7c6422 --- /dev/null +++ b/interface-definitions/include/qos/flows.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/flows.xml.i --> +<leafNode name="flows"> + <properties> + <help>Number of flows into which the incoming packets are classified</help> + <valueHelp> + <format>u32:1-65536</format> + <description>Number of flows</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-65536"/> + </constraint> + <constraintErrorMessage>Interval must be in range 1 to 65536</constraintErrorMessage> + </properties> + <defaultValue>1024</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/hfsc-d.xml.i b/interface-definitions/include/qos/hfsc-d.xml.i new file mode 100644 index 000000000..2a513509c --- /dev/null +++ b/interface-definitions/include/qos/hfsc-d.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/hfsc-d.xml.i --> +<leafNode name="d"> + <properties> + <help>Service curve delay</help> + <valueHelp> + <format><number></format> + <description>Time in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 65535</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/hfsc-m1.xml.i b/interface-definitions/include/qos/hfsc-m1.xml.i new file mode 100644 index 000000000..749d01f57 --- /dev/null +++ b/interface-definitions/include/qos/hfsc-m1.xml.i @@ -0,0 +1,32 @@ +<!-- include start from qos/hfsc-m1.xml.i --> +<leafNode name="m1"> + <properties> + <help>Linkshare m1 parameter for class traffic</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number>%%</format> + <description>Percentage of overall rate</description> + </valueHelp> + <valueHelp> + <format><number>bit</format> + <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> + </valueHelp> + <valueHelp> + <format><number>ibit</format> + <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> + </valueHelp> + <valueHelp> + <format><number>ibps</format> + <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> + </valueHelp> + <valueHelp> + <format><number>bps</format> + <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + </valueHelp> + </properties> + <defaultValue>100%</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/hfsc-m2.xml.i b/interface-definitions/include/qos/hfsc-m2.xml.i new file mode 100644 index 000000000..24e8f5d63 --- /dev/null +++ b/interface-definitions/include/qos/hfsc-m2.xml.i @@ -0,0 +1,32 @@ +<!-- include start from qos/hfsc-m2.xml.i --> +<leafNode name="m2"> + <properties> + <help>Linkshare m2 parameter for class traffic</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number>%%</format> + <description>Percentage of overall rate</description> + </valueHelp> + <valueHelp> + <format><number>bit</format> + <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> + </valueHelp> + <valueHelp> + <format><number>ibit</format> + <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> + </valueHelp> + <valueHelp> + <format><number>ibps</format> + <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> + </valueHelp> + <valueHelp> + <format><number>bps</format> + <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + </valueHelp> + </properties> + <defaultValue>100%</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/interval.xml.i b/interface-definitions/include/qos/interval.xml.i new file mode 100644 index 000000000..41896ac9c --- /dev/null +++ b/interface-definitions/include/qos/interval.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/interval.xml.i --> +<leafNode name="interval"> + <properties> + <help>Interval used to measure the delay</help> + <valueHelp> + <format>u32</format> + <description>Interval in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + <constraintErrorMessage>Interval must be in range 0 to 4294967295</constraintErrorMessage> + </properties> + <defaultValue>100</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/match.xml.i b/interface-definitions/include/qos/match.xml.i new file mode 100644 index 000000000..7d89e4460 --- /dev/null +++ b/interface-definitions/include/qos/match.xml.i @@ -0,0 +1,221 @@ +<!-- include start from qos/match.xml.i --> +<tagNode name="match"> + <properties> + <help>Class matching rule name</help> + <constraint> + <regex>[^-].*</regex> + </constraint> + <constraintErrorMessage>Match queue name cannot start with hyphen (-)</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <node name="ether"> + <properties> + <help>Ethernet header match</help> + </properties> + <children> + <leafNode name="destination"> + <properties> + <help>Ethernet destination address for this match</help> + <valueHelp> + <format>macaddr</format> + <description>MAC address to match</description> + </valueHelp> + <constraint> + <validator name="mac-address"/> + </constraint> + </properties> + </leafNode> + <leafNode name="protocol"> + <properties> + <help>Ethernet protocol for this match</help> + <!-- this refers to /etc/protocols --> + <completionHelp> + <list>all 802.1Q 802_2 802_3 aarp aoe arp atalk dec ip ipv6 ipx lat localtalk rarp snap x25</list> + </completionHelp> + <valueHelp> + <format>u32:0-65535</format> + <description>Ethernet protocol number</description> + </valueHelp> + <valueHelp> + <format>txt</format> + <description>Ethernet protocol name</description> + </valueHelp> + <valueHelp> + <format>all</format> + <description>Any protocol</description> + </valueHelp> + <valueHelp> + <format>ip</format> + <description>Internet IP (IPv4)</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>Internet IP (IPv6)</description> + </valueHelp> + <valueHelp> + <format>arp</format> + <description>Address Resolution Protocol</description> + </valueHelp> + <valueHelp> + <format>atalk</format> + <description>Appletalk</description> + </valueHelp> + <valueHelp> + <format>ipx</format> + <description>Novell Internet Packet Exchange</description> + </valueHelp> + <valueHelp> + <format>802.1Q</format> + <description>802.1Q VLAN tag</description> + </valueHelp> + <constraint> + <validator name="ip-protocol"/> + </constraint> + </properties> + </leafNode> + <leafNode name="source"> + <properties> + <help>Ethernet source address for this match</help> + <valueHelp> + <format>macaddr</format> + <description>MAC address to match</description> + </valueHelp> + <constraint> + <validator name="mac-address"/> + </constraint> + </properties> + </leafNode> + </children> + </node> + #include <include/generic-interface.xml.i> + <node name="ip"> + <properties> + <help>Match IP protocol header</help> + </properties> + <children> + <node name="destination"> + <properties> + <help>Match on destination port or address</help> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv4 destination address for this match</help> + <valueHelp> + <format>ipv4net</format> + <description>IPv4 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ipv4"/> + </constraint> + </properties> + </leafNode> + #include <include/port-number.xml.i> + </children> + </node> + #include <include/qos/dscp.xml.i> + #include <include/qos/max-length.xml.i> + #include <include/ip-protocol.xml.i> + <node name="source"> + <properties> + <help>Match on source port or address</help> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv4 source address for this match</help> + <valueHelp> + <format>ipv4net</format> + <description>IPv4 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ipv4"/> + </constraint> + </properties> + </leafNode> + #include <include/port-number.xml.i> + </children> + </node> + #include <include/qos/tcp-flags.xml.i> + </children> + </node> + <node name="ipv6"> + <properties> + <help>Match IPv6 protocol header</help> + </properties> + <children> + <node name="destination"> + <properties> + <help>Match on destination port or address</help> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv6 destination address for this match</help> + <valueHelp> + <format>ipv6net</format> + <description>IPv6 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ipv6"/> + </constraint> + </properties> + </leafNode> + #include <include/port-number.xml.i> + </children> + </node> + #include <include/qos/dscp.xml.i> + #include <include/qos/max-length.xml.i> + #include <include/ip-protocol.xml.i> + <node name="source"> + <properties> + <help>Match on source port or address</help> + </properties> + <children> + <leafNode name="address"> + <properties> + <help>IPv6 source address for this match</help> + <valueHelp> + <format>ipv6net</format> + <description>IPv6 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ipv6"/> + </constraint> + </properties> + </leafNode> + #include <include/port-number.xml.i> + </children> + </node> + #include <include/qos/tcp-flags.xml.i> + </children> + </node> + <leafNode name="mark"> + <properties> + <help>Match on mark applied by firewall</help> + <valueHelp> + <format>txt</format> + <description>FW mark to match</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0x0-0xffff"/> + </constraint> + </properties> + </leafNode> + <leafNode name="vif"> + <properties> + <help>Virtual Local Area Network (VLAN) ID for this match</help> + <valueHelp> + <format>u32:0-4095</format> + <description>Virtual Local Area Network (VLAN) tag </description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4095"/> + </constraint> + <constraintErrorMessage>VLAN ID must be between 0 and 4095</constraintErrorMessage> + </properties> + </leafNode> + </children> +</tagNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/max-length.xml.i b/interface-definitions/include/qos/max-length.xml.i new file mode 100644 index 000000000..4cc20f8c4 --- /dev/null +++ b/interface-definitions/include/qos/max-length.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/max-length.xml.i --> +<leafNode name="max-length"> + <properties> + <help>Maximum packet length (ipv4)</help> + <valueHelp> + <format>u32:0-65535</format> + <description>Maximum packet/payload length</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + <constraintErrorMessage>Maximum IPv4 total packet length is 65535</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/queue-limit-1-4294967295.xml.i b/interface-definitions/include/qos/queue-limit-1-4294967295.xml.i new file mode 100644 index 000000000..2f2d44631 --- /dev/null +++ b/interface-definitions/include/qos/queue-limit-1-4294967295.xml.i @@ -0,0 +1,15 @@ +<!-- include start from qos/queue-limit-1-4294967295.xml.i --> +<leafNode name="queue-limit"> + <properties> + <help>Maximum queue size</help> + <valueHelp> + <format>u32:1-4294967295</format> + <description>Queue size in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4294967295"/> + </constraint> + <constraintErrorMessage>Queue limit must be greater than zero</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/queue-limit-2-10999.xml.i b/interface-definitions/include/qos/queue-limit-2-10999.xml.i new file mode 100644 index 000000000..7a9c8266b --- /dev/null +++ b/interface-definitions/include/qos/queue-limit-2-10999.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/queue-limit.xml.i --> +<leafNode name="queue-limit"> + <properties> + <help>Upper limit of the queue</help> + <valueHelp> + <format>u32:2-10999</format> + <description>Queue size in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 2-10999"/> + </constraint> + <constraintErrorMessage>Queue limit must greater than 1 and less than 11000</constraintErrorMessage> + </properties> + <defaultValue>10240</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/queue-type.xml.i b/interface-definitions/include/qos/queue-type.xml.i new file mode 100644 index 000000000..634f61024 --- /dev/null +++ b/interface-definitions/include/qos/queue-type.xml.i @@ -0,0 +1,30 @@ +<!-- include start from qos/queue-type.xml.i --> +<leafNode name="queue-type"> + <properties> + <help>Queue type for default traffic</help> + <completionHelp> + <list>fq-codel fair-queue drop-tail random-detect</list> + </completionHelp> + <valueHelp> + <format>fq-codel</format> + <description>Fair Queue Codel</description> + </valueHelp> + <valueHelp> + <format>fair-queue</format> + <description>Stochastic Fair Queue (SFQ)</description> + </valueHelp> + <valueHelp> + <format>drop-tail</format> + <description>First-In-First-Out (FIFO)</description> + </valueHelp> + <valueHelp> + <format>random-detect</format> + <description>Random Early Detection (RED)</description> + </valueHelp> + <constraint> + <regex>(fq-codel|fair-queue|drop-tail|random-detect)</regex> + </constraint> + </properties> + <defaultValue>drop-tail</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/set-dscp.xml.i b/interface-definitions/include/qos/set-dscp.xml.i new file mode 100644 index 000000000..55c0ea44d --- /dev/null +++ b/interface-definitions/include/qos/set-dscp.xml.i @@ -0,0 +1,63 @@ +<!-- include start from qos/set-dscp.xml.i --> +<leafNode name="set-dscp"> + <properties> + <help>Change the Differentiated Services (DiffServ) field in the IP header</help> + <completionHelp> + <list>default reliability throughput lowdelay priority immediate flash flash-override critical internet network</list> + </completionHelp> + <valueHelp> + <format>u32:0-63</format> + <description>Priority order for bandwidth pool</description> + </valueHelp> + <valueHelp> + <format>default</format> + <description>match DSCP (000000)</description> + </valueHelp> + <valueHelp> + <format>reliability</format> + <description>match DSCP (000001)</description> + </valueHelp> + <valueHelp> + <format>throughput</format> + <description>match DSCP (000010)</description> + </valueHelp> + <valueHelp> + <format>lowdelay</format> + <description>match DSCP (000100)</description> + </valueHelp> + <valueHelp> + <format>priority</format> + <description>match DSCP (001000)</description> + </valueHelp> + <valueHelp> + <format>immediate</format> + <description>match DSCP (010000)</description> + </valueHelp> + <valueHelp> + <format>flash</format> + <description>match DSCP (011000)</description> + </valueHelp> + <valueHelp> + <format>flash-override</format> + <description>match DSCP (100000)</description> + </valueHelp> + <valueHelp> + <format>critical</format> + <description>match DSCP (101000)</description> + </valueHelp> + <valueHelp> + <format>internet</format> + <description>match DSCP (110000)</description> + </valueHelp> + <valueHelp> + <format>network</format> + <description>match DSCP (111000)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-63"/> + <regex>(default|reliability|throughput|lowdelay|priority|immediate|flash|flash-override|critical|internet|network)</regex> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 63</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/target.xml.i b/interface-definitions/include/qos/target.xml.i new file mode 100644 index 000000000..bf6342ac9 --- /dev/null +++ b/interface-definitions/include/qos/target.xml.i @@ -0,0 +1,16 @@ +<!-- include start from qos/target.xml.i --> +<leafNode name="target"> + <properties> + <help>Acceptable minimum standing/persistent queue delay</help> + <valueHelp> + <format>u32</format> + <description>Queue delay in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4294967295"/> + </constraint> + <constraintErrorMessage>Delay must be in range 0 to 4294967295</constraintErrorMessage> + </properties> + <defaultValue>5</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/qos/tcp-flags.xml.i b/interface-definitions/include/qos/tcp-flags.xml.i new file mode 100644 index 000000000..81d70d1f3 --- /dev/null +++ b/interface-definitions/include/qos/tcp-flags.xml.i @@ -0,0 +1,21 @@ +<!-- include start from qos/tcp-flags.xml.i --> +<node name="tcp"> + <properties> + <help>TCP Flags matching</help> + </properties> + <children> + <leafNode name="ack"> + <properties> + <help>Match TCP ACK</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="syn"> + <properties> + <help>Match TCP SYN</help> + <valueless/> + </properties> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/radius-server-port.xml.i b/interface-definitions/include/radius-server-port.xml.i index 4e5d906bc..c6b691a0f 100644 --- a/interface-definitions/include/radius-server-port.xml.i +++ b/interface-definitions/include/radius-server-port.xml.i @@ -4,7 +4,7 @@ <help>Authentication port</help> <valueHelp> <format>u32:1-65535</format> - <description>Numeric IP port (default: 1812)</description> + <description>Numeric IP port</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-65535"/> diff --git a/interface-definitions/include/rip/rip-timers.xml.i b/interface-definitions/include/rip/rip-timers.xml.i index 3aaaf8e65..129d9ed23 100644 --- a/interface-definitions/include/rip/rip-timers.xml.i +++ b/interface-definitions/include/rip/rip-timers.xml.i @@ -9,7 +9,7 @@ <help>Garbage collection timer</help> <valueHelp> <format>u32:5-2147483647</format> - <description>Garbage colletion time (default 120)</description> + <description>Garbage colletion time</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 5-2147483647"/> @@ -22,7 +22,7 @@ <help>Routing information timeout timer</help> <valueHelp> <format>u32:5-2147483647</format> - <description>Routing information timeout timer (default 180)</description> + <description>Routing information timeout timer</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 5-2147483647"/> @@ -35,7 +35,7 @@ <help>Routing table update timer</help> <valueHelp> <format>u32:5-2147483647</format> - <description>Routing table update timer in seconds (default 30)</description> + <description>Routing table update timer in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 5-2147483647"/> diff --git a/interface-definitions/include/route-map.xml.i b/interface-definitions/include/route-map.xml.i index 88092b7d4..019868373 100644 --- a/interface-definitions/include/route-map.xml.i +++ b/interface-definitions/include/route-map.xml.i @@ -10,7 +10,7 @@ <description>Route map name</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9.]+$</regex> + <regex>[-_a-zA-Z0-9.]+</regex> </constraint> <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> diff --git a/interface-definitions/include/routing-passive-interface.xml.i b/interface-definitions/include/routing-passive-interface.xml.i index 43dfb5e44..095b683de 100644 --- a/interface-definitions/include/routing-passive-interface.xml.i +++ b/interface-definitions/include/routing-passive-interface.xml.i @@ -15,7 +15,7 @@ <description>Default to suppress routing updates on all interfaces</description> </valueHelp> <constraint> - <regex>^(default)$</regex> + <regex>(default)</regex> <validator name="interface-name"/> </constraint> <multi/> diff --git a/interface-definitions/include/snmp/access-mode.xml.i b/interface-definitions/include/snmp/access-mode.xml.i new file mode 100644 index 000000000..7469805ac --- /dev/null +++ b/interface-definitions/include/snmp/access-mode.xml.i @@ -0,0 +1,23 @@ +<!-- include start from snmp/access-mode.xml.i --> +<leafNode name="mode"> + <properties> + <help>Define access permission</help> + <completionHelp> + <list>ro rw</list> + </completionHelp> + <valueHelp> + <format>ro</format> + <description>Read-Only</description> + </valueHelp> + <valueHelp> + <format>rw</format> + <description>read write</description> + </valueHelp> + <constraint> + <regex>(ro|rw)</regex> + </constraint> + <constraintErrorMessage>Authorization type must be either 'rw' or 'ro'</constraintErrorMessage> + </properties> + <defaultValue>ro</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/snmp/authentication-type.xml.i b/interface-definitions/include/snmp/authentication-type.xml.i new file mode 100644 index 000000000..047d8cff4 --- /dev/null +++ b/interface-definitions/include/snmp/authentication-type.xml.i @@ -0,0 +1,22 @@ +<!-- include start from snmp/authentication-type.xml.i --> +<leafNode name="type"> + <properties> + <help>Define used protocol</help> + <completionHelp> + <list>md5 sha</list> + </completionHelp> + <valueHelp> + <format>md5</format> + <description>Message Digest 5</description> + </valueHelp> + <valueHelp> + <format>sha</format> + <description>Secure Hash Algorithm</description> + </valueHelp> + <constraint> + <regex>(md5|sha)</regex> + </constraint> + </properties> + <defaultValue>md5</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/snmp/privacy-type.xml.i b/interface-definitions/include/snmp/privacy-type.xml.i new file mode 100644 index 000000000..d5fd1e811 --- /dev/null +++ b/interface-definitions/include/snmp/privacy-type.xml.i @@ -0,0 +1,22 @@ +<!-- include start from snmp/privacy-type.xml.i --> +<leafNode name="type"> + <properties> + <help>Defines the protocol for privacy</help> + <completionHelp> + <list>des aes</list> + </completionHelp> + <valueHelp> + <format>des</format> + <description>Data Encryption Standard</description> + </valueHelp> + <valueHelp> + <format>aes</format> + <description>Advanced Encryption Standard</description> + </valueHelp> + <constraint> + <regex>(des|aes)</regex> + </constraint> + </properties> + <defaultValue>des</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/snmp/protocol.xml.i b/interface-definitions/include/snmp/protocol.xml.i new file mode 100644 index 000000000..d7e6752ad --- /dev/null +++ b/interface-definitions/include/snmp/protocol.xml.i @@ -0,0 +1,22 @@ +<!-- include start from snmp/protocol.xml.i -->
+<leafNode name="protocol">
+ <properties>
+ <help>Protocol to be used (TCP/UDP)</help>
+ <completionHelp>
+ <list>udp tcp</list>
+ </completionHelp>
+ <valueHelp>
+ <format>udp</format>
+ <description>Listen protocol UDP</description>
+ </valueHelp>
+ <valueHelp>
+ <format>tcp</format>
+ <description>Listen protocol TCP</description>
+ </valueHelp>
+ <constraint>
+ <regex>(udp|tcp)</regex>
+ </constraint>
+ </properties>
+ <defaultValue>udp</defaultValue>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/ssh-user.xml.i b/interface-definitions/include/ssh-user.xml.i index 677602dd8..6ac1f35bc 100644 --- a/interface-definitions/include/ssh-user.xml.i +++ b/interface-definitions/include/ssh-user.xml.i @@ -3,9 +3,9 @@ <properties> <help>Allow specific users to login</help> <constraint> - <regex>[a-z_][a-z0-9_-]{1,31}[$]?</regex> + <regex>[-_a-zA-Z0-9.]{1,100}</regex> </constraint> - <constraintErrorMessage>illegal characters or more than 32 characters</constraintErrorMessage> + <constraintErrorMessage>Illegal characters or more than 100 characters</constraintErrorMessage> <multi/> </properties> </leafNode> diff --git a/interface-definitions/include/static/static-route-blackhole.xml.i b/interface-definitions/include/static/static-route-blackhole.xml.i index f2ad23e69..487f775f5 100644 --- a/interface-definitions/include/static/static-route-blackhole.xml.i +++ b/interface-definitions/include/static/static-route-blackhole.xml.i @@ -1,10 +1,11 @@ <!-- include start from static/static-route-blackhole.xml.i --> <node name="blackhole"> <properties> - <help>Silently discard packets when matched</help> + <help>Silently discard pkts when matched</help> </properties> <children> #include <include/static/static-route-distance.xml.i> + #include <include/static/static-route-tag.xml.i> </children> </node> <!-- include end --> diff --git a/interface-definitions/include/static/static-route-reject.xml.i b/interface-definitions/include/static/static-route-reject.xml.i new file mode 100644 index 000000000..81d4f9afd --- /dev/null +++ b/interface-definitions/include/static/static-route-reject.xml.i @@ -0,0 +1,12 @@ +<!-- include start from static/static-route-blackhole.xml.i --> +<node name="reject"> + <properties> + <help>Emit an ICMP unreachable when matched</help> + </properties> + <children> + #include <include/static/static-route-distance.xml.i> + #include <include/static/static-route-tag.xml.i> + </children> +</node> +<!-- include end --> + diff --git a/interface-definitions/include/static/static-route-tag.xml.i b/interface-definitions/include/static/static-route-tag.xml.i new file mode 100644 index 000000000..24bfa732e --- /dev/null +++ b/interface-definitions/include/static/static-route-tag.xml.i @@ -0,0 +1,14 @@ +<!-- include start from static/static-route-tag.xml.i --> +<leafNode name="tag"> + <properties> + <help>Tag value for this route</help> + <valueHelp> + <format>u32:1-4294967295</format> + <description>Tag value for this route</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4294967295"/> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/static/static-route-vrf.xml.i b/interface-definitions/include/static/static-route-vrf.xml.i index 69aba253c..e1968f04a 100644 --- a/interface-definitions/include/static/static-route-vrf.xml.i +++ b/interface-definitions/include/static/static-route-vrf.xml.i @@ -11,7 +11,7 @@ <description>Name of VRF to leak to</description> </valueHelp> <constraint> - <regex>^(default)$</regex> + <regex>(default)</regex> <validator name="vrf-name"/> </constraint> </properties> diff --git a/interface-definitions/include/static/static-route.xml.i b/interface-definitions/include/static/static-route.xml.i index 21babc015..2de5dc58f 100644 --- a/interface-definitions/include/static/static-route.xml.i +++ b/interface-definitions/include/static/static-route.xml.i @@ -1,7 +1,7 @@ <!-- include start from static/static-route.xml.i --> <tagNode name="route"> <properties> - <help>VRF static IPv4 route</help> + <help>Static IPv4 route</help> <valueHelp> <format>ipv4net</format> <description>IPv4 static route</description> @@ -11,26 +11,8 @@ </constraint> </properties> <children> - <node name="blackhole"> - <properties> - <help>Silently discard pkts when matched</help> - </properties> - <children> - #include <include/static/static-route-distance.xml.i> - <leafNode name="tag"> - <properties> - <help>Tag value for this route</help> - <valueHelp> - <format>u32:1-4294967295</format> - <description>Tag value for this route</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-4294967295"/> - </constraint> - </properties> - </leafNode> - </children> - </node> + #include <include/static/static-route-blackhole.xml.i> + #include <include/static/static-route-reject.xml.i> #include <include/dhcp-interface.xml.i> <tagNode name="interface"> <properties> diff --git a/interface-definitions/include/static/static-route6.xml.i b/interface-definitions/include/static/static-route6.xml.i index 0ea995588..35feef41c 100644 --- a/interface-definitions/include/static/static-route6.xml.i +++ b/interface-definitions/include/static/static-route6.xml.i @@ -1,7 +1,7 @@ <!-- include start from static/static-route6.xml.i --> <tagNode name="route6"> <properties> - <help>VRF static IPv6 route</help> + <help>Static IPv6 route</help> <valueHelp> <format>ipv6net</format> <description>IPv6 static route</description> @@ -11,26 +11,8 @@ </constraint> </properties> <children> - <node name="blackhole"> - <properties> - <help>Silently discard pkts when matched</help> - </properties> - <children> - #include <include/static/static-route-distance.xml.i> - <leafNode name="tag"> - <properties> - <help>Tag value for this route</help> - <valueHelp> - <format>u32:1-4294967295</format> - <description>Tag value for this route</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-4294967295"/> - </constraint> - </properties> - </leafNode> - </children> - </node> + #include <include/static/static-route-blackhole.xml.i> + #include <include/static/static-route-reject.xml.i> <tagNode name="interface"> <properties> <help>IPv6 gateway interface name</help> diff --git a/interface-definitions/include/version/bgp-version.xml.i b/interface-definitions/include/version/bgp-version.xml.i new file mode 100644 index 000000000..15bc5abd4 --- /dev/null +++ b/interface-definitions/include/version/bgp-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/bgp-version.xml.i --> +<syntaxVersion component='bgp' version='2'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/broadcast-relay-version.xml.i b/interface-definitions/include/version/broadcast-relay-version.xml.i new file mode 100644 index 000000000..98481f446 --- /dev/null +++ b/interface-definitions/include/version/broadcast-relay-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/broadcast-relay-version.xml.i --> +<syntaxVersion component='broadcast-relay' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/cluster-version.xml.i b/interface-definitions/include/version/cluster-version.xml.i new file mode 100644 index 000000000..621996df4 --- /dev/null +++ b/interface-definitions/include/version/cluster-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/cluster-version.xml.i --> +<syntaxVersion component='cluster' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/config-management-version.xml.i b/interface-definitions/include/version/config-management-version.xml.i new file mode 100644 index 000000000..695ba09ab --- /dev/null +++ b/interface-definitions/include/version/config-management-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/config-management-version.xml.i --> +<syntaxVersion component='config-management' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/conntrack-sync-version.xml.i b/interface-definitions/include/version/conntrack-sync-version.xml.i new file mode 100644 index 000000000..f040c29f6 --- /dev/null +++ b/interface-definitions/include/version/conntrack-sync-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/conntrack-sync-version.xml.i --> +<syntaxVersion component='conntrack-sync' version='2'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/conntrack-version.xml.i b/interface-definitions/include/version/conntrack-version.xml.i new file mode 100644 index 000000000..696f76362 --- /dev/null +++ b/interface-definitions/include/version/conntrack-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/conntrack-version.xml.i --> +<syntaxVersion component='conntrack' version='3'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/dhcp-relay-version.xml.i b/interface-definitions/include/version/dhcp-relay-version.xml.i new file mode 100644 index 000000000..75f5d5486 --- /dev/null +++ b/interface-definitions/include/version/dhcp-relay-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/dhcp-relay-version.xml.i --> +<syntaxVersion component='dhcp-relay' version='2'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/dhcp-server-version.xml.i b/interface-definitions/include/version/dhcp-server-version.xml.i new file mode 100644 index 000000000..330cb7d1b --- /dev/null +++ b/interface-definitions/include/version/dhcp-server-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/dhcp-server-version.xml.i --> +<syntaxVersion component='dhcp-server' version='6'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/dhcpv6-server-version.xml.i b/interface-definitions/include/version/dhcpv6-server-version.xml.i new file mode 100644 index 000000000..4b2cf40aa --- /dev/null +++ b/interface-definitions/include/version/dhcpv6-server-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/dhcpv6-server-version.xml.i --> +<syntaxVersion component='dhcpv6-server' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/dns-forwarding-version.xml.i b/interface-definitions/include/version/dns-forwarding-version.xml.i new file mode 100644 index 000000000..fe817940a --- /dev/null +++ b/interface-definitions/include/version/dns-forwarding-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/dns-forwarding-version.xml.i --> +<syntaxVersion component='dns-forwarding' version='3'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/firewall-version.xml.i b/interface-definitions/include/version/firewall-version.xml.i new file mode 100644 index 000000000..059a89f24 --- /dev/null +++ b/interface-definitions/include/version/firewall-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/firewall-version.xml.i --> +<syntaxVersion component='firewall' version='7'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/flow-accounting-version.xml.i b/interface-definitions/include/version/flow-accounting-version.xml.i new file mode 100644 index 000000000..5b01fe4b5 --- /dev/null +++ b/interface-definitions/include/version/flow-accounting-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/flow-accounting-version.xml.i --> +<syntaxVersion component='flow-accounting' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/https-version.xml.i b/interface-definitions/include/version/https-version.xml.i new file mode 100644 index 000000000..586083649 --- /dev/null +++ b/interface-definitions/include/version/https-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/https-version.xml.i --> +<syntaxVersion component='https' version='3'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/interfaces-version.xml.i b/interface-definitions/include/version/interfaces-version.xml.i new file mode 100644 index 000000000..0a209bc3a --- /dev/null +++ b/interface-definitions/include/version/interfaces-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/interfaces-version.xml.i --> +<syntaxVersion component='interfaces' version='26'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/ipoe-server-version.xml.i b/interface-definitions/include/version/ipoe-server-version.xml.i new file mode 100644 index 000000000..00d2544e6 --- /dev/null +++ b/interface-definitions/include/version/ipoe-server-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/ipoe-server-version.xml.i --> +<syntaxVersion component='ipoe-server' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/ipsec-version.xml.i b/interface-definitions/include/version/ipsec-version.xml.i new file mode 100644 index 000000000..59295cc91 --- /dev/null +++ b/interface-definitions/include/version/ipsec-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/ipsec-version.xml.i --> +<syntaxVersion component='ipsec' version='9'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/isis-version.xml.i b/interface-definitions/include/version/isis-version.xml.i new file mode 100644 index 000000000..4a8fef39c --- /dev/null +++ b/interface-definitions/include/version/isis-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/isis-version.xml.i --> +<syntaxVersion component='isis' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/l2tp-version.xml.i b/interface-definitions/include/version/l2tp-version.xml.i new file mode 100644 index 000000000..86114d676 --- /dev/null +++ b/interface-definitions/include/version/l2tp-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/l2tp-version.xml.i --> +<syntaxVersion component='l2tp' version='4'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/lldp-version.xml.i b/interface-definitions/include/version/lldp-version.xml.i new file mode 100644 index 000000000..0deb73279 --- /dev/null +++ b/interface-definitions/include/version/lldp-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/lldp-version.xml.i --> +<syntaxVersion component='lldp' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/mdns-version.xml.i b/interface-definitions/include/version/mdns-version.xml.i new file mode 100644 index 000000000..b200a68b4 --- /dev/null +++ b/interface-definitions/include/version/mdns-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/mdns-version.xml.i --> +<syntaxVersion component='mdns' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/nat-version.xml.i b/interface-definitions/include/version/nat-version.xml.i new file mode 100644 index 000000000..027216a07 --- /dev/null +++ b/interface-definitions/include/version/nat-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/nat-version.xml.i --> +<syntaxVersion component='nat' version='5'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/nat66-version.xml.i b/interface-definitions/include/version/nat66-version.xml.i new file mode 100644 index 000000000..7b7123dcc --- /dev/null +++ b/interface-definitions/include/version/nat66-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/nat66-version.xml.i --> +<syntaxVersion component='nat66' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/ntp-version.xml.i b/interface-definitions/include/version/ntp-version.xml.i new file mode 100644 index 000000000..cc4ff9a1c --- /dev/null +++ b/interface-definitions/include/version/ntp-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/ntp-version.xml.i --> +<syntaxVersion component='ntp' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/openconnect-version.xml.i b/interface-definitions/include/version/openconnect-version.xml.i new file mode 100644 index 000000000..654806278 --- /dev/null +++ b/interface-definitions/include/version/openconnect-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/openconnect-version.xml.i --> +<syntaxVersion component='openconnect' version='2'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/ospf-version.xml.i b/interface-definitions/include/version/ospf-version.xml.i new file mode 100644 index 000000000..755965daa --- /dev/null +++ b/interface-definitions/include/version/ospf-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/ospf-version.xml.i --> +<syntaxVersion component='ospf' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/policy-version.xml.i b/interface-definitions/include/version/policy-version.xml.i new file mode 100644 index 000000000..6d0c80518 --- /dev/null +++ b/interface-definitions/include/version/policy-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/policy-version.xml.i --> +<syntaxVersion component='policy' version='2'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/pppoe-server-version.xml.i b/interface-definitions/include/version/pppoe-server-version.xml.i new file mode 100644 index 000000000..ec81487f8 --- /dev/null +++ b/interface-definitions/include/version/pppoe-server-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/pppoe-server-version.xml.i --> +<syntaxVersion component='pppoe-server' version='5'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/pptp-version.xml.i b/interface-definitions/include/version/pptp-version.xml.i new file mode 100644 index 000000000..0296c44e9 --- /dev/null +++ b/interface-definitions/include/version/pptp-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/pptp-version.xml.i --> +<syntaxVersion component='pptp' version='2'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/qos-version.xml.i b/interface-definitions/include/version/qos-version.xml.i new file mode 100644 index 000000000..e4d139349 --- /dev/null +++ b/interface-definitions/include/version/qos-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/qos-version.xml.i --> +<syntaxVersion component='qos' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/quagga-version.xml.i b/interface-definitions/include/version/quagga-version.xml.i new file mode 100644 index 000000000..f9944acce --- /dev/null +++ b/interface-definitions/include/version/quagga-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/quagga-version.xml.i --> +<syntaxVersion component='quagga' version='10'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/rpki-version.xml.i b/interface-definitions/include/version/rpki-version.xml.i new file mode 100644 index 000000000..2fff259a8 --- /dev/null +++ b/interface-definitions/include/version/rpki-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/rpki-version.xml.i --> +<syntaxVersion component='rpki' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/salt-version.xml.i b/interface-definitions/include/version/salt-version.xml.i new file mode 100644 index 000000000..fe4684050 --- /dev/null +++ b/interface-definitions/include/version/salt-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/salt-version.xml.i --> +<syntaxVersion component='salt' version='1'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/snmp-version.xml.i b/interface-definitions/include/version/snmp-version.xml.i new file mode 100644 index 000000000..0416288f0 --- /dev/null +++ b/interface-definitions/include/version/snmp-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/snmp-version.xml.i --> +<syntaxVersion component='snmp' version='2'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/ssh-version.xml.i b/interface-definitions/include/version/ssh-version.xml.i new file mode 100644 index 000000000..0f25caf98 --- /dev/null +++ b/interface-definitions/include/version/ssh-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/ssh-version.xml.i --> +<syntaxVersion component='ssh' version='2'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/sstp-version.xml.i b/interface-definitions/include/version/sstp-version.xml.i new file mode 100644 index 000000000..79b43a3e7 --- /dev/null +++ b/interface-definitions/include/version/sstp-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/sstp-version.xml.i --> +<syntaxVersion component='sstp' version='4'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/system-version.xml.i b/interface-definitions/include/version/system-version.xml.i new file mode 100644 index 000000000..3cf92001c --- /dev/null +++ b/interface-definitions/include/version/system-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/system-version.xml.i --> +<syntaxVersion component='system' version='24'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/vrf-version.xml.i b/interface-definitions/include/version/vrf-version.xml.i new file mode 100644 index 000000000..9d7ff35fe --- /dev/null +++ b/interface-definitions/include/version/vrf-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/vrf-version.xml.i --> +<syntaxVersion component='vrf' version='3'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/vrrp-version.xml.i b/interface-definitions/include/version/vrrp-version.xml.i new file mode 100644 index 000000000..626dd6cbc --- /dev/null +++ b/interface-definitions/include/version/vrrp-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/vrrp-version.xml.i --> +<syntaxVersion component='vrrp' version='3'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/vyos-accel-ppp-version.xml.i b/interface-definitions/include/version/vyos-accel-ppp-version.xml.i new file mode 100644 index 000000000..e5a4e1613 --- /dev/null +++ b/interface-definitions/include/version/vyos-accel-ppp-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/vyos-accel-ppp-version.xml.i --> +<syntaxVersion component='vyos-accel-ppp' version='2'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/wanloadbalance-version.xml.i b/interface-definitions/include/version/wanloadbalance-version.xml.i new file mode 100644 index 000000000..59f8729cc --- /dev/null +++ b/interface-definitions/include/version/wanloadbalance-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/wanloadbalance-version.xml.i --> +<syntaxVersion component='wanloadbalance' version='3'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/version/webproxy-version.xml.i b/interface-definitions/include/version/webproxy-version.xml.i new file mode 100644 index 000000000..42dbf3f8b --- /dev/null +++ b/interface-definitions/include/version/webproxy-version.xml.i @@ -0,0 +1,3 @@ +<!-- include start from include/version/webproxy-version.xml.i --> +<syntaxVersion component='webproxy' version='2'></syntaxVersion> +<!-- include end --> diff --git a/interface-definitions/include/vpn-ipsec-encryption.xml.i b/interface-definitions/include/vpn-ipsec-encryption.xml.i index 9ef2f7c90..629e6a0b9 100644 --- a/interface-definitions/include/vpn-ipsec-encryption.xml.i +++ b/interface-definitions/include/vpn-ipsec-encryption.xml.i @@ -11,7 +11,7 @@ </valueHelp> <valueHelp> <format>aes128</format> - <description>128 bit AES-CBC (default)</description> + <description>128 bit AES-CBC</description> </valueHelp> <valueHelp> <format>aes192</format> @@ -226,8 +226,9 @@ <description>256 bit ChaCha20/Poly1305 with 128 bit ICV</description> </valueHelp> <constraint> - <regex>^(null|aes128|aes192|aes256|aes128ctr|aes192ctr|aes256ctr|aes128ccm64|aes192ccm64|aes256ccm64|aes128ccm96|aes192ccm96|aes256ccm96|aes128ccm128|aes192ccm128|aes256ccm128|aes128gcm64|aes192gcm64|aes256gcm64|aes128gcm96|aes192gcm96|aes256gcm96|aes128gcm128|aes192gcm128|aes256gcm128|aes128gmac|aes192gmac|aes256gmac|3des|blowfish128|blowfish192|blowfish256|camellia128|camellia192|camellia256|camellia128ctr|camellia192ctr|camellia256ctr|camellia128ccm64|camellia192ccm64|camellia256ccm64|camellia128ccm96|camellia192ccm96|camellia256ccm96|camellia128ccm128|camellia192ccm128|camellia256ccm128|serpent128|serpent192|serpent256|twofish128|twofish192|twofish256|cast128|chacha20poly1305)$</regex> + <regex>(null|aes128|aes192|aes256|aes128ctr|aes192ctr|aes256ctr|aes128ccm64|aes192ccm64|aes256ccm64|aes128ccm96|aes192ccm96|aes256ccm96|aes128ccm128|aes192ccm128|aes256ccm128|aes128gcm64|aes192gcm64|aes256gcm64|aes128gcm96|aes192gcm96|aes256gcm96|aes128gcm128|aes192gcm128|aes256gcm128|aes128gmac|aes192gmac|aes256gmac|3des|blowfish128|blowfish192|blowfish256|camellia128|camellia192|camellia256|camellia128ctr|camellia192ctr|camellia256ctr|camellia128ccm64|camellia192ccm64|camellia256ccm64|camellia128ccm96|camellia192ccm96|camellia256ccm96|camellia128ccm128|camellia192ccm128|camellia256ccm128|serpent128|serpent192|serpent256|twofish128|twofish192|twofish256|cast128|chacha20poly1305)</regex> </constraint> </properties> + <defaultValue>aes128</defaultValue> </leafNode> <!-- include end --> diff --git a/interface-definitions/include/vpn-ipsec-hash.xml.i b/interface-definitions/include/vpn-ipsec-hash.xml.i index 5a06b290e..73d19c24b 100644 --- a/interface-definitions/include/vpn-ipsec-hash.xml.i +++ b/interface-definitions/include/vpn-ipsec-hash.xml.i @@ -15,7 +15,7 @@ </valueHelp> <valueHelp> <format>sha1</format> - <description>SHA1 HMAC (default)</description> + <description>SHA1 HMAC</description> </valueHelp> <valueHelp> <format>sha1_160</format> @@ -58,8 +58,9 @@ <description>256-bit AES-GMAC</description> </valueHelp> <constraint> - <regex>^(md5|md5_128|sha1|sha1_160|sha256|sha256_96|sha384|sha512|aesxcbc|aescmac|aes128gmac|aes192gmac|aes256gmac)$</regex> + <regex>(md5|md5_128|sha1|sha1_160|sha256|sha256_96|sha384|sha512|aesxcbc|aescmac|aes128gmac|aes192gmac|aes256gmac)</regex> </constraint> </properties> + <defaultValue>sha1</defaultValue> </leafNode> <!-- include end --> diff --git a/interface-definitions/include/webproxy-url-filtering.xml.i b/interface-definitions/include/webproxy-url-filtering.xml.i index 265bbff94..7763cb393 100644 --- a/interface-definitions/include/webproxy-url-filtering.xml.i +++ b/interface-definitions/include/webproxy-url-filtering.xml.i @@ -38,7 +38,7 @@ <description>Default filter action is block</description> </valueHelp> <constraint> - <regex>^(allow|block)$</regex> + <regex>(allow|block)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/interfaces-bonding.xml.in b/interface-definitions/interfaces-bonding.xml.in index 17879cf1e..96dede723 100644 --- a/interface-definitions/interfaces-bonding.xml.in +++ b/interface-definitions/interfaces-bonding.xml.in @@ -7,7 +7,7 @@ <help>Bonding Interface/Link Aggregation</help> <priority>320</priority> <constraint> - <regex>^bond[0-9]+$</regex> + <regex>bond[0-9]+</regex> </constraint> <constraintErrorMessage>Bonding interface must be named bondN</constraintErrorMessage> <valueHelp> @@ -56,6 +56,8 @@ #include <include/interface/disable.xml.i> #include <include/interface/vrf.xml.i> #include <include/interface/mirror.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <leafNode name="hash-policy"> <properties> <help>Bonding transmit hash policy</help> @@ -64,7 +66,7 @@ </completionHelp> <valueHelp> <format>layer2</format> - <description>use MAC addresses to generate the hash (802.3ad, default)</description> + <description>use MAC addresses to generate the hash</description> </valueHelp> <valueHelp> <format>layer2+3</format> @@ -83,7 +85,7 @@ <description>combine encapsulated IP address and port to make hash</description> </valueHelp> <constraint> - <regex>^(layer2\+3|layer3\+4|layer2|encap2\+3|encap3\+4)$</regex> + <regex>(layer2\+3|layer3\+4|layer2|encap2\+3|encap3\+4)</regex> </constraint> <constraintErrorMessage>hash-policy must be layer2 layer2+3 layer3+4 encap2+3 or encap3+4</constraintErrorMessage> </properties> @@ -113,14 +115,14 @@ </completionHelp> <valueHelp> <format>slow</format> - <description>Request partner to transmit LACPDUs every 30 seconds (default)</description> + <description>Request partner to transmit LACPDUs every 30 seconds</description> </valueHelp> <valueHelp> <format>fast</format> <description>Request partner to transmit LACPDUs every 1 second</description> </valueHelp> <constraint> - <regex>^(slow|fast)$</regex> + <regex>(slow|fast)</regex> </constraint> </properties> <defaultValue>slow</defaultValue> @@ -133,7 +135,7 @@ </completionHelp> <valueHelp> <format>802.3ad</format> - <description>IEEE 802.3ad Dynamic link aggregation (Default)</description> + <description>IEEE 802.3ad Dynamic link aggregation</description> </valueHelp> <valueHelp> <format>active-backup</format> @@ -160,7 +162,7 @@ <description>Distribute based on MAC address</description> </valueHelp> <constraint> - <regex>^(802.3ad|active-backup|broadcast|round-robin|transmit-load-balance|adaptive-load-balance|xor-hash)$</regex> + <regex>(802.3ad|active-backup|broadcast|round-robin|transmit-load-balance|adaptive-load-balance|xor-hash)</regex> </constraint> <constraintErrorMessage>mode must be 802.3ad, active-backup, broadcast, round-robin, transmit-load-balance, adaptive-load-balance, or xor</constraintErrorMessage> </properties> @@ -205,6 +207,7 @@ </constraint> </properties> </leafNode> + #include <include/interface/redirect.xml.i> #include <include/interface/vif-s.xml.i> #include <include/interface/vif.xml.i> #include <include/interface/xdp.xml.i> diff --git a/interface-definitions/interfaces-bridge.xml.in b/interface-definitions/interfaces-bridge.xml.in index 144f43f32..60edf3ce2 100644 --- a/interface-definitions/interfaces-bridge.xml.in +++ b/interface-definitions/interfaces-bridge.xml.in @@ -7,7 +7,7 @@ <help>Bridge Interface</help> <priority>310</priority> <constraint> - <regex>^br[0-9]+$</regex> + <regex>br[0-9]+</regex> </constraint> <constraintErrorMessage>Bridge interface must be named brN</constraintErrorMessage> <valueHelp> @@ -26,7 +26,7 @@ </valueHelp> <valueHelp> <format>u32:10-1000000</format> - <description>MAC address aging time in seconds (default: 300)</description> + <description>MAC address aging time in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-0 --range 10-1000000"/> @@ -41,12 +41,14 @@ #include <include/interface/disable.xml.i> #include <include/interface/vrf.xml.i> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <leafNode name="forwarding-delay"> <properties> <help>Forwarding delay</help> <valueHelp> <format>u32:0-200</format> - <description>Spanning Tree Protocol forwarding delay in seconds (default 15)</description> + <description>Spanning Tree Protocol forwarding delay in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-200"/> @@ -57,10 +59,10 @@ </leafNode> <leafNode name="hello-time"> <properties> - <help>Hello packet advertisment interval</help> + <help>Hello packet advertisement interval</help> <valueHelp> <format>u32:1-10</format> - <description>Spanning Tree Protocol hello advertisement interval in seconds (default 2)</description> + <description>Spanning Tree Protocol hello advertisement interval in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-10"/> @@ -97,7 +99,7 @@ <help>Interval at which neighbor bridges are removed</help> <valueHelp> <format>u32:1-40</format> - <description>Bridge maximum aging time in seconds (default 20)</description> + <description>Bridge maximum aging time in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-40"/> @@ -193,7 +195,7 @@ <help>Priority for this bridge</help> <valueHelp> <format>u32:0-65535</format> - <description>Bridge priority (default 32768)</description> + <description>Bridge priority</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-65535"/> @@ -208,6 +210,7 @@ <valueless/> </properties> </leafNode> + #include <include/interface/redirect.xml.i> #include <include/interface/vif.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-dummy.xml.in b/interface-definitions/interfaces-dummy.xml.in index 2bc88c1a7..01438de31 100644 --- a/interface-definitions/interfaces-dummy.xml.in +++ b/interface-definitions/interfaces-dummy.xml.in @@ -7,7 +7,7 @@ <help>Dummy Interface</help> <priority>300</priority> <constraint> - <regex>^dum[0-9]+$</regex> + <regex>dum[0-9]+</regex> </constraint> <constraintErrorMessage>Dummy interface must be named dumN</constraintErrorMessage> <valueHelp> @@ -19,6 +19,8 @@ #include <include/interface/address-ipv4-ipv6.xml.i> #include <include/interface/description.xml.i> #include <include/interface/disable.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <node name="ip"> <properties> <help>IPv4 routing parameters</help> @@ -27,6 +29,9 @@ #include <include/interface/source-validation.xml.i> </children> </node> + #include <include/interface/mirror.xml.i> + #include <include/interface/netns.xml.i> + #include <include/interface/redirect.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-ethernet.xml.in b/interface-definitions/interfaces-ethernet.xml.in index ceeda12a0..c821f04b2 100644 --- a/interface-definitions/interfaces-ethernet.xml.in +++ b/interface-definitions/interfaces-ethernet.xml.in @@ -14,7 +14,7 @@ <description>Ethernet interface name</description> </valueHelp> <constraint> - <regex>^((eth|lan)[0-9]+|(eno|ens|enp|enx).+)$</regex> + <regex>((eth|lan)[0-9]+|(eno|ens|enp|enx).+)</regex> </constraint> <constraintErrorMessage>Invalid Ethernet interface name</constraintErrorMessage> </properties> @@ -31,6 +31,8 @@ </leafNode> #include <include/interface/disable-link-detect.xml.i> #include <include/interface/disable.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <leafNode name="duplex"> <properties> <help>Duplex mode</help> @@ -39,7 +41,7 @@ </completionHelp> <valueHelp> <format>auto</format> - <description>Auto negotiation (default)</description> + <description>Auto negotiation</description> </valueHelp> <valueHelp> <format>half</format> @@ -50,7 +52,7 @@ <description>Full duplex</description> </valueHelp> <constraint> - <regex>^(auto|half|full)$</regex> + <regex>(auto|half|full)</regex> </constraint> <constraintErrorMessage>duplex must be auto, half or full</constraintErrorMessage> </properties> @@ -108,7 +110,7 @@ </node> <leafNode name="speed"> <properties> - <help>Link speed (default: auto)</help> + <help>Link speed</help> <completionHelp> <list>auto 10 100 1000 2500 5000 10000 25000 40000 50000 100000</list> </completionHelp> @@ -157,7 +159,7 @@ <description>100 Gbit/sec</description> </valueHelp> <constraint> - <regex>^(auto|10|100|1000|2500|5000|10000|25000|40000|50000|100000)$</regex> + <regex>(auto|10|100|1000|2500|5000|10000|25000|40000|50000|100000)</regex> </constraint> <constraintErrorMessage>Speed must be auto, 10, 100, 1000, 2500, 5000, 10000, 25000, 40000, 50000 or 100000</constraintErrorMessage> </properties> @@ -194,6 +196,7 @@ </leafNode> </children> </node> + #include <include/interface/redirect.xml.i> #include <include/interface/vif-s.xml.i> #include <include/interface/vif.xml.i> #include <include/interface/vrf.xml.i> diff --git a/interface-definitions/interfaces-geneve.xml.in b/interface-definitions/interfaces-geneve.xml.in index 2ca7dd9f6..6e8a8fee2 100644 --- a/interface-definitions/interfaces-geneve.xml.in +++ b/interface-definitions/interfaces-geneve.xml.in @@ -7,7 +7,7 @@ <help>Generic Network Virtualization Encapsulation (GENEVE) Interface</help> <priority>460</priority> <constraint> - <regex>^gnv[0-9]+$</regex> + <regex>gnv[0-9]+</regex> </constraint> <constraintErrorMessage>GENEVE interface must be named gnvN</constraintErrorMessage> <valueHelp> @@ -23,6 +23,8 @@ #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> #include <include/interface/mtu-1450-16000.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <node name="parameters"> <properties> <help>GENEVE tunnel parameters</help> @@ -33,7 +35,7 @@ <help>IPv4 specific tunnel parameters</help> </properties> <children> - #include <include/interface/parameters-dont-fragment.xml.i> + #include <include/interface/parameters-df.xml.i> #include <include/interface/parameters-tos.xml.i> #include <include/interface/parameters-ttl.xml.i> </children> @@ -48,6 +50,8 @@ </node> </children> </node> + #include <include/interface/mirror.xml.i> + #include <include/interface/redirect.xml.i> #include <include/interface/tunnel-remote.xml.i> #include <include/vni.xml.i> </children> diff --git a/interface-definitions/interfaces-input.xml.in b/interface-definitions/interfaces-input.xml.in new file mode 100644 index 000000000..2164bfa4e --- /dev/null +++ b/interface-definitions/interfaces-input.xml.in @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="interfaces"> + <children> + <tagNode name="input" owner="${vyos_conf_scripts_dir}/interfaces-input.py"> + <properties> + <help>Input Functional Block (IFB) interface name</help> + <!-- before real devices that redirect --> + <priority>310</priority> + <constraint> + <regex>ifb[0-9]+</regex> + </constraint> + <constraintErrorMessage>Input interface must be named ifbN</constraintErrorMessage> + <valueHelp> + <format>ifbN</format> + <description>Input interface name</description> + </valueHelp> + </properties> + <children> + #include <include/interface/description.xml.i> + #include <include/interface/disable.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> + #include <include/interface/redirect.xml.i> + </children> + </tagNode> + </children> + </node> +</interfaceDefinition> diff --git a/interface-definitions/interfaces-l2tpv3.xml.in b/interface-definitions/interfaces-l2tpv3.xml.in index 9364c85cd..6a85064cd 100644 --- a/interface-definitions/interfaces-l2tpv3.xml.in +++ b/interface-definitions/interfaces-l2tpv3.xml.in @@ -7,7 +7,7 @@ <help>Layer 2 Tunnel Protocol Version 3 (L2TPv3) Interface</help> <priority>485</priority> <constraint> - <regex>^l2tpeth[0-9]+$</regex> + <regex>l2tpeth[0-9]+</regex> </constraint> <constraintErrorMessage>L2TPv3 interface must be named l2tpethN</constraintErrorMessage> <valueHelp> @@ -20,7 +20,7 @@ #include <include/interface/description.xml.i> <leafNode name="destination-port"> <properties> - <help>UDP destination port for L2TPv3 tunnel (default: 5000)</help> + <help>UDP destination port for L2TPv3 tunnel</help> <valueHelp> <format>u32:1-65535</format> <description>Numeric IP port</description> @@ -32,9 +32,11 @@ <defaultValue>5000</defaultValue> </leafNode> #include <include/interface/disable.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <leafNode name="encapsulation"> <properties> - <help>Encapsulation type (default: UDP)</help> + <help>Encapsulation type</help> <completionHelp> <list>udp ip</list> </completionHelp> @@ -47,7 +49,7 @@ <description>IP encapsulation</description> </valueHelp> <constraint> - <regex>^(udp|ip)$</regex> + <regex>(udp|ip)</regex> </constraint> <constraintErrorMessage>Encapsulation must be UDP or IP</constraintErrorMessage> </properties> @@ -56,6 +58,7 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/source-address-ipv4-ipv6.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-16000.xml.i> <leafNode name="mtu"> <defaultValue>1488</defaultValue> @@ -84,7 +87,6 @@ </constraint> </properties> </leafNode> - #include <include/interface/mtu-68-16000.xml.i> #include <include/interface/tunnel-remote.xml.i> <leafNode name="session-id"> <properties> @@ -100,7 +102,7 @@ </leafNode> <leafNode name="source-port"> <properties> - <help>UDP source port for L2TPv3 tunnel (default: 5000)</help> + <help>UDP source port for L2TPv3 tunnel</help> <valueHelp> <format>u32:1-65535</format> <description>Numeric IP port</description> diff --git a/interface-definitions/interfaces-loopback.xml.in b/interface-definitions/interfaces-loopback.xml.in index 7be15ab89..7f59db543 100644 --- a/interface-definitions/interfaces-loopback.xml.in +++ b/interface-definitions/interfaces-loopback.xml.in @@ -7,7 +7,7 @@ <help>Loopback Interface</help> <priority>300</priority> <constraint> - <regex>^lo$</regex> + <regex>lo</regex> </constraint> <constraintErrorMessage>Loopback interface must be named lo</constraintErrorMessage> <valueHelp> @@ -26,6 +26,8 @@ #include <include/interface/source-validation.xml.i> </children> </node> + #include <include/interface/mirror.xml.i> + #include <include/interface/redirect.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index 4a566ef8b..dbb989588 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -7,7 +7,7 @@ <help>MACsec Interface (802.1ae)</help> <priority>461</priority> <constraint> - <regex>^macsec[0-9]+$</regex> + <regex>macsec[0-9]+</regex> </constraint> <constraintErrorMessage>MACsec interface must be named macsecN</constraintErrorMessage> <valueHelp> @@ -16,9 +16,14 @@ </valueHelp> </properties> <children> - #include <include/interface/address-ipv4-ipv6.xml.i> + #include <include/interface/address-ipv4-ipv6-dhcp.xml.i> + #include <include/interface/dhcp-options.xml.i> + #include <include/interface/dhcpv6-options.xml.i> #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> + #include <include/interface/mirror.xml.i> <node name="security"> <properties> <help>Security/Encryption Settings</help> @@ -32,14 +37,14 @@ </completionHelp> <valueHelp> <format>gcm-aes-128</format> - <description>Galois/Counter Mode of AES cipher with 128-bit key (default)</description> + <description>Galois/Counter Mode of AES cipher with 128-bit key</description> </valueHelp> <valueHelp> <format>gcm-aes-256</format> <description>Galois/Counter Mode of AES cipher with 256-bit key</description> </valueHelp> <constraint> - <regex>^(gcm-aes-128|gcm-aes-256)$</regex> + <regex>(gcm-aes-128|gcm-aes-256)</regex> </constraint> </properties> </leafNode> @@ -62,7 +67,7 @@ <description>16-byte (128-bit) hex-string (32 hex-digits)</description> </valueHelp> <constraint> - <regex>^[A-Fa-f0-9]{32}$</regex> + <regex>[A-Fa-f0-9]{32}</regex> </constraint> </properties> </leafNode> @@ -74,13 +79,13 @@ <description>32-byte (256-bit) hex-string (64 hex-digits)</description> </valueHelp> <constraint> - <regex>^[A-Fa-f0-9]{64}$</regex> + <regex>[A-Fa-f0-9]{64}</regex> </constraint> </properties> </leafNode> <leafNode name="priority"> <properties> - <help>Priority of MACsec Key Agreement protocol (MKA) actor (default: 255)</help> + <help>Priority of MACsec Key Agreement protocol (MKA) actor</help> <valueHelp> <format>u32:0-255</format> <description>MACsec Key Agreement protocol (MKA) priority</description> @@ -118,6 +123,7 @@ <defaultValue>1460</defaultValue> </leafNode> #include <include/source-interface-ethernet.xml.i> + #include <include/interface/redirect.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-openvpn.xml.in b/interface-definitions/interfaces-openvpn.xml.in index 6b4440688..edcf7b37f 100644 --- a/interface-definitions/interfaces-openvpn.xml.in +++ b/interface-definitions/interfaces-openvpn.xml.in @@ -7,7 +7,7 @@ <help>OpenVPN Tunnel Interface</help> <priority>460</priority> <constraint> - <regex>^vtun[0-9]+$</regex> + <regex>vtun[0-9]+</regex> </constraint> <constraintErrorMessage>OpenVPN tunnel interface must be named vtunN</constraintErrorMessage> <valueHelp> @@ -34,9 +34,11 @@ </children> </node> #include <include/interface/description.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <leafNode name="device-type"> <properties> - <help>OpenVPN interface device-type (default: tun)</help> + <help>OpenVPN interface device-type</help> <completionHelp> <list>tun tap</list> </completionHelp> @@ -49,7 +51,7 @@ <description>TAP device, required for OSI layer 2</description> </valueHelp> <constraint> - <regex>^(tun|tap)$</regex> + <regex>(tun|tap)</regex> </constraint> </properties> <defaultValue>tun</defaultValue> @@ -111,7 +113,7 @@ <description>AES algorithm with 256-bit key GCM</description> </valueHelp> <constraint> - <regex>^(none|des|3des|bf128|bf256|aes128|aes128gcm|aes192|aes192gcm|aes256|aes256gcm)$</regex> + <regex>(none|des|3des|bf128|bf256|aes128|aes128gcm|aes192|aes192gcm|aes256|aes256gcm)</regex> </constraint> </properties> </leafNode> @@ -158,7 +160,7 @@ <description>AES algorithm with 256-bit key GCM</description> </valueHelp> <constraint> - <regex>^(none|des|3des|aes128|aes128gcm|aes192|aes192gcm|aes256|aes256gcm)$</regex> + <regex>(none|des|3des|aes128|aes128gcm|aes192|aes192gcm|aes256|aes256gcm)</regex> </constraint> <multi/> </properties> @@ -166,6 +168,7 @@ </children> </node> #include <include/interface/ipv6-options.xml.i> + #include <include/interface/mirror.xml.i> <leafNode name="hash"> <properties> <help>Hashing Algorithm</help> @@ -193,7 +196,7 @@ <description>SHA-512 algorithm</description> </valueHelp> <constraint> - <regex>^(md5|sha1|sha256|sha384|sha512)$</regex> + <regex>(md5|sha1|sha256|sha384|sha512)</regex> </constraint> </properties> </leafNode> @@ -204,7 +207,7 @@ <children> <leafNode name="failure-count"> <properties> - <help>Maximum number of keepalive packet failures (default: 60)</help> + <help>Maximum number of keepalive packet failures</help> <valueHelp> <format>u32:0-1000</format> <description>Maximum number of keepalive packet failures</description> @@ -217,7 +220,7 @@ </leafNode> <leafNode name="interval"> <properties> - <help>Keepalive packet interval in seconds (default: 10)</help> + <help>Keepalive packet interval in seconds</help> <valueHelp> <format>u32:0-600</format> <description>Keepalive packet interval (seconds)</description> @@ -295,7 +298,7 @@ <description>Server in client-server mode</description> </valueHelp> <constraint> - <regex>^(site-to-site|client|server)$</regex> + <regex>(site-to-site|client|server)</regex> </constraint> </properties> </leafNode> @@ -333,7 +336,7 @@ <description>TCP and initiates connections actively</description> </valueHelp> <constraint> - <regex>^(udp|tcp-passive|tcp-active)$</regex> + <regex>(udp|tcp-passive|tcp-active)</regex> </constraint> </properties> <defaultValue>udp</defaultValue> @@ -611,13 +614,13 @@ </leafNode> <leafNode name="topology"> <properties> - <help>Topology for clients (default: net30)</help> + <help>Topology for clients</help> <completionHelp> <list>net30 point-to-point subnet</list> </completionHelp> <valueHelp> <format>net30</format> - <description>net30 topology (default)</description> + <description>net30 topology</description> </valueHelp> <valueHelp> <format>point-to-point</format> @@ -628,7 +631,7 @@ <description>Subnet topology</description> </valueHelp> <constraint> - <regex>^(subnet|point-to-point|net30)$</regex> + <regex>(subnet|point-to-point|net30)</regex> </constraint> </properties> <defaultValue>net30</defaultValue> @@ -645,7 +648,7 @@ <children> <leafNode name="slop"> <properties> - <help>Maximum allowed clock slop in seconds (default: 180)</help> + <help>Maximum allowed clock slop in seconds</help> <valueHelp> <format>1-65535</format> <description>Seconds</description> @@ -658,7 +661,7 @@ </leafNode> <leafNode name="drift"> <properties> - <help>Time drift in seconds (default: 0)</help> + <help>Time drift in seconds</help> <valueHelp> <format>1-65535</format> <description>Seconds</description> @@ -671,7 +674,7 @@ </leafNode> <leafNode name="step"> <properties> - <help>Step value for totp in seconds (default: 30)</help> + <help>Step value for totp in seconds</help> <valueHelp> <format>1-65535</format> <description>Seconds</description> @@ -684,7 +687,7 @@ </leafNode> <leafNode name="digits"> <properties> - <help>Number of digits to use for totp hash (default: 6)</help> + <help>Number of digits to use for totp hash</help> <valueHelp> <format>1-65535</format> <description>Seconds</description> @@ -697,7 +700,7 @@ </leafNode> <leafNode name="challenge"> <properties> - <help>Expect password as result of a challenge response protocol (default: enabled)</help> + <help>Expect password as result of a challenge response protocol</help> <completionHelp> <list>disable enable</list> </completionHelp> @@ -707,10 +710,10 @@ </valueHelp> <valueHelp> <format>enable</format> - <description>Enable chalenge-response (default)</description> + <description>Enable chalenge-response</description> </valueHelp> <constraint> - <regex>^(disable|enable)$</regex> + <regex>(disable|enable)</regex> </constraint> </properties> <defaultValue>enable</defaultValue> @@ -783,7 +786,7 @@ <description>TLS v1.3</description> </valueHelp> <constraint> - <regex>^(1.0|1.1|1.2|1.3)$</regex> + <regex>(1.0|1.1|1.2|1.3)</regex> </constraint> </properties> </leafNode> @@ -802,7 +805,7 @@ <description>Wait for incoming TLS connection</description> </valueHelp> <constraint> - <regex>^(active|passive)$</regex> + <regex>(active|passive)</regex> </constraint> </properties> </leafNode> @@ -814,6 +817,7 @@ <valueless/> </properties> </leafNode> + #include <include/interface/redirect.xml.i> #include <include/interface/vrf.xml.i> </children> </tagNode> diff --git a/interface-definitions/interfaces-pppoe.xml.in b/interface-definitions/interfaces-pppoe.xml.in index 57bb01258..664914baa 100644 --- a/interface-definitions/interfaces-pppoe.xml.in +++ b/interface-definitions/interfaces-pppoe.xml.in @@ -7,7 +7,7 @@ <help>Point-to-Point Protocol over Ethernet (PPPoE)</help> <priority>322</priority> <constraint> - <regex>^pppoe[0-9]+$</regex> + <regex>pppoe[0-9]+</regex> </constraint> <constraintErrorMessage>PPPoE interface must be named pppoeN</constraintErrorMessage> <valueHelp> @@ -19,35 +19,13 @@ #include <include/pppoe-access-concentrator.xml.i> #include <include/interface/authentication.xml.i> #include <include/interface/dial-on-demand.xml.i> - <leafNode name="default-route"> - <properties> - <help>Default route insertion behaviour (default: auto)</help> - <completionHelp> - <list>auto none force</list> - </completionHelp> - <constraint> - <regex>^(auto|none|force)$</regex> - </constraint> - <constraintErrorMessage>PPPoE default-route option must be 'auto', 'none', or 'force'</constraintErrorMessage> - <valueHelp> - <format>auto</format> - <description>Automatically install a default route</description> - </valueHelp> - <valueHelp> - <format>none</format> - <description>Do not install a default route</description> - </valueHelp> - <valueHelp> - <format>force</format> - <description>Replace existing default route</description> - </valueHelp> - </properties> - <defaultValue>auto</defaultValue> - </leafNode> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> + #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/interface/disable.xml.i> - #include <include/interface/vrf.xml.i> <leafNode name="idle-timeout"> <properties> <help>Delay before disconnecting idle session (in seconds)</help> @@ -101,6 +79,7 @@ </constraint> </properties> </leafNode> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-1500.xml.i> <leafNode name="mtu"> <defaultValue>1492</defaultValue> @@ -127,11 +106,13 @@ <properties> <help>Service name, only connect to access concentrators advertising this</help> <constraint> - <regex>[a-zA-Z0-9]+$</regex> + <regex>[a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Service name must be alphanumeric only</constraintErrorMessage> </properties> </leafNode> + #include <include/interface/redirect.xml.i> + #include <include/interface/vrf.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-pseudo-ethernet.xml.in b/interface-definitions/interfaces-pseudo-ethernet.xml.in index 366892032..6b62f4c61 100644 --- a/interface-definitions/interfaces-pseudo-ethernet.xml.in +++ b/interface-definitions/interfaces-pseudo-ethernet.xml.in @@ -7,7 +7,7 @@ <help>Pseudo Ethernet</help> <priority>321</priority> <constraint> - <regex>^peth[0-9]+$</regex> + <regex>peth[0-9]+</regex> </constraint> <constraintErrorMessage>Pseudo Ethernet interface must be named pethN</constraintErrorMessage> <valueHelp> @@ -27,6 +27,9 @@ #include <include/interface/ipv6-options.xml.i> #include <include/source-interface-ethernet.xml.i> #include <include/interface/mac.xml.i> + #include <include/interface/mirror.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <leafNode name="mode"> <properties> <help>Receive mode (default: private)</help> @@ -50,13 +53,14 @@ <description>Promicious mode passthrough of underlying device</description> </valueHelp> <constraint> - <regex>^(private|vepa|bridge|passthru)$</regex> + <regex>(private|vepa|bridge|passthru)</regex> </constraint> <constraintErrorMessage>mode must be private, vepa, bridge or passthru</constraintErrorMessage> </properties> <defaultValue>private</defaultValue> </leafNode> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/redirect.xml.i> #include <include/interface/vif-s.xml.i> #include <include/interface/vif.xml.i> </children> diff --git a/interface-definitions/interfaces-tunnel.xml.in b/interface-definitions/interfaces-tunnel.xml.in index cca732f82..98ff878ba 100644 --- a/interface-definitions/interfaces-tunnel.xml.in +++ b/interface-definitions/interfaces-tunnel.xml.in @@ -7,7 +7,7 @@ <help>Tunnel interface</help> <priority>380</priority> <constraint> - <regex>^tun[0-9]+$</regex> + <regex>tun[0-9]+</regex> </constraint> <constraintErrorMessage>tunnel interface must be named tunN</constraintErrorMessage> <valueHelp> @@ -20,7 +20,6 @@ #include <include/interface/address-ipv4-ipv6.xml.i> #include <include/interface/disable.xml.i> #include <include/interface/disable-link-detect.xml.i> - #include <include/interface/vrf.xml.i> #include <include/interface/mtu-64-8024.xml.i> <leafNode name="mtu"> <defaultValue>1476</defaultValue> @@ -30,6 +29,8 @@ #include <include/source-address-ipv4-ipv6.xml.i> #include <include/interface/tunnel-remote.xml.i> #include <include/source-interface.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <leafNode name="6rd-prefix"> <properties> <help>6rd network prefix</help> @@ -66,46 +67,47 @@ </valueHelp> <valueHelp> <format>gre</format> - <description>Generic Routing Encapsulation</description> + <description>Generic Routing Encapsulation (network layer)</description> </valueHelp> <valueHelp> <format>gretap</format> - <description>Generic Routing Encapsulation (virtual L2 tunnel)</description> + <description>Generic Routing Encapsulation (datalink layer)</description> </valueHelp> <valueHelp> <format>ip6erspan</format> - <description>Encapsulated Remote Switched Port Analyzer over IPv6 network</description> + <description>Encapsulated Remote Switched Port Analyzer over IPv6</description> </valueHelp> <valueHelp> <format>ip6gre</format> - <description>GRE over IPv6 network</description> + <description>GRE over IPv6 (network layer)</description> </valueHelp> <valueHelp> <format>ip6gretap</format> - <description>Generic Routing Encapsulation over IPv6 (virtual L2 tunnel)</description> + <description>GRE over IPv6 (datalink layer)</description> </valueHelp> <valueHelp> <format>ip6ip6</format> - <description>IP6 in IP6 encapsulation</description> + <description>IPv6 in IPv6 encapsulation</description> </valueHelp> <valueHelp> <format>ipip</format> - <description>IP in IP encapsulation</description> + <description>IPv4 in IPv4 encapsulation</description> </valueHelp> <valueHelp> <format>ipip6</format> - <description>IP in IP6 encapsulation</description> + <description>IPv4 in IP6 encapsulation</description> </valueHelp> <valueHelp> <format>sit</format> - <description>Simple Internet Transition encapsulation</description> + <description>Simple Internet Transition (IPv6 in IPv4)</description> </valueHelp> <constraint> - <regex>^(erspan|gre|gretap|ip6erspan|ip6gre|ip6gretap|ip6ip6|ipip|ipip6|sit)$</regex> + <regex>(erspan|gre|gretap|ip6erspan|ip6gre|ip6gretap|ip6ip6|ipip|ipip6|sit)</regex> </constraint> <constraintErrorMessage>Invalid encapsulation, must be one of: erspan, gre, gretap, ip6erspan, ip6gre, ip6gretap, ipip, sit, ipip6 or ip6ip6</constraintErrorMessage> </properties> </leafNode> + #include <include/interface/mirror.xml.i> <leafNode name="multicast"> <properties> <help>Multicast operation over tunnel</help> @@ -114,14 +116,14 @@ </completionHelp> <valueHelp> <format>enable</format> - <description>Enable Multicast</description> + <description>Enable multicast</description> </valueHelp> <valueHelp> <format>disable</format> - <description>Disable Multicast (default)</description> + <description>Disable multicast (default)</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> <constraintErrorMessage>Must be 'disable' or 'enable'</constraintErrorMessage> </properties> @@ -133,34 +135,34 @@ <children> <node name="erspan"> <properties> - <help>ERSPAN Tunnel parameters</help> + <help>ERSPAN tunnel parameters</help> </properties> <children> <leafNode name="direction"> <properties> - <help>Specifies mirrored traffic direction</help> + <help>Mirrored traffic direction</help> <completionHelp> <list>ingress egress</list> </completionHelp> <valueHelp> <format>ingress</format> - <description>Mirror ingress direction</description> + <description>Mirror ingress traffic</description> </valueHelp> <valueHelp> <format>egress</format> - <description>Mirror egress direction</description> + <description>Mirror egress traffic</description> </valueHelp> <constraint> - <regex>^(ingress|egress)$</regex> + <regex>(ingress|egress)</regex> </constraint> </properties> </leafNode> <leafNode name="hw-id"> <properties> - <help>Unique identifier of ERSPAN engine within a system</help> + <help>Unique identifier of an ERSPAN engine within a system</help> <valueHelp> <format>u32:0-1048575</format> - <description>Unique identifier of ERSPAN engine</description> + <description>Unique identifier of an ERSPAN engine</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-1048575"/> @@ -169,7 +171,7 @@ </leafNode> <leafNode name="index"> <properties> - <help>Specifify ERSPAN version 1 index field</help> + <help>ERSPAN version 1 index field</help> <valueHelp> <format>u32:0-63</format> <description>Platform-depedent field for specifying port number and direction</description> @@ -203,18 +205,18 @@ </node> <node name="ip"> <properties> - <help>IPv4 specific tunnel parameters</help> + <help>IPv4-specific tunnel parameters</help> </properties> <children> <leafNode name="no-pmtu-discovery"> <properties> - <help>Disable Path MTU Discovery on this tunnel</help> + <help>Disable path MTU discovery</help> <valueless/> </properties> </leafNode> <leafNode name="ignore-df"> <properties> - <help>Enable IPv4 DF suppression on this tunnel</help> + <help>Ignore the DF (don't fragment) bit</help> <valueless/> </properties> </leafNode> @@ -228,7 +230,7 @@ </node> <node name="ipv6"> <properties> - <help>IPv6 specific tunnel parameters</help> + <help>IPv6-specific tunnel parameters</help> </properties> <children> <leafNode name="encaplimit"> @@ -239,14 +241,14 @@ </completionHelp> <valueHelp> <format>u32:0-255</format> - <description>Encaplimit (default: 4)</description> + <description>Encapsulation limit</description> </valueHelp> <valueHelp> <format>none</format> - <description>Encaplimit disabled</description> + <description>Disable encapsulation limit</description> </valueHelp> <constraint> - <regex>^(none)$</regex> + <regex>(none)</regex> <validator name="numeric" argument="--range 0-255"/> </constraint> <constraintErrorMessage>Tunnel encaplimit must be 0-255 or none</constraintErrorMessage> @@ -259,12 +261,12 @@ <help>Hoplimit</help> <valueHelp> <format>u32:0-255</format> - <description>Hoplimit (default 64)</description> + <description>Hop limit</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-255"/> </constraint> - <constraintErrorMessage>hoplimit must be between 0-255</constraintErrorMessage> + <constraintErrorMessage>hop limit must be between 0-255</constraintErrorMessage> </properties> <defaultValue>64</defaultValue> </leafNode> @@ -286,6 +288,8 @@ </node> </children> </node> + #include <include/interface/vrf.xml.i> + #include <include/interface/redirect.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-vti.xml.in b/interface-definitions/interfaces-vti.xml.in index b12434ae7..b471c3b92 100644 --- a/interface-definitions/interfaces-vti.xml.in +++ b/interface-definitions/interfaces-vti.xml.in @@ -7,7 +7,7 @@ <help>Virtual Tunnel interface</help> <priority>381</priority> <constraint> - <regex>^vti[0-9]+$</regex> + <regex>vti[0-9]+</regex> </constraint> <constraintErrorMessage>VTI interface must be named vtiN</constraintErrorMessage> <valueHelp> @@ -34,7 +34,11 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/mirror.xml.i> + #include <include/interface/redirect.xml.i> #include <include/interface/vrf.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in index 0a8a88596..faa3dd5e0 100644 --- a/interface-definitions/interfaces-vxlan.xml.in +++ b/interface-definitions/interfaces-vxlan.xml.in @@ -7,7 +7,7 @@ <help>Virtual Extensible LAN (VXLAN) Interface</help> <priority>460</priority> <constraint> - <regex>^vxlan[0-9]+$</regex> + <regex>vxlan[0-9]+</regex> </constraint> <constraintErrorMessage>VXLAN interface must be named vxlanN</constraintErrorMessage> <valueHelp> @@ -19,6 +19,18 @@ #include <include/interface/address-ipv4-ipv6.xml.i> #include <include/interface/description.xml.i> #include <include/interface/disable.xml.i> + <leafNode name="external"> + <properties> + <help>Use external control plane</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="gpe"> + <properties> + <help>Enable Generic Protocol extension (VXLAN-GPE)</help> + <valueless/> + </properties> + </leafNode> <leafNode name="group"> <properties> <help>Multicast group address for VXLAN interface</help> @@ -41,6 +53,9 @@ #include <include/interface/ipv6-options.xml.i> #include <include/interface/mac.xml.i> #include <include/interface/mtu-1200-16000.xml.i> + #include <include/interface/mirror.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <leafNode name="mtu"> <defaultValue>1450</defaultValue> </leafNode> @@ -54,7 +69,7 @@ <help>IPv4 specific tunnel parameters</help> </properties> <children> - #include <include/interface/parameters-dont-fragment.xml.i> + #include <include/interface/parameters-df.xml.i> #include <include/interface/parameters-tos.xml.i> #include <include/interface/parameters-ttl.xml.i> <leafNode name="ttl"> @@ -84,7 +99,8 @@ </leafNode> #include <include/source-address-ipv4-ipv6.xml.i> #include <include/source-interface.xml.i> - #include <include/interface/tunnel-remote.xml.i> + #include <include/interface/tunnel-remote-multi.xml.i> + #include <include/interface/redirect.xml.i> #include <include/interface/vrf.xml.i> #include <include/vni.xml.i> </children> diff --git a/interface-definitions/interfaces-wireguard.xml.in b/interface-definitions/interfaces-wireguard.xml.in index 403282e5c..4a1b4ac68 100644 --- a/interface-definitions/interfaces-wireguard.xml.in +++ b/interface-definitions/interfaces-wireguard.xml.in @@ -7,7 +7,7 @@ <help>WireGuard Interface</help> <priority>459</priority> <constraint> - <regex>^wg[0-9]+$</regex> + <regex>wg[0-9]+</regex> </constraint> <constraintErrorMessage>WireGuard interface must be named wgN</constraintErrorMessage> <valueHelp> @@ -19,9 +19,11 @@ #include <include/interface/address-ipv4-ipv6.xml.i> #include <include/interface/description.xml.i> #include <include/interface/disable.xml.i> - #include <include/interface/vrf.xml.i> #include <include/port-number.xml.i> #include <include/interface/mtu-68-16000.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> + #include <include/interface/mirror.xml.i> <leafNode name="mtu"> <defaultValue>1420</defaultValue> </leafNode> @@ -44,7 +46,7 @@ <properties> <help>Base64 encoded private key</help> <constraint> - <regex>[0-9a-zA-Z\+/]{43}=$</regex> + <regex>[0-9a-zA-Z\+/]{43}=</regex> </constraint> <constraintErrorMessage>Key is not valid 44-character (32-bytes) base64</constraintErrorMessage> </properties> @@ -53,7 +55,7 @@ <properties> <help>peer alias</help> <constraint> - <regex>[^ ]{1,100}$</regex> + <regex>[^ ]{1,100}</regex> </constraint> <constraintErrorMessage>peer alias too long (limit 100 characters)</constraintErrorMessage> </properties> @@ -63,7 +65,7 @@ <properties> <help>base64 encoded public key</help> <constraint> - <regex>[0-9a-zA-Z\+/]{43}=$</regex> + <regex>[0-9a-zA-Z\+/]{43}=</regex> </constraint> <constraintErrorMessage>Key is not valid 44-character (32-bytes) base64</constraintErrorMessage> </properties> @@ -72,7 +74,7 @@ <properties> <help>base64 encoded preshared key</help> <constraint> - <regex>[0-9a-zA-Z\+/]{43}=$</regex> + <regex>[0-9a-zA-Z\+/]{43}=</regex> </constraint> <constraintErrorMessage>Key is not valid 44-character (32-bytes) base64</constraintErrorMessage> </properties> @@ -99,6 +101,7 @@ </valueHelp> <constraint> <validator name="ip-address"/> + <validator name="ipv6-link-local"/> </constraint> </properties> </leafNode> @@ -117,6 +120,8 @@ </leafNode> </children> </tagNode> + #include <include/interface/redirect.xml.i> + #include <include/interface/vrf.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in index 048c7b475..eb6107303 100644 --- a/interface-definitions/interfaces-wireless.xml.in +++ b/interface-definitions/interfaces-wireless.xml.in @@ -6,8 +6,11 @@ <properties> <help>Wireless (WiFi/WLAN) Network Interface</help> <priority>318</priority> + <completionHelp> + <script>cd /sys/class/net; if compgen -G "wlan*" > /dev/null; then ls -d wlan*; fi</script> + </completionHelp> <constraint> - <regex>^wlan[0-9]+$</regex> + <regex>wlan[0-9]+</regex> </constraint> <constraintErrorMessage>Wireless interface must be named wlanN</constraintErrorMessage> <valueHelp> @@ -17,6 +20,8 @@ </properties> <children> #include <include/interface/address-ipv4-ipv6-dhcp.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> <node name="capabilities"> <properties> <help>HT and VHT capabilities for your card</help> @@ -58,7 +63,7 @@ <description>Supported channel set width both 20 MHz and 40 MHz with secondary channel below primary channel</description> </valueHelp> <constraint> - <regex>^(ht20|ht40\+|ht40-)$</regex> + <regex>(ht20|ht40\+|ht40-)</regex> </constraint> <multi/> </properties> @@ -108,7 +113,7 @@ <description>Set maximum A-MSDU length to 7935 octets</description> </valueHelp> <constraint> - <regex>^(3839|7935)$</regex> + <regex>(3839|7935)</regex> </constraint> </properties> </leafNode> @@ -127,7 +132,7 @@ <description>Short GI for 40 MHz</description> </valueHelp> <constraint> - <regex>^(20|40)$</regex> + <regex>(20|40)</regex> </constraint> <multi/> </properties> @@ -147,7 +152,7 @@ <description>DYNAMIC Spatial Multiplexing (SM) Power Save</description> </valueHelp> <constraint> - <regex>^(static|dynamic)$</regex> + <regex>(static|dynamic)</regex> </constraint> </properties> </leafNode> @@ -164,7 +169,7 @@ <description>Number of spacial streams that can use RX STBC</description> </valueHelp> <constraint> - <regex>^[1-3]+$</regex> + <regex>[1-3]+</regex> </constraint> <constraintErrorMessage>Invalid capability item</constraintErrorMessage> </properties> @@ -243,7 +248,7 @@ <description>Support for operation as multi user beamformee</description> </valueHelp> <constraint> - <regex>^(single-user-beamformer|single-user-beamformee|multi-user-beamformer|multi-user-beamformee)$</regex> + <regex>(single-user-beamformer|single-user-beamformee|multi-user-beamformer|multi-user-beamformee)</regex> </constraint> <multi/> </properties> @@ -289,7 +294,7 @@ </completionHelp> <valueHelp> <format>0</format> - <description>20 or 40 MHz channel width (default)</description> + <description>20 or 40 MHz channel width</description> </valueHelp> <valueHelp> <format>1</format> @@ -329,7 +334,7 @@ <description>Station can provide VHT MFB in response to VHT MRQ and unsolicited VHT MFB</description> </valueHelp> <constraint> - <regex>^(unsolicited|both)$</regex> + <regex>(unsolicited|both)</regex> </constraint> <constraintErrorMessage>Invalid capability item</constraintErrorMessage> </properties> @@ -361,7 +366,7 @@ <description>ncrease Maximum MPDU length to 11454 octets</description> </valueHelp> <constraint> - <regex>^(7991|11454)$</regex> + <regex>(7991|11454)</regex> </constraint> </properties> </leafNode> @@ -380,7 +385,7 @@ <description>Short GI for 160 MHz</description> </valueHelp> <constraint> - <regex>^(80|160)$</regex> + <regex>(80|160)</regex> </constraint> <multi/> </properties> @@ -398,7 +403,7 @@ <description>Number of spacial streams that can use RX STBC</description> </valueHelp> <constraint> - <regex>^[1-4]+$</regex> + <regex>[1-4]+</regex> </constraint> <constraintErrorMessage>Invalid capability item</constraintErrorMessage> </properties> @@ -429,7 +434,7 @@ </node> <leafNode name="channel"> <properties> - <help>Wireless radio channel (default: 0)</help> + <help>Wireless radio channel</help> <valueHelp> <format>0</format> <description>Automatic Channel Selection (ACS)</description> @@ -459,7 +464,7 @@ <description>ISO/IEC 3166-1 Country Code</description> </valueHelp> <constraint> - <regex>^[a-z][a-z]$</regex> + <regex>[a-z][a-z]</regex> </constraint> <constraintErrorMessage>Invalid ISO/IEC 3166-1 Country Code</constraintErrorMessage> </properties> @@ -513,7 +518,7 @@ </completionHelp> <valueHelp> <format>disabled</format> - <description>no MFP (hostapd default)</description> + <description>no MFP</description> </valueHelp> <valueHelp> <format>optional</format> @@ -524,9 +529,10 @@ <description>MFP enforced</description> </valueHelp> <constraint> - <regex>^(disabled|optional|required)$</regex> + <regex>(disabled|optional|required)</regex> </constraint> </properties> + <defaultValue>disabled</defaultValue> </leafNode> <leafNode name="mode"> <properties> @@ -544,7 +550,7 @@ </valueHelp> <valueHelp> <format>g</format> - <description>802.11g - 54 Mbits/sec (default)</description> + <description>802.11g - 54 Mbits/sec</description> </valueHelp> <valueHelp> <format>n</format> @@ -555,14 +561,15 @@ <description>802.11ac - 1300 Mbits/sec</description> </valueHelp> <constraint> - <regex>^(a|b|g|n|ac)$</regex> + <regex>(a|b|g|n|ac)</regex> </constraint> </properties> <defaultValue>g</defaultValue> </leafNode> + #include <include/interface/mirror.xml.i> <leafNode name="physical-device"> <properties> - <help>Wireless physical device (default: phy0)</help> + <help>Wireless physical device</help> <completionHelp> <script>${vyos_completion_dir}/list_wireless_phys.sh</script> </completionHelp> @@ -643,7 +650,7 @@ <description>Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]</description> </valueHelp> <constraint> - <regex>^(GCMP-256|GCMP|CCMP-256|CCMP|TKIP)$</regex> + <regex>(GCMP-256|GCMP|CCMP-256|CCMP|TKIP)</regex> </constraint> <constraintErrorMessage>Invalid cipher selection</constraintErrorMessage> <multi/> @@ -676,7 +683,7 @@ <description>Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]</description> </valueHelp> <constraint> - <regex>^(GCMP-256|GCMP|CCMP-256|CCMP|TKIP)$</regex> + <regex>(GCMP-256|GCMP|CCMP-256|CCMP|TKIP)</regex> </constraint> <constraintErrorMessage>Invalid group cipher selection</constraintErrorMessage> <multi/> @@ -701,7 +708,7 @@ <description>Allow both WPA and WPA2</description> </valueHelp> <constraint> - <regex>^(wpa|wpa2|wpa\+wpa2|wpa3)$</regex> + <regex>(wpa|wpa2|wpa\+wpa2|wpa3)</regex> </constraint> <constraintErrorMessage>Unknown WPA mode</constraintErrorMessage> </properties> @@ -717,7 +724,7 @@ <description>Passphrase of at least 8 but not more than 63 printable characters</description> </valueHelp> <constraint> - <regex>.{8,63}$</regex> + <regex>.{8,63}</regex> </constraint> <constraintErrorMessage>Invalid WPA pass phrase, must be 8 to 63 printable characters!</constraintErrorMessage> </properties> @@ -745,7 +752,7 @@ <properties> <help>Wireless access-point service set identifier (SSID)</help> <constraint> - <regex>.{1,32}$</regex> + <regex>.{1,32}</regex> </constraint> <constraintErrorMessage>Invalid SSID</constraintErrorMessage> </properties> @@ -769,12 +776,13 @@ <description>Passively monitor all packets on the frequency/channel</description> </valueHelp> <constraint> - <regex>^(access-point|station|monitor)$</regex> + <regex>(access-point|station|monitor)</regex> </constraint> <constraintErrorMessage>Type must be access-point, station or monitor</constraintErrorMessage> </properties> <defaultValue>monitor</defaultValue> </leafNode> + #include <include/interface/redirect.xml.i> #include <include/interface/vif.xml.i> #include <include/interface/vif-s.xml.i> </children> diff --git a/interface-definitions/interfaces-wwan.xml.in b/interface-definitions/interfaces-wwan.xml.in index 6b6fa1a66..3071e6091 100644 --- a/interface-definitions/interfaces-wwan.xml.in +++ b/interface-definitions/interfaces-wwan.xml.in @@ -7,10 +7,10 @@ <help>Wireless Modem (WWAN) Interface</help> <priority>350</priority> <completionHelp> - <script>cd /sys/class/net; ls -d wwan*</script> + <script>cd /sys/class/net; if compgen -G "wwan*" > /dev/null; then ls -d wwan*; fi</script> </completionHelp> <constraint> - <regex>^wwan[0-9]+$</regex> + <regex>wwan[0-9]+</regex> </constraint> <constraintErrorMessage>Wireless Modem interface must be named wwanN</constraintErrorMessage> <valueHelp> @@ -30,8 +30,8 @@ #include <include/interface/authentication.xml.i> #include <include/interface/description.xml.i> #include <include/interface/disable.xml.i> - #include <include/interface/vrf.xml.i> #include <include/interface/disable-link-detect.xml.i> + #include <include/interface/mirror.xml.i> #include <include/interface/mtu-68-1500.xml.i> <leafNode name="mtu"> <defaultValue>1430</defaultValue> @@ -39,6 +39,10 @@ #include <include/interface/ipv4-options.xml.i> #include <include/interface/ipv6-options.xml.i> #include <include/interface/dial-on-demand.xml.i> + #include <include/interface/interface-firewall.xml.i> + #include <include/interface/interface-policy.xml.i> + #include <include/interface/redirect.xml.i> + #include <include/interface/vrf.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/lldp.xml.in b/interface-definitions/lldp.xml.in index 32ef0ad14..b9ffe234c 100644 --- a/interface-definitions/lldp.xml.in +++ b/interface-definitions/lldp.xml.in @@ -28,7 +28,7 @@ #include <include/generic-disable-node.xml.i> <node name="location"> <properties> - <help>LLDP-MED location data [REQUIRED]</help> + <help>LLDP-MED location data</help> </properties> <children> <node name="coordinate-based"> @@ -40,6 +40,10 @@ <properties> <help>Altitude in meters</help> <valueHelp> + <format>0</format> + <description>No altitude</description> + </valueHelp> + <valueHelp> <format>[+-]<meters></format> <description>Altitude in meters</description> </valueHelp> @@ -48,13 +52,14 @@ <validator name="numeric"/> </constraint> </properties> + <defaultValue>0</defaultValue> </leafNode> <leafNode name="datum"> <properties> <help>Coordinate datum type</help> <valueHelp> <format>WGS84</format> - <description>WGS84 (default)</description> + <description>WGS84</description> </valueHelp> <valueHelp> <format>NAD83</format> @@ -69,33 +74,34 @@ </completionHelp> <constraintErrorMessage>Datum should be WGS84, NAD83, or MLLW</constraintErrorMessage> <constraint> - <regex>^(WGS84|NAD83|MLLW)$</regex> + <regex>(WGS84|NAD83|MLLW)</regex> </constraint> </properties> + <defaultValue>WGS84</defaultValue> </leafNode> <leafNode name="latitude"> <properties> - <help>Latitude [REQUIRED]</help> + <help>Latitude</help> <valueHelp> <format><latitude></format> <description>Latitude (example "37.524449N")</description> </valueHelp> <constraintErrorMessage>Latitude should be a number followed by S or N</constraintErrorMessage> <constraint> - <regex>(\d+)(\.\d+)?[nNsS]$</regex> + <regex>(\d+)(\.\d+)?[nNsS]</regex> </constraint> </properties> </leafNode> <leafNode name="longitude"> <properties> - <help>Longitude [REQUIRED]</help> + <help>Longitude</help> <valueHelp> <format><longitude></format> <description>Longitude (example "122.267255W")</description> </valueHelp> <constraintErrorMessage>Longiture should be a number followed by E or W</constraintErrorMessage> <constraint> - <regex>(\d+)(\.\d+)?[eEwW]$</regex> + <regex>(\d+)(\.\d+)?[eEwW]</regex> </constraint> </properties> </leafNode> @@ -109,7 +115,7 @@ <description>Emergency Call Service ELIN number (between 10-25 numbers)</description> </valueHelp> <constraint> - <regex>[0-9]{10,25}$</regex> + <regex>[0-9]{10,25}</regex> </constraint> <constraintErrorMessage>ELIN number must be between 10-25 numbers</constraintErrorMessage> </properties> diff --git a/interface-definitions/nat.xml.in b/interface-definitions/nat.xml.in index 3cf3ba6aa..9295b631f 100644 --- a/interface-definitions/nat.xml.in +++ b/interface-definitions/nat.xml.in @@ -18,6 +18,7 @@ <properties> <help>Inbound interface of NAT traffic</help> <completionHelp> + <list>any</list> <script>${vyos_completion_dir}/list_interfaces.py</script> </completionHelp> </properties> @@ -97,7 +98,7 @@ <validator name="ipv4-prefix"/> <validator name="ipv4-address"/> <validator name="ipv4-range"/> - <regex>^(masquerade)$</regex> + <regex>(masquerade)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/nat66.xml.in b/interface-definitions/nat66.xml.in index 11d986c96..b47f653c6 100644 --- a/interface-definitions/nat66.xml.in +++ b/interface-definitions/nat66.xml.in @@ -94,7 +94,7 @@ <constraint> <validator name="ipv6-address"/> <validator name="ipv6-prefix"/> - <regex>^(masquerade)$</regex> + <regex>(masquerade)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/netns.xml.in b/interface-definitions/netns.xml.in new file mode 100644 index 000000000..088985cb6 --- /dev/null +++ b/interface-definitions/netns.xml.in @@ -0,0 +1,23 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="netns" owner="${vyos_conf_scripts_dir}/netns.py"> + <properties> + <help>Network namespace</help> + <priority>299</priority> + </properties> + <children> + <tagNode name="name"> + <properties> + <help>Network namespace name</help> + <constraint> + <regex>[a-zA-Z0-9-_]{1,100}</regex> + </constraint> + <constraintErrorMessage>Netns name must be alphanumeric and can contain hyphens and underscores.</constraintErrorMessage> + </properties> + <children> + #include <include/interface/description.xml.i> + </children> + </tagNode> + </children> + </node> +</interfaceDefinition> diff --git a/interface-definitions/policy-local-route.xml.in b/interface-definitions/policy-local-route.xml.in index 86445b65d..d969613b1 100644 --- a/interface-definitions/policy-local-route.xml.in +++ b/interface-definitions/policy-local-route.xml.in @@ -14,7 +14,7 @@ <valueHelp> <!-- table main with prio 32766 --> <format>u32:1-32765</format> - <description>Local-route rule number (1-219)</description> + <description>Local-route rule number (1-32765)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-32765"/> @@ -70,6 +70,115 @@ <multi/> </properties> </leafNode> + <leafNode name="destination"> + <properties> + <help>Destination address or prefix</help> + <valueHelp> + <format>ipv4</format> + <description>Address to match against</description> + </valueHelp> + <valueHelp> + <format>ipv4net</format> + <description>Prefix to match against</description> + </valueHelp> + <constraint> + <validator name="ipv4-address"/> + <validator name="ip-prefix"/> + </constraint> + <multi/> + </properties> + </leafNode> + #include <include/interface/inbound-interface.xml.i> + </children> + </tagNode> + </children> + </node> + <node name="local-route6" owner="${vyos_conf_scripts_dir}/policy-local-route.py"> + <properties> + <help>IPv6 policy route of local traffic</help> + </properties> + <children> + <tagNode name="rule"> + <properties> + <help>IPv6 policy local-route rule set number</help> + <valueHelp> + <!-- table main with prio 32766 --> + <format>u32:1-32765</format> + <description>Local-route rule number (1-32765)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-32765"/> + </constraint> + </properties> + <children> + <node name="set"> + <properties> + <help>Packet modifications</help> + </properties> + <children> + <leafNode name="table"> + <properties> + <help>Routing table to forward packet with</help> + <valueHelp> + <format>u32:1-200</format> + <description>Table number</description> + </valueHelp> + <completionHelp> + <list>main</list> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + <leafNode name="fwmark"> + <properties> + <help>Match fwmark value</help> + <valueHelp> + <format>u32:1-2147483647</format> + <description>Address to match against</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-2147483647"/> + </constraint> + </properties> + </leafNode> + <leafNode name="source"> + <properties> + <help>Source address or prefix</help> + <valueHelp> + <format>ipv6</format> + <description>Address to match against</description> + </valueHelp> + <valueHelp> + <format>ipv6net</format> + <description>Prefix to match against</description> + </valueHelp> + <constraint> + <validator name="ipv6-address"/> + <validator name="ipv6-prefix"/> + </constraint> + <multi/> + </properties> + </leafNode> + <leafNode name="destination"> + <properties> + <help>Destination address or prefix</help> + <valueHelp> + <format>ipv6</format> + <description>Address to match against</description> + </valueHelp> + <valueHelp> + <format>ipv6net</format> + <description>Prefix to match against</description> + </valueHelp> + <constraint> + <validator name="ipv6-address"/> + <validator name="ipv6-prefix"/> + </constraint> + <multi/> + </properties> + </leafNode> + #include <include/interface/inbound-interface.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/policy-route.xml.in b/interface-definitions/policy-route.xml.in new file mode 100644 index 000000000..a10c9b08f --- /dev/null +++ b/interface-definitions/policy-route.xml.in @@ -0,0 +1,105 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="policy"> + <children> + <tagNode name="route6" owner="${vyos_conf_scripts_dir}/policy-route.py"> + <properties> + <help>Policy route rule set name for IPv6</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> + <priority>201</priority> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/firewall/name-default-log.xml.i> + <tagNode name="rule"> + <properties> + <help>Policy rule number</help> + <valueHelp> + <format>u32:1-999999</format> + <description>Number of policy rule</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-999999"/> + </constraint> + <constraintErrorMessage>Policy rule number must be between 1 and 999999</constraintErrorMessage> + </properties> + <children> + <node name="destination"> + <properties> + <help>Destination parameters</help> + </properties> + <children> + #include <include/firewall/address-ipv6.xml.i> + #include <include/firewall/source-destination-group-ipv6.xml.i> + #include <include/firewall/port.xml.i> + </children> + </node> + <node name="source"> + <properties> + <help>Source parameters</help> + </properties> + <children> + #include <include/firewall/address-ipv6.xml.i> + #include <include/firewall/source-destination-group-ipv6.xml.i> + #include <include/firewall/port.xml.i> + </children> + </node> + #include <include/policy/route-common-rule-ipv6.xml.i> + </children> + </tagNode> + </children> + </tagNode> + <tagNode name="route" owner="${vyos_conf_scripts_dir}/policy-route.py"> + <properties> + <help>Policy route rule set name for IPv4</help> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> + <priority>201</priority> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/firewall/name-default-log.xml.i> + <tagNode name="rule"> + <properties> + <help>Policy rule number</help> + <valueHelp> + <format>u32:1-999999</format> + <description>Number of policy rule</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-999999"/> + </constraint> + <constraintErrorMessage>Policy rule number must be between 1 and 999999</constraintErrorMessage> + </properties> + <children> + <node name="destination"> + <properties> + <help>Destination parameters</help> + </properties> + <children> + #include <include/firewall/address.xml.i> + #include <include/firewall/source-destination-group.xml.i> + #include <include/firewall/port.xml.i> + </children> + </node> + <node name="source"> + <properties> + <help>Source parameters</help> + </properties> + <children> + #include <include/firewall/address.xml.i> + #include <include/firewall/source-destination-group.xml.i> + #include <include/firewall/port.xml.i> + </children> + </node> + #include <include/policy/route-common-rule.xml.i> + </children> + </tagNode> + </children> + </tagNode> + </children> + </node> +</interfaceDefinition> diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in index 225f9a6f9..50b7cbc84 100644 --- a/interface-definitions/policy.xml.in +++ b/interface-definitions/policy.xml.in @@ -242,7 +242,7 @@ <description>BGP extended community-list name</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9]+$</regex> + <regex>[-_a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Should be an alphanumeric name</constraintErrorMessage> </properties> @@ -291,7 +291,7 @@ <description>BGP large-community-list name</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9]+$</regex> + <regex>[-_a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Should be an alphanumeric name</constraintErrorMessage> </properties> @@ -340,7 +340,7 @@ <description>Name of IPv4 prefix-list</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9]+$</regex> + <regex>[-_a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Name of prefix-list can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> @@ -408,7 +408,7 @@ <description>Name of IPv6 prefix-list</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9]+$</regex> + <regex>[-_a-zA-Z0-9]+</regex> </constraint> <constraintErrorMessage>Name of prefix-list6 can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> @@ -476,7 +476,7 @@ <description>Route map name</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9.]+$</regex> + <regex>[-_a-zA-Z0-9.]+</regex> </constraint> <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage> </properties> @@ -582,7 +582,7 @@ <description>Prefix route</description> </valueHelp> <constraint> - <regex>^(macip|multicast|prefix)$</regex> + <regex>(macip|multicast|prefix)</regex> </constraint> </properties> </leafNode> @@ -793,7 +793,7 @@ </node> <leafNode name="local-preference"> <properties> - <help>local-preference_help</help> + <help>Local Preference</help> <valueHelp> <format>u32:0-4294967295</format> <description>Local Preference</description> @@ -834,7 +834,7 @@ <description>Incomplete origin</description> </valueHelp> <constraint> - <regex>^(egp|igp|incomplete)$</regex> + <regex>(egp|igp|incomplete)</regex> </constraint> </properties> </leafNode> @@ -869,7 +869,7 @@ <description>Match valid entries</description> </valueHelp> <constraint> - <regex>^(invalid|notfound|valid)$</regex> + <regex>(invalid|notfound|valid)</regex> </constraint> </properties> </leafNode> @@ -948,24 +948,49 @@ </leafNode> </children> </node> - <leafNode name="as-path-exclude"> + <node name="as-path"> <properties> - <help>Remove ASN(s) from a Border Gateway Protocol (BGP) AS-path attribute</help> - <valueHelp> - <format>txt</format> - <description>BGP AS path exclude string (ex: "456 64500 45001")</description> - </valueHelp> - </properties> - </leafNode> - <leafNode name="as-path-prepend"> - <properties> - <help>Prepend string for a Border Gateway Protocol (BGP) AS-path attribute</help> - <valueHelp> - <format>txt</format> - <description>BGP AS path prepend string (ex: "64501 64501")</description> - </valueHelp> + <help>Transform BGP AS_PATH attribute</help> </properties> - </leafNode> + <children> + <leafNode name="exclude"> + <properties> + <help>Remove/exclude from the as-path attribute</help> + <valueHelp> + <format>u32</format> + <description>AS number</description> + </valueHelp> + <constraint> + <validator name="as-number-list"/> + </constraint> + </properties> + </leafNode> + <leafNode name="prepend"> + <properties> + <help>Prepend to the as-path</help> + <valueHelp> + <format>u32</format> + <description>AS number</description> + </valueHelp> + <constraint> + <validator name="as-number-list"/> + </constraint> + </properties> + </leafNode> + <leafNode name="prepend-last-as"> + <properties> + <help>Use the last AS-number in the as-path</help> + <valueHelp> + <format>u32:1-10</format> + <description>Number of times to insert</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-10"/> + </constraint> + </properties> + </leafNode> + </children> + </node> <leafNode name="atomic-aggregate"> <properties> <help>BGP atomic aggregate attribute</help> @@ -1045,6 +1070,44 @@ </constraint> </properties> </leafNode> + <node name="evpn"> + <properties> + <help>Ethernet Virtual Private Network</help> + </properties> + <children> + <node name="gateway"> + <properties> + <help>Set gateway IP for prefix advertisement route</help> + </properties> + <children> + <leafNode name="ipv4"> + <properties> + <help>Set gateway IPv4 address</help> + <valueHelp> + <format>ipv4</format> + <description>Gateway IPv4 address</description> + </valueHelp> + <constraint> + <validator name="ipv4-address"/> + </constraint> + </properties> + </leafNode> + <leafNode name="ipv6"> + <properties> + <help>Set gateway IPv6 address</help> + <valueHelp> + <format>ipv6</format> + <description>Gateway IPv6 address</description> + </valueHelp> + <constraint> + <validator name="ipv6-address"/> + </constraint> + </properties> + </leafNode> + </children> + </node> + </children> + </node> <node name="extcommunity"> <properties> <help>BGP extended community attribute</help> @@ -1070,7 +1133,7 @@ </valueHelp> <constraint> <validator name="numeric" argument="--range 1-25600"/> - <regex>^(cumulative|num-multipaths)$</regex> + <regex>(cumulative|num-multipaths)</regex> </constraint> </properties> </leafNode> @@ -1086,7 +1149,7 @@ <description>Based on a router-id IP address</description> </valueHelp> <constraint> - <regex>^((?:[0-9]{1,3}\.){3}[0-9]{1,3}|\d+):\d+$</regex> + <regex>(((\b(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))\b)|(\d+)):(\d+) ?)+</regex> </constraint> <constraintErrorMessage>Should be in form: ASN:NN or IPADDR:NN where ASN is autonomous system number</constraintErrorMessage> </properties> @@ -1103,7 +1166,7 @@ <description>Based on a router-id IP address</description> </valueHelp> <constraint> - <regex>^((?:[0-9]{1,3}\.){3}[0-9]{1,3}|\d+):\d+$</regex> + <regex>((?:[0-9]{1,3}\.){3}[0-9]{1,3}|\d+):\d+</regex> </constraint> <constraintErrorMessage>Should be in form: ASN:NN or IPADDR:NN where ASN is autonomous system number</constraintErrorMessage> </properties> @@ -1113,12 +1176,25 @@ <leafNode name="ip-next-hop"> <properties> <help>Nexthop IP address</help> + <completionHelp> + <script>${vyos_completion_dir}/list_local_ips.sh --ipv4</script> + <list>unchanged peer-address</list> + </completionHelp> <valueHelp> <format>ipv4</format> <description>IP address</description> </valueHelp> + <valueHelp> + <format>unchanged</format> + <description>Set the BGP nexthop address as unchanged</description> + </valueHelp> + <valueHelp> + <format>peer-address</format> + <description>Set the BGP nexthop address to the address of the peer</description> + </valueHelp> <constraint> <validator name="ipv4-address"/> + <regex>(unchanged|peer-address)</regex> </constraint> </properties> </leafNode> @@ -1130,6 +1206,9 @@ <leafNode name="global"> <properties> <help>Nexthop IPv6 global address</help> + <completionHelp> + <script>${vyos_completion_dir}/list_local_ips.sh --ipv6</script> + </completionHelp> <valueHelp> <format>ipv6</format> <description>IPv6 address and prefix length</description> @@ -1142,6 +1221,9 @@ <leafNode name="local"> <properties> <help>Nexthop IPv6 local address</help> + <completionHelp> + <script>${vyos_completion_dir}/list_local_ips.sh --ipv6</script> + </completionHelp> <valueHelp> <format>ipv6</format> <description>IPv6 address and prefix length</description> @@ -1151,6 +1233,12 @@ </constraint> </properties> </leafNode> + <leafNode name="peer-address"> + <properties> + <help>Use peer address (for BGP only)</help> + <valueless/> + </properties> + </leafNode> <leafNode name="prefer-global"> <properties> <help>Prefer global address as the nexthop</help> @@ -1226,7 +1314,7 @@ <description>OSPF external type 2 metric</description> </valueHelp> <constraint> - <regex>^(type-1|type-2)$</regex> + <regex>(type-1|type-2)</regex> </constraint> </properties> </leafNode> @@ -1249,7 +1337,7 @@ <description>Incomplete origin</description> </valueHelp> <constraint> - <regex>^(igp|egp|incomplete)$</regex> + <regex>(igp|egp|incomplete)</regex> </constraint> </properties> </leafNode> @@ -1268,6 +1356,9 @@ <leafNode name="src"> <properties> <help>Source address for route</help> + <completionHelp> + <script>${vyos_completion_dir}/list_local_ips.sh --both</script> + </completionHelp> <valueHelp> <format>ipv4</format> <description>IPv4 address</description> diff --git a/interface-definitions/protocols-bfd.xml.in b/interface-definitions/protocols-bfd.xml.in index 7b22b8125..edbac8d0e 100644 --- a/interface-definitions/protocols-bfd.xml.in +++ b/interface-definitions/protocols-bfd.xml.in @@ -26,18 +26,7 @@ </constraint> </properties> <children> - <leafNode name="profile"> - <properties> - <help>Use settings from BFD profile</help> - <completionHelp> - <path>protocols bfd profile</path> - </completionHelp> - <valueHelp> - <format>txt</format> - <description>BFD profile name</description> - </valueHelp> - </properties> - </leafNode> + #include <include/bfd/profile.xml.i> <node name="source"> <properties> <help>Bind listener to specified interface/address, mandatory for IPv6</help> @@ -66,13 +55,14 @@ </leafNode> </children> </node> - #include <include/bfd-common.xml.i> + #include <include/bfd/common.xml.i> <leafNode name="multihop"> <properties> <help>Allow this BFD peer to not be directly connected</help> <valueless/> </properties> </leafNode> + #include <include/interface/vrf.xml.i> </children> </tagNode> <tagNode name="profile"> @@ -83,11 +73,11 @@ <description>Name of BFD profile</description> </valueHelp> <constraint> - <regex>^[-_a-zA-Z0-9]{1,32}$</regex> + <regex>[-_a-zA-Z0-9]{1,32}</regex> </constraint> </properties> <children> - #include <include/bfd-common.xml.i> + #include <include/bfd/common.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/protocols-nhrp.xml.in b/interface-definitions/protocols-nhrp.xml.in index 9dd9d3389..1e08c6873 100644 --- a/interface-definitions/protocols-nhrp.xml.in +++ b/interface-definitions/protocols-nhrp.xml.in @@ -4,7 +4,7 @@ <children> <node name="nhrp" owner="${vyos_conf_scripts_dir}/protocols_nhrp.py"> <properties> - <help>NHRP parameters</help> + <help>Next Hop Resolution Protocol (NHRP) parameters</help> <priority>680</priority> </properties> <children> @@ -12,7 +12,7 @@ <properties> <help>Tunnel for NHRP [REQUIRED]</help> <constraint> - <regex>^tun[0-9]+$</regex> + <regex>tun[0-9]+</regex> </constraint> <valueHelp> <format>tunN</format> @@ -85,7 +85,7 @@ <list>dynamic nhs</list> </completionHelp> <constraint> - <regex>^(dynamic|nhs)$</regex> + <regex>(dynamic|nhs)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/protocols-ospfv3.xml.in b/interface-definitions/protocols-ospfv3.xml.in index fffeeb9a5..2b98ffa7b 100644 --- a/interface-definitions/protocols-ospfv3.xml.in +++ b/interface-definitions/protocols-ospfv3.xml.in @@ -8,226 +8,7 @@ <priority>620</priority> </properties> <children> - <tagNode name="area"> - <properties> - <help>OSPFv3 Area</help> - <valueHelp> - <format>u32</format> - <description>Area ID as a decimal value</description> - </valueHelp> - <valueHelp> - <format>ipv4</format> - <description>Area ID in IP address forma</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-4294967295"/> - <validator name="ip-address"/> - </constraint> - </properties> - <children> - <node name="area-type"> - <properties> - <help>OSPFv3 Area type</help> - </properties> - <children> - <node name="stub"> - <properties> - <help>Stub OSPFv3 area</help> - </properties> - <children> - <leafNode name="no-summary"> - <properties> - <help>Do not inject inter-area routes into the stub</help> - <valueless/> - </properties> - </leafNode> - </children> - </node> - </children> - </node> - <leafNode name="export-list"> - <properties> - <help>Name of export-list</help> - <completionHelp> - <path>policy access-list6</path> - </completionHelp> - </properties> - </leafNode> - <leafNode name="import-list"> - <properties> - <help>Name of import-list</help> - <completionHelp> - <path>policy access-list6</path> - </completionHelp> - </properties> - </leafNode> - #include <include/generic-interface-multi.xml.i> - <tagNode name="range"> - <properties> - <help>Specify IPv6 prefix (border routers only)</help> - <valueHelp> - <format>ipv6net</format> - <description>Specify IPv6 prefix (border routers only)</description> - </valueHelp> - <constraint> - <validator name="ipv6-prefix"/> - </constraint> - </properties> - <children> - <leafNode name="advertise"> - <properties> - <help>Advertise this range</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="not-advertise"> - <properties> - <help>Do not advertise this range</help> - <valueless/> - </properties> - </leafNode> - </children> - </tagNode> - </children> - </tagNode> - <node name="distance"> - <properties> - <help>Administrative distance</help> - </properties> - <children> - #include <include/ospf/distance-global.xml.i> - <node name="ospfv3"> - <properties> - <help>OSPFv3 administrative distance</help> - </properties> - <children> - #include <include/ospf/distance-per-protocol.xml.i> - </children> - </node> - </children> - </node> - <tagNode name="interface"> - <properties> - <help>Enable routing on an IPv6 interface</help> - <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> - </completionHelp> - <valueHelp> - <format>txt</format> - <description>Interface used for routing information exchange</description> - </valueHelp> - <constraint> - <validator name="interface-name"/> - </constraint> - </properties> - <children> - #include <include/ospf/intervals.xml.i> - #include <include/ospf/interface-common.xml.i> - <leafNode name="ifmtu"> - <properties> - <help>Interface MTU</help> - <valueHelp> - <format>u32:1-65535</format> - <description>Interface MTU</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-65535"/> - </constraint> - </properties> - </leafNode> - <leafNode name="instance-id"> - <properties> - <help>Instance Id (default: 0)</help> - <valueHelp> - <format>u32:0-255</format> - <description>Instance Id</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-255"/> - </constraint> - </properties> - <defaultValue>0</defaultValue> - </leafNode> - <leafNode name="network"> - <properties> - <help>Network type</help> - <completionHelp> - <list>broadcast point-to-point</list> - </completionHelp> - <valueHelp> - <format>broadcast</format> - <description>Broadcast network type</description> - </valueHelp> - <valueHelp> - <format>point-to-point</format> - <description>Point-to-point network type</description> - </valueHelp> - <constraint> - <regex>^(broadcast|point-to-point)$</regex> - </constraint> - <constraintErrorMessage>Must be broadcast or point-to-point</constraintErrorMessage> - </properties> - </leafNode> - #include <include/isis/passive.xml.i> - </children> - </tagNode> - #include <include/ospf/log-adjacency-changes.xml.i> - <node name="parameters"> - <properties> - <help>OSPFv3 specific parameters</help> - </properties> - <children> - #include <include/router-id.xml.i> - </children> - </node> - <node name="redistribute"> - <properties> - <help>Redistribute information from another routing protocol</help> - </properties> - <children> - <node name="bgp"> - <properties> - <help>Redistribute BGP routes</help> - </properties> - <children> - #include <include/route-map.xml.i> - </children> - </node> - <node name="connected"> - <properties> - <help>Redistribute connected routes</help> - </properties> - <children> - #include <include/route-map.xml.i> - </children> - </node> - <node name="kernel"> - <properties> - <help>Redistribute kernel routes</help> - </properties> - <children> - #include <include/route-map.xml.i> - </children> - </node> - <node name="ripng"> - <properties> - <help>Redistribute RIPNG routes</help> - </properties> - <children> - #include <include/route-map.xml.i> - </children> - </node> - <node name="static"> - <properties> - <help>Redistribute static routes</help> - </properties> - <children> - #include <include/route-map.xml.i> - </children> - </node> - </children> - </node> - #include <include/route-map.xml.i> + #include <include/ospfv3/protocol-common-config.xml.i> </children> </node> </children> diff --git a/interface-definitions/protocols-rip.xml.in b/interface-definitions/protocols-rip.xml.in index d3be4e1af..bbb88aef1 100644 --- a/interface-definitions/protocols-rip.xml.in +++ b/interface-definitions/protocols-rip.xml.in @@ -78,7 +78,7 @@ <description>MD5 Key (16 characters or less)</description> </valueHelp> <constraint> - <regex>^[^[:space:]]{1,16}$</regex> + <regex>[^[:space:]]{1,16}</regex> </constraint> <constraintErrorMessage>Password must be 16 characters or less</constraintErrorMessage> </properties> @@ -93,7 +93,7 @@ <description>Plain text password (16 characters or less)</description> </valueHelp> <constraint> - <regex>^[^[:space:]]{1,16}$</regex> + <regex>[^[:space:]]{1,16}</regex> </constraint> <constraintErrorMessage>Password must be 16 characters or less</constraintErrorMessage> </properties> diff --git a/interface-definitions/protocols-rpki.xml.in b/interface-definitions/protocols-rpki.xml.in index a73d0aae4..68762ff9a 100644 --- a/interface-definitions/protocols-rpki.xml.in +++ b/interface-definitions/protocols-rpki.xml.in @@ -82,7 +82,7 @@ </tagNode> <leafNode name="polling-period"> <properties> - <help>RPKI cache polling period (default: 300)</help> + <help>RPKI cache polling period</help> <valueHelp> <format>u32:1-86400</format> <description>Polling period in seconds</description> diff --git a/interface-definitions/protocols-static-arp.xml.in b/interface-definitions/protocols-static-arp.xml.in index e5e8a9ad9..8b1b3b5e1 100644 --- a/interface-definitions/protocols-static-arp.xml.in +++ b/interface-definitions/protocols-static-arp.xml.in @@ -4,32 +4,46 @@ <children> <node name="static"> <children> - <tagNode name="arp" owner="${vyos_conf_scripts_dir}/arp.py"> + <node name="arp" owner="${vyos_conf_scripts_dir}/arp.py"> <properties> <help>Static ARP translation</help> - <valueHelp> - <format>ipv4</format> - <description>IPv4 destination address</description> - </valueHelp> - <constraint> - <validator name="ipv4-address"/> - </constraint> </properties> <children> - <leafNode name="hwaddr"> + <tagNode name="interface"> <properties> - <help>Translation MAC address</help> + <help>Interface configuration</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> <valueHelp> - <format>macaddr</format> - <description>Hardware (MAC) address</description> + <format>txt</format> + <description>Interface name</description> </valueHelp> <constraint> - <validator name="mac-address"/> + <validator name="interface-name"/> </constraint> </properties> - </leafNode> + <children> + <tagNode name="address"> + <properties> + <help>IP address for static ARP entry</help> + <valueHelp> + <format>ipv4</format> + <description>IPv4 destination address</description> + </valueHelp> + <constraint> + <validator name="ipv4-address"/> + </constraint> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/interface/mac.xml.i> + </children> + </tagNode> + </children> + </tagNode> </children> - </tagNode> + </node> </children> </node> </children> diff --git a/interface-definitions/qos.xml.in b/interface-definitions/qos.xml.in new file mode 100644 index 000000000..e8f575a1e --- /dev/null +++ b/interface-definitions/qos.xml.in @@ -0,0 +1,789 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="qos" owner="${vyos_conf_scripts_dir}/qos.py"> + <properties> + <help>Quality of Service (QoS)</help> + </properties> + <children> + <tagNode name="interface"> + <properties> + <help>Interface to apply QoS policy</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>Interface name</description> + </valueHelp> + <constraint> + <validator name="interface-name"/> + </constraint> + </properties> + <children> + <leafNode name="ingress"> + <properties> + <help>Interface ingress traffic policy</help> + <completionHelp> + <path>traffic-policy drop-tail</path> + <path>traffic-policy fair-queue</path> + <path>traffic-policy fq-codel</path> + <path>traffic-policy limiter</path> + <path>traffic-policy network-emulator</path> + <path>traffic-policy priority-queue</path> + <path>traffic-policy random-detect</path> + <path>traffic-policy rate-control</path> + <path>traffic-policy round-robin</path> + <path>traffic-policy shaper</path> + <path>traffic-policy shaper-hfsc</path> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>QoS Policy name</description> + </valueHelp> + </properties> + </leafNode> + <leafNode name="egress"> + <properties> + <help>Interface egress traffic policy</help> + <completionHelp> + <path>traffic-policy drop-tail</path> + <path>traffic-policy fair-queue</path> + <path>traffic-policy fq-codel</path> + <path>traffic-policy limiter</path> + <path>traffic-policy network-emulator</path> + <path>traffic-policy priority-queue</path> + <path>traffic-policy random-detect</path> + <path>traffic-policy rate-control</path> + <path>traffic-policy round-robin</path> + <path>traffic-policy shaper</path> + <path>traffic-policy shaper-hfsc</path> + </completionHelp> + <valueHelp> + <format>txt</format> + <description>QoS Policy name</description> + </valueHelp> + </properties> + </leafNode> + </children> + </tagNode> + <node name="policy" owner="${vyos_conf_scripts_dir}/qos.py"> + <properties> + <help>Service Policy definitions</help> + <priority>900</priority> + </properties> + <children> + <tagNode name="drop-tail"> + <properties> + <help>Packet limited First In, First Out queue</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/qos/queue-limit-1-4294967295.xml.i> + </children> + </tagNode> + <tagNode name="fair-queue"> + <properties> + <help>Stochastic Fairness Queueing</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <leafNode name="hash-interval"> + <properties> + <help>Interval in seconds for queue algorithm perturbation</help> + <valueHelp> + <format>u32:0</format> + <description>No perturbation</description> + </valueHelp> + <valueHelp> + <format>u32:1-127</format> + <description>Interval in seconds for queue algorithm perturbation (advised: 10)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-127"/> + </constraint> + <constraintErrorMessage>Interval must be in range 0 to 127</constraintErrorMessage> + </properties> + <defaultValue>0</defaultValue> + </leafNode> + <leafNode name="queue-limit"> + <properties> + <help>Upper limit of the SFQ</help> + <valueHelp> + <format>u32:2-127</format> + <description>Queue size in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 2-127"/> + </constraint> + <constraintErrorMessage>Queue limit must greater than 1 and less than 128</constraintErrorMessage> + </properties> + <defaultValue>127</defaultValue> + </leafNode> + </children> + </tagNode> + <tagNode name="fq-codel"> + <properties> + <help>Fair Queuing Controlled Delay</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/qos/codel-quantum.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/queue-limit-2-10999.xml.i> + #include <include/qos/target.xml.i> + </children> + </tagNode> + <tagNode name="limiter"> + <properties> + <help>Traffic input limiting policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + <tagNode name="class"> + <properties> + <help>Class ID</help> + <valueHelp> + <format>u32:1-4090</format> + <description>Class Identifier</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4090"/> + </constraint> + <constraintErrorMessage>Class identifier must be between 1 and 4090</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/match.xml.i> + <leafNode name="priority"> + <properties> + <help>Priority for rule evaluation</help> + <valueHelp> + <format>u32:0-20</format> + <description>Priority for match rule evaluation</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-20"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 20</constraintErrorMessage> + </properties> + <defaultValue>20</defaultValue> + </leafNode> + </children> + </tagNode> + <node name="default"> + <properties> + <help>Default policy</help> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + </children> + </node> + #include <include/generic-description.xml.i> + </children> + </tagNode> + <tagNode name="network-emulator"> + <properties> + <help>Network emulator policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + #include <include/generic-description.xml.i> + <leafNode name="network-delay"> + <properties> + <help>Adds delay to packets outgoing to chosen network interface</help> + <valueHelp> + <format><number></format> + <description>Time in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 65535</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="packet-corruption"> + <properties> + <help>Introducing error in a random position for chosen percent of packets</help> + <valueHelp> + <format><number></format> + <description>Percentage of packets affected</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 100</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="packet-loss"> + <properties> + <help>Add independent loss probability to the packets outgoing to chosen network interface</help> + <valueHelp> + <format><number></format> + <description>Percentage of packets affected</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="packet-loss"> + <properties> + <help>Add independent loss probability to the packets outgoing to chosen network interface</help> + <valueHelp> + <format><number></format> + <description>Percentage of packets affected</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="packet-loss"> + <properties> + <help>Packet reordering percentage</help> + <valueHelp> + <format><number></format> + <description>Percentage of packets affected</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Must be between 0 and 100</constraintErrorMessage> + </properties> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + </children> + </tagNode> + <tagNode name="priority-queue"> + <properties> + <help>Priority queuing based policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + <tagNode name="class"> + <properties> + <help>Class Handle</help> + <valueHelp> + <format>u32:1-7</format> + <description>Priority</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-7"/> + </constraint> + <constraintErrorMessage>Class handle must be between 1 and 7</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/qos/codel-quantum.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/match.xml.i> + #include <include/qos/queue-limit-2-10999.xml.i> + #include <include/qos/target.xml.i> + #include <include/qos/queue-type.xml.i> + </children> + </tagNode> + <node name="default"> + <properties> + <help>Default policy</help> + </properties> + <children> + #include <include/generic-description.xml.i> + #include <include/qos/codel-quantum.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/queue-limit-2-10999.xml.i> + #include <include/qos/target.xml.i> + #include <include/qos/queue-type.xml.i> + </children> + </node> + #include <include/generic-description.xml.i> + </children> + </tagNode> + <tagNode name="random-detect"> + <properties> + <help>Priority queuing based policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>auto</defaultValue> + </leafNode> + #include <include/generic-description.xml.i> + <tagNode name="precedence"> + <properties> + <help>IP precedence</help> + <valueHelp> + <format>u32:0-7</format> + <description>IP precedence value</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-7"/> + </constraint> + <constraintErrorMessage>IP precedence value must be between 0 and 7</constraintErrorMessage> + </properties> + <children> + #include <include/qos/queue-limit-1-4294967295.xml.i> + <leafNode name="average-packet"> + <properties> + <help>Average packet size (bytes)</help> + <valueHelp> + <format>u32:16-10240</format> + <description>Average packet size in bytes</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-100"/> + </constraint> + <constraintErrorMessage>Average packet size must be between 16 and 10240</constraintErrorMessage> + </properties> + <defaultValue>1024</defaultValue> + </leafNode> + <leafNode name="mark-probability"> + <properties> + <help>Mark probability for this precedence</help> + <valueHelp> + <format><number></format> + <description>Numeric value (1/N)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--positive"/> + </constraint> + <constraintErrorMessage>Mark probability must be greater than 0</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="maximum-threshold"> + <properties> + <help>Maximum threshold for random detection</help> + <valueHelp> + <format>u32:0-4096</format> + <description>Maximum Threshold in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4096"/> + </constraint> + <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="minimum-threshold"> + <properties> + <help>Minimum threshold for random detection</help> + <valueHelp> + <format>u32:0-4096</format> + <description>Maximum Threshold in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4096"/> + </constraint> + <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> + </properties> + </leafNode> + </children> + </tagNode> + </children> + </tagNode> + <tagNode name="rate-control"> + <properties> + <help>Rate limiting policy (Token Bucket Filter)</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/burst.xml.i> + <leafNode name="latency"> + <properties> + <help>Maximum latency</help> + <valueHelp> + <format><number></format> + <description>Time in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-4096"/> + </constraint> + <constraintErrorMessage>Threshold must be between 0 and 4096</constraintErrorMessage> + </properties> + <defaultValue>50</defaultValue> + </leafNode> + </children> + </tagNode> + <tagNode name="round-robin"> + <properties> + <help>Round-Robin based policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <tagNode name="class"> + <properties> + <help>Class ID</help> + <valueHelp> + <format>u32:1-4095</format> + <description>Class Identifier</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4095"/> + </constraint> + <constraintErrorMessage>Class identifier must be between 1 and 4095</constraintErrorMessage> + </properties> + <children> + #include <include/qos/codel-quantum.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/match.xml.i> + <leafNode name="quantum"> + <properties> + <help>Packet scheduling quantum</help> + <valueHelp> + <format>u32:1-4294967295</format> + <description>Packet scheduling quantum (bytes)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4294967295"/> + </constraint> + <constraintErrorMessage>Quantum must be in range 1 to 4294967295</constraintErrorMessage> + </properties> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + #include <include/qos/queue-type.xml.i> + #include <include/qos/target.xml.i> + </children> + </tagNode> + </children> + </tagNode> + <tagNode name="shaper-hfsc"> + <properties> + <help>Hierarchical Fair Service Curve's policy</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>auto</defaultValue> + </leafNode> + #include <include/generic-description.xml.i> + <tagNode name="class"> + <properties> + <help>Class ID</help> + <valueHelp> + <format>u32:1-4095</format> + <description>Class Identifier</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-4095"/> + </constraint> + <constraintErrorMessage>Class identifier must be between 1 and 4095</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <node name="linkshare"> + <properties> + <help>Linkshare class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + #include <include/qos/match.xml.i> + <node name="realtime"> + <properties> + <help>Realtime class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + <node name="upperlimit"> + <properties> + <help>Upperlimit class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + </children> + </tagNode> + <node name="default"> + <properties> + <help>Default policy</help> + </properties> + <children> + <node name="linkshare"> + <properties> + <help>Linkshare class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + <node name="realtime"> + <properties> + <help>Realtime class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + <node name="upperlimit"> + <properties> + <help>Upperlimit class settings</help> + </properties> + <children> + #include <include/qos/hfsc-d.xml.i> + #include <include/qos/hfsc-m1.xml.i> + #include <include/qos/hfsc-m2.xml.i> + </children> + </node> + </children> + </node> + </children> + </tagNode> + <tagNode name="shaper"> + <properties> + <help>Traffic shaping based policy (Hierarchy Token Bucket)</help> + <valueHelp> + <format>txt</format> + <description>Policy name</description> + </valueHelp> + <constraint> + <regex>[[:alnum:]][-_[:alnum:]]*</regex> + </constraint> + <constraintErrorMessage>Only alpha-numeric policy name allowed</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>auto</defaultValue> + </leafNode> + <tagNode name="class"> + <properties> + <help>Class ID</help> + <valueHelp> + <format>u32:2-4095</format> + <description>Class Identifier</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 2-4095"/> + </constraint> + <constraintErrorMessage>Class identifier must be between 2 and 4095</constraintErrorMessage> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + <leafNode name="bandwidth"> + <defaultValue>100%</defaultValue> + </leafNode> + #include <include/qos/burst.xml.i> + <leafNode name="ceiling"> + <properties> + <help>Bandwidth limit for this class</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number>%%</format> + <description>Percentage of overall rate</description> + </valueHelp> + <valueHelp> + <format><number>bit</format> + <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> + </valueHelp> + <valueHelp> + <format><number>ibit</format> + <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> + </valueHelp> + <valueHelp> + <format><number>ibps</format> + <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> + </valueHelp> + <valueHelp> + <format><number>bps</format> + <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + </valueHelp> + </properties> + </leafNode> + #include <include/qos/codel-quantum.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + #include <include/qos/match.xml.i> + <leafNode name="priority"> + <properties> + <help>Priority for usage of excess bandwidth</help> + <valueHelp> + <format>u32:0-7</format> + <description>Priority order for bandwidth pool</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-7"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 7</constraintErrorMessage> + </properties> + <defaultValue>20</defaultValue> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + #include <include/qos/queue-type.xml.i> + #include <include/qos/set-dscp.xml.i> + #include <include/qos/target.xml.i> + </children> + </tagNode> + #include <include/generic-description.xml.i> + <node name="default"> + <properties> + <help>Default policy</help> + </properties> + <children> + #include <include/qos/bandwidth.xml.i> + #include <include/qos/burst.xml.i> + <leafNode name="ceiling"> + <properties> + <help>Bandwidth limit for this class</help> + <valueHelp> + <format><number></format> + <description>Rate in kbit (kilobit per second)</description> + </valueHelp> + <valueHelp> + <format><number>%%</format> + <description>Percentage of overall rate</description> + </valueHelp> + <valueHelp> + <format><number>bit</format> + <description>bit(1), kbit(10^3), mbit(10^6), gbit, tbit</description> + </valueHelp> + <valueHelp> + <format><number>ibit</format> + <description>kibit(1024), mibit(1024^2), gibit(1024^3), tbit(1024^4)</description> + </valueHelp> + <valueHelp> + <format><number>ibps</format> + <description>kibps(1024*8), mibps(1024^2*8), gibps, tibps - Byte/sec</description> + </valueHelp> + <valueHelp> + <format><number>bps</format> + <description>bps(8),kbps(8*10^3),mbps(8*10^6), gbps, tbps - Byte/sec</description> + </valueHelp> + </properties> + </leafNode> + #include <include/qos/codel-quantum.xml.i> + #include <include/generic-description.xml.i> + #include <include/qos/flows.xml.i> + #include <include/qos/interval.xml.i> + <leafNode name="priority"> + <properties> + <help>Priority for usage of excess bandwidth</help> + <valueHelp> + <format>u32:0-7</format> + <description>Priority order for bandwidth pool</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-7"/> + </constraint> + <constraintErrorMessage>Priority must be between 0 and 7</constraintErrorMessage> + </properties> + <defaultValue>20</defaultValue> + </leafNode> + #include <include/qos/queue-limit-1-4294967295.xml.i> + #include <include/qos/queue-type.xml.i> + #include <include/qos/set-dscp.xml.i> + #include <include/qos/target.xml.i> + </children> + </node> + </children> + </tagNode> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/interface-definitions/salt-minion.xml.in b/interface-definitions/salt-minion.xml.in index d3b022d12..c3219cff3 100644 --- a/interface-definitions/salt-minion.xml.in +++ b/interface-definitions/salt-minion.xml.in @@ -15,20 +15,25 @@ <list>md5 sha1 sha224 sha256 sha384 sha512</list> </completionHelp> <constraint> - <regex>^(md5|sha1|sha224|sha256|sha384|sha512)$</regex> + <regex>(md5|sha1|sha224|sha256|sha384|sha512)</regex> </constraint> </properties> + <defaultValue>sha256</defaultValue> </leafNode> <leafNode name="master"> <properties> - <help>The hostname or IP address of the master.</help> + <help>Hostname or IP address of the Salt master server</help> <valueHelp> <format>ipv4</format> - <description>Remote syslog server IPv4 address</description> + <description>Salt server IPv4 address</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>Salt server IPv6 address</description> </valueHelp> <valueHelp> <format>hostname</format> - <description>Remote syslog server FQDN</description> + <description>Salt server FQDN address</description> </valueHelp> <constraint> <validator name="ip-address"/> @@ -54,12 +59,14 @@ <validator name="numeric" argument="--range 1-1440"/> </constraint> </properties> + <defaultValue>60</defaultValue> </leafNode> <leafNode name="master-key"> <properties> <help>URL with signature of master for auth reply verification</help> </properties> </leafNode> + #include <include/source-interface.xml.i> </children> </node> </children> diff --git a/interface-definitions/service-ids-ddos-protection.xml.in b/interface-definitions/service-ids-ddos-protection.xml.in index ff4c1c24e..5e65d3106 100644 --- a/interface-definitions/service-ids-ddos-protection.xml.in +++ b/interface-definitions/service-ids-ddos-protection.xml.in @@ -25,7 +25,7 @@ <list>in out</list> </completionHelp> <constraint> - <regex>^(in|out)$</regex> + <regex>(in|out)</regex> </constraint> <multi/> </properties> diff --git a/interface-definitions/service_conntrack-sync.xml.in b/interface-definitions/service_conntrack-sync.xml.in index 584f687c7..6fa6fc5f9 100644 --- a/interface-definitions/service_conntrack-sync.xml.in +++ b/interface-definitions/service_conntrack-sync.xml.in @@ -5,7 +5,8 @@ <node name="conntrack-sync" owner="${vyos_conf_scripts_dir}/conntrack_sync.py"> <properties> <help>Connection tracking synchronization</help> - <priority>995</priority> + <!-- before VRRP / HA --> + <priority>799</priority> </properties> <children> <leafNode name="accept-protocol"> @@ -39,7 +40,7 @@ <description>Sync Datagram Congestion Control Protocol entries</description> </valueHelp> <constraint> - <regex>^(tcp|udp|icmp|icmp6|sctp|dccp)$</regex> + <regex>(tcp|udp|icmp|icmp6|sctp|dccp)</regex> </constraint> <constraintErrorMessage>Allowed protocols: tcp udp icmp or sctp</constraintErrorMessage> <multi/> @@ -68,7 +69,7 @@ <list>all ftp sip h323 nfs sqlnet</list> </completionHelp> <constraint> - <regex>^(all|ftp|sip|h323|nfs|sqlnet)$</regex> + <regex>(all|ftp|sip|h323|nfs|sqlnet)</regex> </constraint> <constraintErrorMessage>Invalid protocol</constraintErrorMessage> <multi/> diff --git a/interface-definitions/service_console-server.xml.in b/interface-definitions/service_console-server.xml.in index 28aa7ea71..e9591ad87 100644 --- a/interface-definitions/service_console-server.xml.in +++ b/interface-definitions/service_console-server.xml.in @@ -23,7 +23,7 @@ <description>USB based serial interface</description> </valueHelp> <constraint> - <regex>^(ttyS\d+|usb\d+b.*p.*)$</regex> + <regex>(ttyS\d+|usb\d+b.*p.*)</regex> </constraint> </properties> <children> @@ -35,13 +35,13 @@ <list>300 1200 2400 4800 9600 19200 38400 57600 115200</list> </completionHelp> <constraint> - <regex>^(300|1200|2400|4800|9600|19200|38400|57600|115200)$</regex> + <regex>(300|1200|2400|4800|9600|19200|38400|57600|115200)</regex> </constraint> </properties> </leafNode> <leafNode name="data-bits"> <properties> - <help>Serial port data bits (default: 8)</help> + <help>Serial port data bits</help> <completionHelp> <list>7 8</list> </completionHelp> @@ -53,7 +53,7 @@ </leafNode> <leafNode name="stop-bits"> <properties> - <help>Serial port stop bits (default: 1)</help> + <help>Serial port stop bits</help> <completionHelp> <list>1 2</list> </completionHelp> @@ -65,12 +65,12 @@ </leafNode> <leafNode name="parity"> <properties> - <help>Parity setting (default: none)</help> + <help>Parity setting</help> <completionHelp> <list>even odd none</list> </completionHelp> <constraint> - <regex>^(even|odd|none)$</regex> + <regex>(even|odd|none)</regex> </constraint> </properties> <defaultValue>none</defaultValue> diff --git a/interface-definitions/service_ipoe-server.xml.in b/interface-definitions/service_ipoe-server.xml.in index b19acab56..e222467b1 100644 --- a/interface-definitions/service_ipoe-server.xml.in +++ b/interface-definitions/service_ipoe-server.xml.in @@ -23,7 +23,7 @@ <list>L2 L3</list> </completionHelp> <constraint> - <regex>^(L2|L3)$</regex> + <regex>(L2|L3)</regex> </constraint> <valueHelp> <format>L2</format> @@ -42,7 +42,7 @@ <list>shared vlan</list> </completionHelp> <constraint> - <regex>^(shared|vlan)$</regex> + <regex>(shared|vlan)</regex> </constraint> <valueHelp> <format>shared</format> @@ -112,6 +112,22 @@ </children> </tagNode> #include <include/name-server-ipv4-ipv6.xml.i> + <node name="client-ip-pool"> + <properties> + <help>Client IP pools and gateway setting</help> + </properties> + <children> + <tagNode name="name"> + <properties> + <help>Pool name</help> + </properties> + <children> + #include <include/accel-ppp/gateway-address.xml.i> + #include <include/accel-ppp/client-ip-pool-subnet-single.xml.i> + </children> + </tagNode> + </children> + </node> #include <include/accel-ppp/client-ipv6-pool.xml.i> <node name="authentication"> <properties> @@ -125,7 +141,7 @@ <list>local radius noauth</list> </completionHelp> <constraint> - <regex>^(local|radius|noauth)$</regex> + <regex>(local|radius|noauth)</regex> </constraint> <valueHelp> <format>local</format> diff --git a/interface-definitions/service_monitoring_telegraf.xml.in b/interface-definitions/service_monitoring_telegraf.xml.in new file mode 100644 index 000000000..bd528ea33 --- /dev/null +++ b/interface-definitions/service_monitoring_telegraf.xml.in @@ -0,0 +1,308 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="service"> + <children> + <node name="monitoring"> + <properties> + <help>Monitoring services</help> + <priority>1280</priority> + </properties> + <children> + <node name="telegraf" owner="${vyos_conf_scripts_dir}/service_monitoring_telegraf.py"> + <properties> + <help>Telegraf monitoring</help> + </properties> + <children> + <node name="authentication"> + <properties> + <help>Authentication parameters</help> + </properties> + <children> + <leafNode name="organization"> + <properties> + <help>Authentication organization for InfluxDB v2 [REQUIRED]</help> + <constraint> + <regex>[a-zA-Z][1-9a-zA-Z@_\-.]{2,50}</regex> + </constraint> + <constraintErrorMessage>Organization name must be alphanumeric and can contain hyphens, underscores and at symbol.</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="token"> + <properties> + <help>Authentication token for InfluxDB v2 [REQUIRED]</help> + <valueHelp> + <format>txt</format> + <description>Authentication token</description> + </valueHelp> + <constraint> + <regex>[a-zA-Z0-9-_]{86}==</regex> + </constraint> + <constraintErrorMessage>Token must be 88 characters long and must contain only [a-zA-Z0-9-_] and '==' characters.</constraintErrorMessage> + </properties> + </leafNode> + </children> + </node> + <node name="azure-data-explorer"> + <properties> + <help>Output plugin Azure Data Explorer</help> + </properties> + <children> + <node name="authentication"> + <properties> + <help>Authentication parameters</help> + </properties> + <children> + <leafNode name="client-id"> + <properties> + <help>Application client id</help> + <constraint> + <regex>[-_a-zA-Z0-9]+</regex> + </constraint> + <constraintErrorMessage>Client-id is limited to alphanumerical characters and can contain hyphen and underscores</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="client-secret"> + <properties> + <help>Application client secret</help> + <constraint> + <regex>[-_a-zA-Z0-9]+</regex> + </constraint> + <constraintErrorMessage>Client-secret is limited to alphanumerical characters and can contain hyphen and underscores</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="tenant-id"> + <properties> + <help>Set tenant id</help> + <constraint> + <regex>[-_a-zA-Z0-9]+</regex> + </constraint> + <constraintErrorMessage>Tenant-id is limited to alphanumerical characters and can contain hyphen and underscores</constraintErrorMessage> + </properties> + </leafNode> + </children> + </node> + <leafNode name="database"> + <properties> + <help>Remote database name [REQUIRED]</help> + <valueHelp> + <format>txt</format> + <description>Remote database name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9]+</regex> + </constraint> + <constraintErrorMessage>Database is limited to alphanumerical characters and can contain hyphen and underscores</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="group-metrics"> + <properties> + <help>Type of metrics grouping when push to Azure Data Explorer</help> + <completionHelp> + <list>single-table table-per-metric</list> + </completionHelp> + <valueHelp> + <format>single-table</format> + <description>Metrics stores in one table</description> + </valueHelp> + <valueHelp> + <format>table-per-metric</format> + <description>One table per gorups of metric by the metric name</description> + </valueHelp> + <constraint> + <regex>(single-table|table-per-metric)</regex> + </constraint> + </properties> + <defaultValue>table-per-metric</defaultValue> + </leafNode> + <leafNode name="table"> + <properties> + <help>Name of the single table [Only if set group-metrics single-table]</help> + <valueHelp> + <format>txt</format> + <description>Table name</description> + </valueHelp> + <constraint> + <regex>[-_a-zA-Z0-9]+</regex> + </constraint> + <constraintErrorMessage>Table is limited to alphanumerical characters and can contain hyphen and underscores</constraintErrorMessage> + </properties> + </leafNode> + #include <include/monitoring/url.xml.i> + </children> + </node> + <leafNode name="bucket"> + <properties> + <help>Remote bucket</help> + </properties> + <defaultValue>main</defaultValue> + </leafNode> + <leafNode name="source"> + <properties> + <help>Source parameters for monitoring</help> + <completionHelp> + <list>all hardware-utilization logs network system telegraf</list> + </completionHelp> + <valueHelp> + <format>all</format> + <description>All parameters</description> + </valueHelp> + <valueHelp> + <format>hardware-utilization</format> + <description>Hardware-utilization parameters (CPU, disk, memory)</description> + </valueHelp> + <valueHelp> + <format>logs</format> + <description>Logs parameters</description> + </valueHelp> + <valueHelp> + <format>network</format> + <description>Network parameters (net, netstat, nftables)</description> + </valueHelp> + <valueHelp> + <format>system</format> + <description>System parameters (system, processes, interrupts)</description> + </valueHelp> + <valueHelp> + <format>telegraf</format> + <description>Telegraf internal statistics</description> + </valueHelp> + <constraint> + <regex>(all|hardware-utilization|logs|network|system|telegraf)</regex> + </constraint> + <multi/> + </properties> + <defaultValue>all</defaultValue> + </leafNode> + <node name="prometheus-client"> + <properties> + <help>Output plugin Prometheus client</help> + </properties> + <children> + <node name="authentication"> + <properties> + <help>HTTP basic authentication parameters</help> + </properties> + <children> + <leafNode name="username"> + <properties> + <help>Authentication username</help> + </properties> + </leafNode> + <leafNode name="password"> + <properties> + <help>Authentication password</help> + <valueHelp> + <format>txt</format> + <description>Authentication password</description> + </valueHelp> + </properties> + </leafNode> + </children> + </node> + <leafNode name="allow-from"> + <properties> + <help>Networks allowed to query this server</help> + <valueHelp> + <format>ipv4net</format> + <description>IP address and prefix length</description> + </valueHelp> + <valueHelp> + <format>ipv6net</format> + <description>IPv6 address and prefix length</description> + </valueHelp> + <multi/> + <constraint> + <validator name="ip-prefix"/> + </constraint> + </properties> + </leafNode> + <leafNode name="listen-address"> + <properties> + <help>Local IP addresses to listen on</help> + <completionHelp> + <script>${vyos_completion_dir}/list_local_ips.sh --both</script> + </completionHelp> + <valueHelp> + <format>ipv4</format> + <description>IPv4 address to listen for incoming connections</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address to listen for incoming connections</description> + </valueHelp> + <constraint> + <validator name="ipv4-address"/> + <validator name="ipv6-address"/> + <validator name="ipv6-link-local"/> + </constraint> + </properties> + </leafNode> + <leafNode name="metric-version"> + <properties> + <help>Metric version control mapping from Telegraf to Prometheus format</help> + <valueHelp> + <format>u32:1-2</format> + <description>Metric version (default: 2)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-2"/> + </constraint> + </properties> + <defaultValue>2</defaultValue> + </leafNode> + #include <include/port-number.xml.i> + <leafNode name="port"> + <defaultValue>9273</defaultValue> + </leafNode> + </children> + </node> + <node name="splunk"> + <properties> + <help>Output plugin Splunk</help> + </properties> + <children> + <node name="authentication"> + <properties> + <help>HTTP basic authentication parameters</help> + </properties> + <children> + <leafNode name="token"> + <properties> + <help>Authorization token</help> + </properties> + </leafNode> + <leafNode name="insecure"> + <properties> + <help>Use TLS but skip host validation</help> + <valueless/> + </properties> + </leafNode> + </children> + </node> + <leafNode name="url"> + <properties> + <help>Remote URL [REQUIRED]</help> + <valueHelp> + <format>url</format> + <description>Remote URL to Splunk collector</description> + </valueHelp> + <constraint> + <regex>^(http(s?):\/\/.*):(\d*)\/?(.*)</regex> + </constraint> + <constraintErrorMessage>Incorrect URL format</constraintErrorMessage> + </properties> + </leafNode> + </children> + </node> + #include <include/monitoring/url.xml.i> + #include <include/port-number.xml.i> + <leafNode name="port"> + <defaultValue>8086</defaultValue> + </leafNode> + </children> + </node> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/interface-definitions/service_pppoe-server.xml.in b/interface-definitions/service_pppoe-server.xml.in index 188aed6c4..50f42849b 100644 --- a/interface-definitions/service_pppoe-server.xml.in +++ b/interface-definitions/service_pppoe-server.xml.in @@ -32,7 +32,7 @@ <list>ifname ifname:mac</list> </completionHelp> <constraint> - <regex>^(ifname|ifname:mac)$</regex> + <regex>(ifname|ifname:mac)</regex> </constraint> <constraintErrorMessage>Invalid Called-Station-Id format</constraintErrorMessage> <valueHelp> @@ -70,19 +70,27 @@ <children> <leafNode name="vlan-id"> <properties> - <help>VLAN monitor for the automatic creation of vlans (user per vlan)</help> + <help>VLAN monitor for the automatic creation of single vlan</help> + <valueHelp> + <format>u32:1-4094</format> + <description>VLAN monitor for the automatic creation of single vlan</description> + </valueHelp> <constraint> - <validator name="numeric" argument="--range 1-4096"/> + <validator name="numeric" argument="--range 1-4094"/> </constraint> - <constraintErrorMessage>VLAN ID needs to be between 1 and 4096</constraintErrorMessage> + <constraintErrorMessage>VLAN ID needs to be between 1 and 4094</constraintErrorMessage> <multi/> </properties> </leafNode> <leafNode name="vlan-range"> <properties> - <help>VLAN monitor for the automatic creation of vlans (user per vlan)</help> + <help>VLAN monitor for the automatic creation of vlans range</help> + <valueHelp> + <format>start-end</format> + <description>VLAN monitor range for the automatic creation of vlans (e.g. 1-4094)</description> + </valueHelp> <constraint> - <regex>(409[0-6]|40[0-8][0-9]|[1-3][0-9]{3}|[1-9][0-9]{0,2})-(409[0-6]|40[0-8][0-9]|[1-3][0-9]{3}|[1-9][0-9]{0,2})</regex> + <validator name="range" argument="--min=1 --max=4094"/> </constraint> <multi/> </properties> @@ -100,7 +108,7 @@ <properties> <help>Acceptable rate of connections (e.g. 1/min, 60/sec)</help> <constraint> - <regex>[0-9]+\/(min|sec)$</regex> + <regex>[0-9]+\/(min|sec)</regex> </constraint> <constraintErrorMessage>illegal value</constraintErrorMessage> </properties> @@ -163,7 +171,7 @@ <properties> <help>IPv4 (IPCP) negotiation algorithm</help> <constraint> - <regex>^(deny|allow|prefer|require)$</regex> + <regex>(deny|allow|prefer|require)</regex> </constraint> <constraintErrorMessage>invalid value</constraintErrorMessage> <valueHelp> @@ -268,7 +276,7 @@ <properties> <help>control sessions count</help> <constraint> - <regex>^(deny|disable|replace)$</regex> + <regex>(deny|disable|replace)</regex> </constraint> <constraintErrorMessage>Invalid value</constraintErrorMessage> <valueHelp> diff --git a/interface-definitions/service_router-advert.xml.in b/interface-definitions/service_router-advert.xml.in index 0f4009f5c..bb11e9cd0 100644 --- a/interface-definitions/service_router-advert.xml.in +++ b/interface-definitions/service_router-advert.xml.in @@ -18,7 +18,7 @@ <children> <leafNode name="hop-limit"> <properties> - <help>Set Hop Count field of the IP header for outgoing packets (default: 64)</help> + <help>Set Hop Count field of the IP header for outgoing packets</help> <valueHelp> <format>u32:0</format> <description>Unspecified (by this router)</description> @@ -63,14 +63,14 @@ </valueHelp> <valueHelp> <format>medium</format> - <description>Default router has medium preference (default)</description> + <description>Default router has medium preference</description> </valueHelp> <valueHelp> <format>high</format> <description>Default router has high preference</description> </valueHelp> <constraint> - <regex>^(low|medium|high)$</regex> + <regex>(low|medium|high)</regex> </constraint> <constraintErrorMessage>Default preference must be low, medium or high</constraintErrorMessage> </properties> @@ -108,7 +108,7 @@ <children> <leafNode name="max"> <properties> - <help>Maximum interval between unsolicited multicast RAs (default: 600)</help> + <help>Maximum interval between unsolicited multicast RAs</help> <valueHelp> <format>u32:4-1800</format> <description>Maximum interval in seconds</description> @@ -156,7 +156,7 @@ <children> <leafNode name="valid-lifetime"> <properties> - <help>Time in seconds that the route will remain valid (default: 1800 seconds)</help> + <help>Time in seconds that the route will remain valid</help> <completionHelp> <list>infinity</list> </completionHelp> @@ -170,7 +170,7 @@ </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> - <regex>^(infinity)$</regex> + <regex>(infinity)</regex> </constraint> </properties> <defaultValue>1800</defaultValue> @@ -187,14 +187,14 @@ </valueHelp> <valueHelp> <format>medium</format> - <description>Route has medium preference (default)</description> + <description>Route has medium preference</description> </valueHelp> <valueHelp> <format>high</format> <description>Route has high preference</description> </valueHelp> <constraint> - <regex>^(low|medium|high)$</regex> + <regex>(low|medium|high)</regex> </constraint> <constraintErrorMessage>Route preference must be low, medium or high</constraintErrorMessage> </properties> @@ -234,7 +234,7 @@ </leafNode> <leafNode name="preferred-lifetime"> <properties> - <help>Time in seconds that the prefix will remain preferred (default 4 hours)</help> + <help>Time in seconds that the prefix will remain preferred</help> <completionHelp> <list>infinity</list> </completionHelp> @@ -248,14 +248,14 @@ </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> - <regex>^(infinity)$</regex> + <regex>(infinity)</regex> </constraint> </properties> <defaultValue>14400</defaultValue> </leafNode> <leafNode name="valid-lifetime"> <properties> - <help>Time in seconds that the prefix will remain valid (default: 30 days)</help> + <help>Time in seconds that the prefix will remain valid</help> <completionHelp> <list>infinity</list> </completionHelp> @@ -269,7 +269,7 @@ </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> - <regex>^(infinity)$</regex> + <regex>(infinity)</regex> </constraint> </properties> <defaultValue>2592000</defaultValue> diff --git a/interface-definitions/service_upnp.xml.in b/interface-definitions/service_upnp.xml.in new file mode 100644 index 000000000..a129b7260 --- /dev/null +++ b/interface-definitions/service_upnp.xml.in @@ -0,0 +1,224 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="service"> + <children> + <node name="upnp" owner="${vyos_conf_scripts_dir}/service_upnp.py"> + <properties> + <help>Universal Plug and Play (UPnP) service</help> + <priority>900</priority> + </properties> + <children> + <leafNode name="friendly-name"> + <properties> + <help>Name of this service</help> + <valueHelp> + <format>txt</format> + <description>Friendly name</description> + </valueHelp> + </properties> + </leafNode> + <leafNode name="wan-interface"> + <properties> + <help>WAN network interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + <constraint> + <validator name="interface-name" /> + </constraint> + </properties> + </leafNode> + <leafNode name="wan-ip"> + <properties> + <help>WAN network IP</help> + <valueHelp> + <format>ipv4</format> + <description>IPv4 address</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address</description> + </valueHelp> + <constraint> + <validator name="ipv4-address" /> + <validator name="ipv6-address" /> + </constraint> + <multi/> + </properties> + </leafNode> + <leafNode name="nat-pmp"> + <properties> + <help>Enable NAT-PMP support</help> + <valueless /> + </properties> + </leafNode> + <leafNode name="secure-mode"> + <properties> + <help>Enable Secure Mode</help> + <valueless /> + </properties> + </leafNode> + <leafNode name="presentation-url"> + <properties> + <help>Presentation Url</help> + <valueHelp> + <format>txt</format> + <description>Presentation Url</description> + </valueHelp> + </properties> + </leafNode> + <node name="pcp-lifetime"> + <properties> + <help>PCP-base lifetime Option</help> + </properties> + <children> + <leafNode name="max"> + <properties> + <help>Max lifetime time</help> + <constraint> + <validator name="numeric" /> + </constraint> + </properties> + </leafNode> + <leafNode name="min"> + <properties> + <help>Min lifetime time</help> + <constraint> + <validator name="numeric" /> + </constraint> + </properties> + </leafNode> + </children> + </node> + <leafNode name="listen"> + <properties> + <help>Local IP addresses for service to listen on</help> + <completionHelp> + <script>${vyos_completion_dir}/list_local_ips.sh --both</script> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + <valueHelp> + <format><interface></format> + <description>Monitor interface address</description> + </valueHelp> + <valueHelp> + <format>ipv4</format> + <description>IP address to listen for incoming connections</description> + </valueHelp> + <valueHelp> + <format>ipv4-prefix</format> + <description>IP prefix to listen for incoming connections</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>IP address to listen for incoming connections</description> + </valueHelp> + <valueHelp> + <format>ipv6-prefix</format> + <description>IP prefix to listen for incoming connections</description> + </valueHelp> + <multi/> + <constraint> + <validator name="interface-name" /> + <validator name="ipv4-address"/> + <validator name="ipv4-prefix"/> + <validator name="ipv6-address"/> + <validator name="ipv6-prefix"/> + </constraint> + </properties> + </leafNode> + <node name="stun"> + <properties> + <help>Enable STUN probe support (can be used with NAT 1:1 support for WAN interfaces)</help> + </properties> + <children> + <leafNode name="host"> + <properties> + <help>The STUN server address</help> + <valueHelp> + <format>txt</format> + <description>The STUN server host address</description> + </valueHelp> + <constraint> + <validator name="fqdn"/> + </constraint> + </properties> + </leafNode> + #include <include/port-number.xml.i> + </children> + </node> + <tagNode name="rule"> + <properties> + <help>UPnP Rule</help> + <valueHelp> + <format>u32:0-65535</format> + <description>Rule number</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-65535"/> + </constraint> + </properties> + <children> + #include <include/generic-disable-node.xml.i> + <leafNode name="external-port-range"> + <properties> + <help>Port range (REQUIRE)</help> + <valueHelp> + <format><port></format> + <description>single port</description> + </valueHelp> + <valueHelp> + <format><portN>-<portM></format> + <description>Port range (use '-' as delimiter)</description> + </valueHelp> + <constraint> + <validator name="port-range"/> + </constraint> + </properties> + </leafNode> + <leafNode name="internal-port-range"> + <properties> + <help>Port range (REQUIRE)</help> + <valueHelp> + <format><port></format> + <description>single port</description> + </valueHelp> + <valueHelp> + <format><portN>-<portM></format> + <description>Port range (use '-' as delimiter)</description> + </valueHelp> + <constraint> + <validator name="port-range"/> + </constraint> + </properties> + </leafNode> + <leafNode name="ip"> + <properties> + <help>The IP to which this rule applies (REQUIRE)</help> + <valueHelp> + <format>ipv4</format> + <description>The IPv4 to which this rule applies</description> + </valueHelp> + <constraint> + <validator name="ipv4-address" /> + </constraint> + </properties> + </leafNode> + <leafNode name="action"> + <properties> + <help>Actions against the rule (REQUIRE)</help> + <completionHelp> + <list>allow deny</list> + </completionHelp> + <constraint> + <regex>(allow|deny)</regex> + </constraint> + </properties> + </leafNode> + </children> + </tagNode> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/interface-definitions/service_webproxy.xml.in b/interface-definitions/service_webproxy.xml.in index d61a95690..9a75bc27d 100644 --- a/interface-definitions/service_webproxy.xml.in +++ b/interface-definitions/service_webproxy.xml.in @@ -16,7 +16,7 @@ <description>Domain to use for urls that do not contain a '.'</description> </valueHelp> <constraint> - <regex>^[\.][a-z0-9-][$]?</regex> + <regex>[.][A-Za-z0-9][-.A-Za-z0-9]*</regex> </constraint> <constraintErrorMessage>Must start append-domain with a '.'</constraintErrorMessage> </properties> @@ -28,7 +28,7 @@ <children> <leafNode name="children"> <properties> - <help>Number of authentication helper processes (default: 5)</help> + <help>Number of authentication helper processes</help> <valueHelp> <format>n</format> <description>Number of authentication helper processes</description> @@ -41,7 +41,7 @@ </leafNode> <leafNode name="credentials-ttl"> <properties> - <help>Authenticated session time to live in minutes (default: 60)</help> + <help>Authenticated session time to live in minutes</help> <valueHelp> <format>n</format> <description>Authenticated session timeout</description> @@ -105,7 +105,7 @@ </leafNode> <leafNode name="version"> <properties> - <help>LDAP protocol version (default: 3)</help> + <help>LDAP protocol version</help> <completionHelp> <list>2 3</list> </completionHelp> @@ -136,7 +136,7 @@ <description>Lightweight Directory Access Protocol</description> </valueHelp> <constraint> - <regex>^(ldap)$</regex> + <regex>(ldap)</regex> </constraint> <constraintErrorMessage>The only supported method currently is LDAP</constraintErrorMessage> </properties> @@ -177,7 +177,7 @@ </leafNode> <leafNode name="http-port"> <properties> - <help>Default Proxy Port (default: 3128)</help> + <help>Default Proxy Port</help> <valueHelp> <format>u32:1025-65535</format> <description>Default port number</description> @@ -190,7 +190,11 @@ </leafNode> <leafNode name="icp-port"> <properties> - <help>Cache peer ICP port (default: disabled)</help> + <help>Cache peer ICP port</help> + <valueHelp> + <format>u32:0</format> + <description>Cache peer disabled</description> + </valueHelp> <valueHelp> <format>u32:1-65535</format> <description>Cache peer ICP port</description> @@ -203,7 +207,7 @@ </leafNode> <leafNode name="options"> <properties> - <help>Cache peer options (default: "no-query default")</help> + <help>Cache peer options</help> <valueHelp> <format>txt</format> <description>Cache peer options</description> @@ -230,7 +234,7 @@ <description>Peer is a member of a multicast group</description> </valueHelp> <constraint> - <regex>^(parent|sibling|multicast)$</regex> + <regex>(parent|sibling|multicast)</regex> </constraint> </properties> <defaultValue>parent</defaultValue> @@ -239,7 +243,7 @@ </tagNode> <leafNode name="cache-size"> <properties> - <help>Disk cache size in MB (default: 100)</help> + <help>Disk cache size in MB</help> <valueHelp> <format>u32</format> <description>Disk cache size in MB</description> @@ -253,7 +257,7 @@ </leafNode> <leafNode name="default-port"> <properties> - <help>Default Proxy Port (default: 3128)</help> + <help>Default Proxy Port</help> <valueHelp> <format>u32:1025-65535</format> <description>Default port number</description> @@ -296,7 +300,7 @@ <children> <leafNode name="port"> <properties> - <help>Default Proxy Port (default: 3128)</help> + <help>Default Proxy Port</help> <valueHelp> <format>u32:1025-65535</format> <description>Default port number</description> @@ -305,6 +309,7 @@ <validator name="numeric" argument="--range 1025-65535"/> </constraint> </properties> + <!-- no defaultValue specified as there is default-port --> </leafNode> <leafNode name="disable-transparent"> <properties> @@ -363,7 +368,7 @@ <list>image/gif www/mime application/macbinary application/oda application/octet-stream application/pdf application/postscript application/postscript application/postscript text/rtf application/octet-stream application/octet-stream application/x-tar application/x-csh application/x-dvi application/x-hdf application/x-latex text/plain application/x-netcdf application/x-netcdf application/x-sh application/x-tcl application/x-tex application/x-texinfo application/x-texinfo application/x-troff application/x-troff application/x-troff application/x-troff-man application/x-troff-me application/x-troff-ms application/x-wais-source application/zip application/x-bcpio application/x-cpio application/x-gtar application/x-rpm application/x-shar application/x-sv4cpio application/x-sv4crc application/x-tar application/x-ustar audio/basic audio/basic audio/mpeg audio/mpeg audio/mpeg audio/x-aiff audio/x-aiff audio/x-aiff audio/x-wav image/bmp image/ief image/jpeg image/jpeg image/jpeg image/tiff image/tiff image/x-cmu-raster image/x-portable-anymap image/x-portable-bitmap image/x-portable-graymap image/x-portable-pixmap image/x-rgb image/x-xbitmap image/x-xpixmap image/x-xwindowdump text/html text/html text/css application/x-javascript text/plain text/plain text/plain text/plain text/plain text/plain text/plain text/plain text/plain text/richtext text/tab-separated-values text/x-setext video/mpeg video/mpeg video/mpeg video/quicktime video/quicktime video/x-msvideo video/x-sgi-movie application/mac-compactpro application/mac-binhex40 application/macwriteii application/msword application/msword application/vnd.ms-excel application/vnd.ms-powerpoint application/vnd.lotus-1-2-3 application/vnd.mif application/x-stuffit application/pict application/pict application/x-arj-compressed application/x-lha-compressed application/x-lha-compressed application/x-deflate text/plain application/octet-stream application/octet-stream image/png application/octet-stream application/x-xpinstall application/octet-stream text/plain application/x-director application/x-director application/x-director image/vnd.djvu image/vnd.djvu application/octet-stream application/octet-stream application/andrew-inset x-conference/x-cooltalk model/iges model/iges audio/midi audio/midi audio/midi model/mesh model/mesh video/vnd.mpegurl chemical/x-pdb application/x-chess-pgn audio/x-realaudio audio/x-pn-realaudio audio/x-pn-realaudio text/sgml text/sgml application/x-koan application/x-koan application/x-koan application/x-koan application/smil application/smil application/octet-stream application/x-futuresplash application/x-shockwave-flash application/x-cdlink model/vrml image/vnd.wap.wbmp application/vnd.wap.wbxml application/vnd.wap.wmlc application/vnd.wap.wmlscriptc application/vnd.wap.wmlscript application/xhtml application/xhtml text/xml text/xml chemical/x-xyz text/plain</list> </completionHelp> <constraint> - <regex>^(image/gif|www/mime|application/macbinary|application/oda|application/octet-stream|application/pdf|application/postscript|application/postscript|application/postscript|text/rtf|application/octet-stream|application/octet-stream|application/x-tar|application/x-csh|application/x-dvi|application/x-hdf|application/x-latex|text/plain|application/x-netcdf|application/x-netcdf|application/x-sh|application/x-tcl|application/x-tex|application/x-texinfo|application/x-texinfo|application/x-troff|application/x-troff|application/x-troff|application/x-troff-man|application/x-troff-me|application/x-troff-ms|application/x-wais-source|application/zip|application/x-bcpio|application/x-cpio|application/x-gtar|application/x-rpm|application/x-shar|application/x-sv4cpio|application/x-sv4crc|application/x-tar|application/x-ustar|audio/basic|audio/basic|audio/mpeg|audio/mpeg|audio/mpeg|audio/x-aiff|audio/x-aiff|audio/x-aiff|audio/x-wav|image/bmp|image/ief|image/jpeg|image/jpeg|image/jpeg|image/tiff|image/tiff|image/x-cmu-raster|image/x-portable-anymap|image/x-portable-bitmap|image/x-portable-graymap|image/x-portable-pixmap|image/x-rgb|image/x-xbitmap|image/x-xpixmap|image/x-xwindowdump|text/html|text/html|text/css|application/x-javascript|text/plain|text/plain|text/plain|text/plain|text/plain|text/plain|text/plain|text/plain|text/plain|text/richtext|text/tab-separated-values|text/x-setext|video/mpeg|video/mpeg|video/mpeg|video/quicktime|video/quicktime|video/x-msvideo|video/x-sgi-movie|application/mac-compactpro|application/mac-binhex40|application/macwriteii|application/msword|application/msword|application/vnd.ms-excel|application/vnd.ms-powerpoint|application/vnd.lotus-1-2-3|application/vnd.mif|application/x-stuffit|application/pict|application/pict|application/x-arj-compressed|application/x-lha-compressed|application/x-lha-compressed|application/x-deflate|text/plain|application/octet-stream|application/octet-stream|image/png|application/octet-stream|application/x-xpinstall|application/octet-stream|text/plain|application/x-director|application/x-director|application/x-director|image/vnd.djvu|image/vnd.djvu|application/octet-stream|application/octet-stream|application/andrew-inset|x-conference/x-cooltalk|model/iges|model/iges|audio/midi|audio/midi|audio/midi|model/mesh|model/mesh|video/vnd.mpegurl|chemical/x-pdb|application/x-chess-pgn|audio/x-realaudio|audio/x-pn-realaudio|audio/x-pn-realaudio|text/sgml|text/sgml|application/x-koan|application/x-koan|application/x-koan|application/x-koan|application/smil|application/smil|application/octet-stream|application/x-futuresplash|application/x-shockwave-flash|application/x-cdlink|model/vrml|image/vnd.wap.wbmp|application/vnd.wap.wbxml|application/vnd.wap.wmlc|application/vnd.wap.wmlscriptc|application/vnd.wap.wmlscript|application/xhtml|application/xhtml|text/xml|text/xml|chemical/x-xyz|text/plain)$</regex> + <regex>(image/gif|www/mime|application/macbinary|application/oda|application/octet-stream|application/pdf|application/postscript|application/postscript|application/postscript|text/rtf|application/octet-stream|application/octet-stream|application/x-tar|application/x-csh|application/x-dvi|application/x-hdf|application/x-latex|text/plain|application/x-netcdf|application/x-netcdf|application/x-sh|application/x-tcl|application/x-tex|application/x-texinfo|application/x-texinfo|application/x-troff|application/x-troff|application/x-troff|application/x-troff-man|application/x-troff-me|application/x-troff-ms|application/x-wais-source|application/zip|application/x-bcpio|application/x-cpio|application/x-gtar|application/x-rpm|application/x-shar|application/x-sv4cpio|application/x-sv4crc|application/x-tar|application/x-ustar|audio/basic|audio/basic|audio/mpeg|audio/mpeg|audio/mpeg|audio/x-aiff|audio/x-aiff|audio/x-aiff|audio/x-wav|image/bmp|image/ief|image/jpeg|image/jpeg|image/jpeg|image/tiff|image/tiff|image/x-cmu-raster|image/x-portable-anymap|image/x-portable-bitmap|image/x-portable-graymap|image/x-portable-pixmap|image/x-rgb|image/x-xbitmap|image/x-xpixmap|image/x-xwindowdump|text/html|text/html|text/css|application/x-javascript|text/plain|text/plain|text/plain|text/plain|text/plain|text/plain|text/plain|text/plain|text/plain|text/richtext|text/tab-separated-values|text/x-setext|video/mpeg|video/mpeg|video/mpeg|video/quicktime|video/quicktime|video/x-msvideo|video/x-sgi-movie|application/mac-compactpro|application/mac-binhex40|application/macwriteii|application/msword|application/msword|application/vnd.ms-excel|application/vnd.ms-powerpoint|application/vnd.lotus-1-2-3|application/vnd.mif|application/x-stuffit|application/pict|application/pict|application/x-arj-compressed|application/x-lha-compressed|application/x-lha-compressed|application/x-deflate|text/plain|application/octet-stream|application/octet-stream|image/png|application/octet-stream|application/x-xpinstall|application/octet-stream|text/plain|application/x-director|application/x-director|application/x-director|image/vnd.djvu|image/vnd.djvu|application/octet-stream|application/octet-stream|application/andrew-inset|x-conference/x-cooltalk|model/iges|model/iges|audio/midi|audio/midi|audio/midi|model/mesh|model/mesh|video/vnd.mpegurl|chemical/x-pdb|application/x-chess-pgn|audio/x-realaudio|audio/x-pn-realaudio|audio/x-pn-realaudio|text/sgml|text/sgml|application/x-koan|application/x-koan|application/x-koan|application/x-koan|application/smil|application/smil|application/octet-stream|application/x-futuresplash|application/x-shockwave-flash|application/x-cdlink|model/vrml|image/vnd.wap.wbmp|application/vnd.wap.wbxml|application/vnd.wap.wmlc|application/vnd.wap.wmlscriptc|application/vnd.wap.wmlscript|application/xhtml|application/xhtml|text/xml|text/xml|chemical/x-xyz|text/plain)</regex> </constraint> <multi/> </properties> @@ -399,7 +404,7 @@ <children> <leafNode name="update-hour"> <properties> - <help>Hour of day for database update [REQUIRED]</help> + <help>Hour of day for database update</help> <valueHelp> <format>u32:0-23</format> <description>Hour for database update</description> @@ -414,7 +419,7 @@ </node> <leafNode name="redirect-url"> <properties> - <help>Redirect URL for filtered websites (default: block.vyos.net)</help> + <help>Redirect URL for filtered websites</help> <valueHelp> <format>url</format> <description>URL for redirect</description> @@ -479,7 +484,7 @@ <description>Name of source group</description> </valueHelp> <constraint> - <regex>^[^0-9]</regex> + <regex>[^0-9]</regex> </constraint> <constraintErrorMessage>URL-filter source-group cannot start with a number!</constraintErrorMessage> </properties> @@ -593,7 +598,7 @@ <description>All days of the week</description> </valueHelp> <constraint> - <regex>^(Sun|Mon|Tue|Wed|Thu|Fri|Sat|weekdays|weekend|all)$</regex> + <regex>(Sun|Mon|Tue|Wed|Thu|Fri|Sat|weekdays|weekend|all)</regex> </constraint> </properties> <children> @@ -606,7 +611,7 @@ </valueHelp> <constraint> <!-- time range example: 12:00-13:00 --> - <regex>^(\d\d:\d\d)-(\d\d:\d\d)$</regex> + <regex>(\d\d:\d\d)-(\d\d:\d\d)</regex> </constraint> <constraintErrorMessage>Expected time format hh:mm - hh:mm in 24hr time</constraintErrorMessage> </properties> diff --git a/interface-definitions/snmp.xml.in b/interface-definitions/snmp.xml.in index 949536fe7..b4f72589e 100644 --- a/interface-definitions/snmp.xml.in +++ b/interface-definitions/snmp.xml.in @@ -13,30 +13,31 @@ <properties> <help>Community name</help> <constraint> - <regex>^[a-zA-Z0-9\-_]{1,100}$</regex> + <regex>[a-zA-Z0-9\-_]{1,100}</regex> </constraint> <constraintErrorMessage>Community string is limited to alphanumerical characters only with a total lenght of 100</constraintErrorMessage> </properties> <children> <leafNode name="authorization"> <properties> - <help>Authorization type (default: 'ro')</help> + <help>Authorization type</help> <completionHelp> <list>ro rw</list> </completionHelp> <valueHelp> <format>ro</format> - <description>read only</description> + <description>Read-Only</description> </valueHelp> <valueHelp> <format>rw</format> - <description>read write</description> + <description>Read-Write</description> </valueHelp> <constraint> - <regex>^(ro|rw)$</regex> + <regex>(ro|rw)</regex> </constraint> <constraintErrorMessage>Authorization type must be either 'rw' or 'ro'</constraintErrorMessage> </properties> + <defaultValue>ro</defaultValue> </leafNode> <leafNode name="client"> <properties> @@ -71,7 +72,7 @@ <properties> <help>Contact information</help> <constraint> - <regex>^.{1,255}$</regex> + <regex>.{1,255}</regex> </constraint> <constraintErrorMessage>Contact information is limited to 255 characters or less</constraintErrorMessage> </properties> @@ -80,7 +81,7 @@ <properties> <help>Description information</help> <constraint> - <regex>^.{1,255}$</regex> + <regex>.{1,255}</regex> </constraint> <constraintErrorMessage>Description is limited to 255 characters or less</constraintErrorMessage> </properties> @@ -105,18 +106,9 @@ </constraint> </properties> <children> + #include <include/port-number.xml.i> <leafNode name="port"> - <properties> - <help>Port for SNMP service (default: '161')</help> - <valueHelp> - <format>u32:1-65535</format> - <description>Numeric IP port</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-65535"/> - </constraint> - <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage> - </properties> + <defaultValue>161</defaultValue> </leafNode> </children> </tagNode> @@ -124,57 +116,34 @@ <properties> <help>Location information</help> <constraint> - <regex>^.{1,255}$</regex> + <regex>.{1,255}</regex> </constraint> <constraintErrorMessage>Location is limited to 255 characters or less</constraintErrorMessage> </properties> </leafNode> <leafNode name="oid-enable"> <properties> - <help>Enable specific oids</help> - <valueHelp> - <format>txt</format> - <description>Enable specific oids</description> - </valueHelp> - <valueHelp> - <format>route-table</format> - <description>Enable route table oids (ipCidrRouteTable inetCidrRouteTable)</description> - </valueHelp> + <help>Enable specific OIDs</help> <completionHelp> <list>route-table</list> </completionHelp> - <constraint> - <regex>^(route-table)$</regex> - </constraint> - <constraintErrorMessage>Oid must be 'route-table'</constraintErrorMessage> - </properties> - </leafNode> - <leafNode name="protocol"> - <properties> - <help>Listen protocol for SNMP</help> - <completionHelp> - <list>udp tcp</list> - </completionHelp> <valueHelp> - <format>udp</format> - <description>Listen protocol UDP (default)</description> - </valueHelp> - <valueHelp> - <format>tcp</format> - <description>Listen protocol TCP</description> + <format>route-table</format> + <description>Enable routing table OIDs (ipCidrRouteTable inetCidrRouteTable)</description> </valueHelp> <constraint> - <regex>^(udp|tcp)$</regex> + <regex>(route-table)</regex> </constraint> + <constraintErrorMessage>OID must be 'route-table'</constraintErrorMessage> </properties> - <defaultValue>udp</defaultValue> </leafNode> + #include <include/snmp/protocol.xml.i> <leafNode name="smux-peer"> <properties> <help>Register a subtree for SMUX-based processing</help> <valueHelp> - <format>oid</format> - <description>Object Identifier</description> + <format>txt</format> + <description>SNMP Object Identifier</description> </valueHelp> <multi/> </properties> @@ -218,18 +187,9 @@ <help>Community used when sending trap information</help> </properties> </leafNode> + #include <include/port-number.xml.i> <leafNode name="port"> - <properties> - <help>Destination port used for trap notification</help> - <valueHelp> - <format>u32:1-65535</format> - <description>Numeric IP port</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-65535"/> - </constraint> - <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage> - </properties> + <defaultValue>162</defaultValue> </leafNode> </children> </tagNode> @@ -242,36 +202,18 @@ <properties> <help>Specifies the EngineID that uniquely identify an agent (e.g. 000000000000000000000002)</help> <constraint> - <regex>^([0-9a-f][0-9a-f]){1,18}$</regex> + <regex>([0-9a-f][0-9a-f]){1,18}</regex> </constraint> <constraintErrorMessage>ID must contain an even number (from 2 to 36) of hex digits</constraintErrorMessage> </properties> + <defaultValue></defaultValue> </leafNode> <tagNode name="group"> <properties> <help>Specifies the group with name groupname</help> </properties> <children> - <leafNode name="mode"> - <properties> - <help>Define group access permission (default: 'ro')</help> - <completionHelp> - <list>ro rw</list> - </completionHelp> - <valueHelp> - <format>ro</format> - <description>read only</description> - </valueHelp> - <valueHelp> - <format>rw</format> - <description>read write</description> - </valueHelp> - <constraint> - <regex>^(ro|rw)$</regex> - </constraint> - <constraintErrorMessage>Authorization type must be either 'rw' or 'ro'</constraintErrorMessage> - </properties> - </leafNode> + #include <include/snmp/access-mode.xml.i> <leafNode name="seclevel"> <properties> <help>Security levels</help> @@ -291,9 +233,10 @@ <description>Messages are authenticated and encrypted (authPriv)</description> </valueHelp> <constraint> - <regex>^(noauth|auth|priv)$</regex> + <regex>(noauth|auth|priv)</regex> </constraint> </properties> + <defaultValue>auth</defaultValue> </leafNode> <leafNode name="view"> <properties> @@ -331,7 +274,7 @@ <properties> <help>Defines the encrypted key for authentication</help> <constraint> - <regex>^[0-9a-f]*$</regex> + <regex>[0-9a-f]*</regex> </constraint> <constraintErrorMessage>Encrypted key must only contain hex digits</constraintErrorMessage> </properties> @@ -340,44 +283,17 @@ <properties> <help>Defines the clear text key for authentication</help> <constraint> - <regex>^.{8,}$</regex> + <regex>.{8,}</regex> </constraint> <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage> </properties> </leafNode> - <leafNode name="type"> - <properties> - <help>Defines the protocol used for authentication (default: 'md5')</help> - <completionHelp> - <list>md5 sha</list> - </completionHelp> - <valueHelp> - <format>md5</format> - <description>Message Digest 5</description> - </valueHelp> - <valueHelp> - <format>sha</format> - <description>Secure Hash Algorithm</description> - </valueHelp> - <constraint> - <regex>^(md5|sha)$</regex> - </constraint> - </properties> - </leafNode> + #include <include/snmp/authentication-type.xml.i> </children> </node> + #include <include/port-number.xml.i> <leafNode name="port"> - <properties> - <help>Specifies TCP/UDP port of destination SNMP traps/informs (default: '162')</help> - <valueHelp> - <format>u32:1-65535</format> - <description>Numeric IP port</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-65535"/> - </constraint> - <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage> - </properties> + <defaultValue>162</defaultValue> </leafNode> <node name="privacy"> <properties> @@ -388,7 +304,7 @@ <properties> <help>Defines the encrypted key for privacy protocol</help> <constraint> - <regex>^[0-9a-f]*$</regex> + <regex>[0-9a-f]*</regex> </constraint> <constraintErrorMessage>Encrypted key must only contain hex digits</constraintErrorMessage> </properties> @@ -397,54 +313,18 @@ <properties> <help>Defines the clear text key for privacy protocol</help> <constraint> - <regex>^.{8,}$</regex> + <regex>.{8,}</regex> </constraint> <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage> </properties> </leafNode> - <leafNode name="type"> - <properties> - <help>Defines the protocol for privacy (default: 'des')</help> - <completionHelp> - <list>des aes</list> - </completionHelp> - <valueHelp> - <format>des</format> - <description>Data Encryption Standard</description> - </valueHelp> - <valueHelp> - <format>aes</format> - <description>Advanced Encryption Standard</description> - </valueHelp> - <constraint> - <regex>^(des|aes)$</regex> - </constraint> - </properties> - </leafNode> + #include <include/snmp/privacy-type.xml.i> </children> </node> - <leafNode name="protocol"> - <properties> - <help>Defines protocol for notification between TCP and UDP</help> - <completionHelp> - <list>tcp udp</list> - </completionHelp> - <valueHelp> - <format>tcp</format> - <description>Use Transmission Control Protocol for notifications</description> - </valueHelp> - <valueHelp> - <format>udp</format> - <description>Use User Datagram Protocol for notifications</description> - </valueHelp> - <constraint> - <regex>^(tcp|udp)$</regex> - </constraint> - </properties> - </leafNode> + #include <include/snmp/protocol.xml.i> <leafNode name="type"> <properties> - <help>Specifies the type of notification between inform and trap (default: 'inform')</help> + <help>Specifies the type of notification between inform and trap</help> <completionHelp> <list>inform trap</list> </completionHelp> @@ -457,9 +337,10 @@ <description>Use TRAP</description> </valueHelp> <constraint> - <regex>^(inform|trap)$</regex> + <regex>(inform|trap)</regex> </constraint> </properties> + <defaultValue>inform</defaultValue> </leafNode> <leafNode name="user"> <properties> @@ -475,7 +356,7 @@ <properties> <help>Specifies the user with name username</help> <constraint> - <regex>[^\(\)\|\-]+$</regex> + <regex>[^\(\)\|\-]+</regex> </constraint> <constraintErrorMessage>Illegal characters in name</constraintErrorMessage> </properties> @@ -489,7 +370,7 @@ <properties> <help>Defines the encrypted key for authentication</help> <constraint> - <regex>^[0-9a-f]*$</regex> + <regex>[0-9a-f]*</regex> </constraint> <constraintErrorMessage>Encrypted key must only contain hex digits</constraintErrorMessage> </properties> @@ -498,30 +379,12 @@ <properties> <help>Defines the clear text key for authentication</help> <constraint> - <regex>^.{8,}$</regex> + <regex>.{8,}</regex> </constraint> <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage> </properties> </leafNode> - <leafNode name="type"> - <properties> - <help>Defines the protocol used for authentication (default: 'md5')</help> - <completionHelp> - <list>md5 sha</list> - </completionHelp> - <valueHelp> - <format>md5</format> - <description>Message Digest 5</description> - </valueHelp> - <valueHelp> - <format>sha</format> - <description>Secure Hash Algorithm</description> - </valueHelp> - <constraint> - <regex>^(md5|sha)$</regex> - </constraint> - </properties> - </leafNode> + #include <include/snmp/authentication-type.xml.i> </children> </node> <leafNode name="group"> @@ -532,26 +395,7 @@ </completionHelp> </properties> </leafNode> - <leafNode name="mode"> - <properties> - <help>Define users access permission (default: 'ro')</help> - <completionHelp> - <list>ro rw</list> - </completionHelp> - <valueHelp> - <format>ro</format> - <description>read only</description> - </valueHelp> - <valueHelp> - <format>rw</format> - <description>read write</description> - </valueHelp> - <constraint> - <regex>^(ro|rw)$</regex> - </constraint> - <constraintErrorMessage>Authorization type must be either 'rw' or 'ro'</constraintErrorMessage> - </properties> - </leafNode> + #include <include/snmp/access-mode.xml.i> <node name="privacy"> <properties> <help>Defines the privacy</help> @@ -561,7 +405,7 @@ <properties> <help>Defines the encrypted key for privacy protocol</help> <constraint> - <regex>^[0-9a-f]*$</regex> + <regex>[0-9a-f]*</regex> </constraint> <constraintErrorMessage>Encrypted key must only contain hex digits</constraintErrorMessage> </properties> @@ -570,30 +414,12 @@ <properties> <help>Defines the clear text key for privacy protocol</help> <constraint> - <regex>^.{8,}$</regex> + <regex>.{8,}</regex> </constraint> <constraintErrorMessage>Key must contain 8 or more characters</constraintErrorMessage> </properties> </leafNode> - <leafNode name="type"> - <properties> - <help>Defines the protocol for privacy (default: 'des')</help> - <completionHelp> - <list>des aes</list> - </completionHelp> - <valueHelp> - <format>des</format> - <description>Data Encryption Standard</description> - </valueHelp> - <valueHelp> - <format>aes</format> - <description>Advanced Encryption Standard</description> - </valueHelp> - <constraint> - <regex>^(des|aes)$</regex> - </constraint> - </properties> - </leafNode> + #include <include/snmp/privacy-type.xml.i> </children> </node> </children> @@ -602,7 +428,7 @@ <properties> <help>Specifies the view with name viewname</help> <constraint> - <regex>[^\(\)\|\-]+$</regex> + <regex>[^\(\)\|\-]+</regex> </constraint> <constraintErrorMessage>Illegal characters in name</constraintErrorMessage> </properties> @@ -611,7 +437,7 @@ <properties> <help>Specifies the oid</help> <constraint> - <regex>^[0-9]+(\.[0-9]+)*$</regex> + <regex>[0-9]+(\.[0-9]+)*</regex> </constraint> <constraintErrorMessage>OID must start from a number</constraintErrorMessage> </properties> @@ -625,7 +451,7 @@ <properties> <help>Defines a bit-mask that is indicating which subidentifiers of the associated subtree OID should be regarded as significant</help> <constraint> - <regex>^[0-9a-f]{2}([\.:][0-9a-f]{2})*$</regex> + <regex>[0-9a-f]{2}([\.:][0-9a-f]{2})*</regex> </constraint> <constraintErrorMessage>MASK is a list of hex octets, separated by '.' or ':'</constraintErrorMessage> </properties> @@ -645,7 +471,7 @@ <properties> <help>Extension name</help> <constraint> - <regex>^[a-z0-9\.\-\_]+</regex> + <regex>[a-z0-9\.\-\_]+</regex> </constraint> <constraintErrorMessage>Script extension contains invalid characters</constraintErrorMessage> </properties> @@ -657,7 +483,7 @@ <script>ls /config/user-data</script> </completionHelp> <constraint> - <regex>^[a-z0-9\.\-\_\/]+</regex> + <regex>[a-z0-9\.\-\_\/]+</regex> </constraint> <constraintErrorMessage>Script extension contains invalid characters</constraintErrorMessage> </properties> diff --git a/interface-definitions/ssh.xml.in b/interface-definitions/ssh.xml.in index e3b9d16e1..126183162 100644 --- a/interface-definitions/ssh.xml.in +++ b/interface-definitions/ssh.xml.in @@ -44,7 +44,7 @@ <list>3des-cbc aes128-cbc aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com chacha20-poly1305@openssh.com</list> </completionHelp> <constraint> - <regex>^(3des-cbc|aes128-cbc|aes192-cbc|aes256-cbc|rijndael-cbc@lysator.liu.se|aes128-ctr|aes192-ctr|aes256-ctr|aes128-gcm@openssh.com|aes256-gcm@openssh.com|chacha20-poly1305@openssh.com)$</regex> + <regex>(3des-cbc|aes128-cbc|aes192-cbc|aes256-cbc|rijndael-cbc@lysator.liu.se|aes128-ctr|aes192-ctr|aes256-ctr|aes128-gcm@openssh.com|aes256-gcm@openssh.com|chacha20-poly1305@openssh.com)</regex> </constraint> <multi/> </properties> @@ -61,6 +61,78 @@ <valueless/> </properties> </leafNode> + <node name="dynamic-protection"> + <properties> + <help>Allow dynamic protection</help> + </properties> + <children> + <leafNode name="block-time"> + <properties> + <help>Block source IP in seconds. Subsequent blocks increase by a factor of 1.5</help> + <valueHelp> + <format>u32:1-65535</format> + <description>Time interval in seconds for blocking</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-65535"/> + </constraint> + </properties> + <defaultValue>120</defaultValue> + </leafNode> + <leafNode name="detect-time"> + <properties> + <help>Remember source IP in seconds before reset their score</help> + <valueHelp> + <format>u32:1-65535</format> + <description>Time interval in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-65535"/> + </constraint> + </properties> + <defaultValue>1800</defaultValue> + </leafNode> + <leafNode name="threshold"> + <properties> + <help>Block source IP when their cumulative attack score exceeds threshold</help> + <valueHelp> + <format>u32:1-65535</format> + <description>Threshold score</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-65535"/> + </constraint> + </properties> + <defaultValue>30</defaultValue> + </leafNode> + <leafNode name="allow-from"> + <properties> + <help>Always allow inbound connections from these systems</help> + <valueHelp> + <format>ipv4</format> + <description>Address to match against</description> + </valueHelp> + <valueHelp> + <format>ipv4net</format> + <description>IPv4 address and prefix length</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address to match against</description> + </valueHelp> + <valueHelp> + <format>ipv6net</format> + <description>IPv6 address and prefix length</description> + </valueHelp> + <constraint> + <validator name="ip-address"/> + <validator name="ip-prefix"/> + </constraint> + <multi/> + </properties> + </leafNode> + </children> + </node> <leafNode name="key-exchange"> <properties> <help>Allowed key exchange (KEX) algorithms</help> @@ -70,7 +142,7 @@ </completionHelp> <multi/> <constraint> - <regex>^(diffie-hellman-group1-sha1|diffie-hellman-group14-sha1|diffie-hellman-group14-sha256|diffie-hellman-group16-sha512|diffie-hellman-group18-sha512|diffie-hellman-group-exchange-sha1|diffie-hellman-group-exchange-sha256|ecdh-sha2-nistp256|ecdh-sha2-nistp384|ecdh-sha2-nistp521|curve25519-sha256|curve25519-sha256@libssh.org)$</regex> + <regex>(diffie-hellman-group1-sha1|diffie-hellman-group14-sha1|diffie-hellman-group14-sha256|diffie-hellman-group16-sha512|diffie-hellman-group18-sha512|diffie-hellman-group-exchange-sha1|diffie-hellman-group-exchange-sha256|ecdh-sha2-nistp256|ecdh-sha2-nistp384|ecdh-sha2-nistp521|curve25519-sha256|curve25519-sha256@libssh.org)</regex> </constraint> </properties> </leafNode> @@ -102,10 +174,10 @@ <description>enable logging of failed login attempts</description> </valueHelp> <constraint> - <regex>^(quiet|fatal|error|info|verbose)$</regex> + <regex>(quiet|fatal|error|info|verbose)</regex> </constraint> </properties> - <defaultValue>INFO</defaultValue> + <defaultValue>info</defaultValue> </leafNode> <leafNode name="mac"> <properties> @@ -115,7 +187,7 @@ <list>hmac-sha1 hmac-sha1-96 hmac-sha2-256 hmac-sha2-512 hmac-md5 hmac-md5-96 umac-64@openssh.com umac-128@openssh.com hmac-sha1-etm@openssh.com hmac-sha1-96-etm@openssh.com hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com hmac-md5-etm@openssh.com hmac-md5-96-etm@openssh.com umac-64-etm@openssh.com umac-128-etm@openssh.com</list> </completionHelp> <constraint> - <regex>^(hmac-sha1|hmac-sha1-96|hmac-sha2-256|hmac-sha2-512|hmac-md5|hmac-md5-96|umac-64@openssh.com|umac-128@openssh.com|hmac-sha1-etm@openssh.com|hmac-sha1-96-etm@openssh.com|hmac-sha2-256-etm@openssh.com|hmac-sha2-512-etm@openssh.com|hmac-md5-etm@openssh.com|hmac-md5-96-etm@openssh.com|umac-64-etm@openssh.com|umac-128-etm@openssh.com)$</regex> + <regex>(hmac-sha1|hmac-sha1-96|hmac-sha2-256|hmac-sha2-512|hmac-md5|hmac-md5-96|umac-64@openssh.com|umac-128@openssh.com|hmac-sha1-etm@openssh.com|hmac-sha1-96-etm@openssh.com|hmac-sha2-256-etm@openssh.com|hmac-sha2-512-etm@openssh.com|hmac-md5-etm@openssh.com|hmac-md5-96-etm@openssh.com|umac-64-etm@openssh.com|umac-128-etm@openssh.com)</regex> </constraint> <multi/> </properties> diff --git a/interface-definitions/system-conntrack.xml.in b/interface-definitions/system-conntrack.xml.in index daa4177c9..14f12b569 100644 --- a/interface-definitions/system-conntrack.xml.in +++ b/interface-definitions/system-conntrack.xml.in @@ -35,6 +35,128 @@ </properties> <defaultValue>32768</defaultValue> </leafNode> + <node name="ignore"> + <properties> + <help>Customized rules to ignore selective connection tracking</help> + </properties> + <children> + <tagNode name="rule"> + <properties> + <help>Rule number</help> + <valueHelp> + <format>u32:1-999999</format> + <description>Number of conntrack ignore rule</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-999999"/> + </constraint> + <constraintErrorMessage>Ignore rule number must be between 1 and 999999</constraintErrorMessage> + </properties> + <children> + #include <include/generic-description.xml.i> + <node name="destination"> + <properties> + <help>Destination parameters</help> + </properties> + <children> + #include <include/nat-address.xml.i> + #include <include/nat-port.xml.i> + </children> + </node> + <leafNode name="inbound-interface"> + <properties> + <help>Interface to ignore connections tracking on</help> + <completionHelp> + <list>any</list> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + </properties> + </leafNode> + #include <include/ip-protocol.xml.i> + <leafNode name="protocol"> + <properties> + <help>Protocol to match (protocol name, number, or "all")</help> + <completionHelp> + <script>${vyos_completion_dir}/list_protocols.sh</script> + <list>all tcp_udp</list> + </completionHelp> + <valueHelp> + <format>all</format> + <description>All IP protocols</description> + </valueHelp> + <valueHelp> + <format>tcp_udp</format> + <description>Both TCP and UDP</description> + </valueHelp> + <valueHelp> + <format>u32:0-255</format> + <description>IP protocol number</description> + </valueHelp> + <valueHelp> + <format><protocol></format> + <description>IP protocol name</description> + </valueHelp> + <valueHelp> + <format>!<protocol></format> + <description>IP protocol name</description> + </valueHelp> + <constraint> + <validator name="ip-protocol"/> + </constraint> + </properties> + </leafNode> + <node name="source"> + <properties> + <help>Source parameters</help> + </properties> + <children> + #include <include/nat-address.xml.i> + #include <include/nat-port.xml.i> + </children> + </node> + </children> + </tagNode> + </children> + </node> + <node name="log"> + <properties> + <help>Log connection tracking events per protocol</help> + </properties> + <children> + <node name="icmp"> + <properties> + <help>Log connection tracking events for ICMP</help> + </properties> + <children> + #include <include/conntrack/log-common.xml.i> + </children> + </node> + <node name="other"> + <properties> + <help>Log connection tracking events for all protocols other than TCP, UDP and ICMP</help> + </properties> + <children> + #include <include/conntrack/log-common.xml.i> + </children> + </node> + <node name="tcp"> + <properties> + <help>Log connection tracking events for TCP</help> + </properties> + <children> + #include <include/conntrack/log-common.xml.i> + </children> + </node> + <node name="udp"> + <properties> + <help>Log connection tracking events for UDP</help> + </properties> + <children> + #include <include/conntrack/log-common.xml.i> + </children> + </node> + </children> + </node> <node name="modules"> <properties> <help>Connection tracking modules</help> @@ -130,7 +252,7 @@ <description>Do not allow tracking of previously established connections</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> <defaultValue>enable</defaultValue> @@ -155,176 +277,66 @@ <help>Connection timeout options</help> </properties> <children> - <leafNode name="icmp"> - <properties> - <help>ICMP timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>ICMP timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>30</defaultValue> - </leafNode> - <leafNode name="other"> - <properties> - <help>Generic connection timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>Generic connection timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>600</defaultValue> - </leafNode> - <node name="tcp"> - <properties> - <help>TCP connection timeout options</help> - </properties> - <children> - <leafNode name="close-wait"> - <properties> - <help>TCP CLOSE-WAIT timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>TCP CLOSE-WAIT timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>60</defaultValue> - </leafNode> - <leafNode name="close"> - <properties> - <help>TCP CLOSE timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>TCP CLOSE timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>10</defaultValue> - </leafNode> - <leafNode name="established"> - <properties> - <help>TCP ESTABLISHED timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>TCP ESTABLISHED timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>432000</defaultValue> - </leafNode> - <leafNode name="fin-wait"> - <properties> - <help>TCP FIN-WAIT timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>TCP FIN-WAIT timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>120</defaultValue> - </leafNode> - <leafNode name="last-ack"> - <properties> - <help>TCP LAST-ACK timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>TCP LAST-ACK timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>30</defaultValue> - </leafNode> - <leafNode name="syn-recv"> - <properties> - <help>TCP SYN-RECEIVED timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>TCP SYN-RECEIVED timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>60</defaultValue> - </leafNode> - <leafNode name="syn-sent"> - <properties> - <help>TCP SYN-SENT timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>TCP SYN-SENT timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>120</defaultValue> - </leafNode> - <leafNode name="time-wait"> - <properties> - <help>TCP TIME-WAIT timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>TCP TIME-WAIT timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>120</defaultValue> - </leafNode> - </children> - </node> - <node name="udp"> + <node name="custom"> <properties> - <help>UDP timeout options</help> + <help>Define custom timeouts per connection</help> </properties> <children> - <leafNode name="other"> + <tagNode name="rule"> <properties> - <help>UDP generic timeout in seconds</help> + <help>Rule number</help> <valueHelp> - <format>u32:1-21474836</format> - <description>UDP generic timeout in seconds</description> + <format>u32:1-999999</format> + <description>Number of conntrack rule</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 1-21474836"/> + <validator name="numeric" argument="--range 1-999999"/> </constraint> + <constraintErrorMessage>Ignore rule number must be between 1 and 999999</constraintErrorMessage> </properties> - <defaultValue>30</defaultValue> - </leafNode> - <leafNode name="stream"> - <properties> - <help>UDP stream timeout in seconds</help> - <valueHelp> - <format>u32:1-21474836</format> - <description>UDP stream timeout in seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-21474836"/> - </constraint> - </properties> - <defaultValue>180</defaultValue> - </leafNode> + <children> + #include <include/generic-description.xml.i> + <node name="destination"> + <properties> + <help>Destination parameters</help> + </properties> + <children> + #include <include/nat-address.xml.i> + #include <include/nat-port.xml.i> + </children> + </node> + <leafNode name="inbound-interface"> + <properties> + <help>Interface to ignore connections tracking on</help> + <completionHelp> + <list>any</list> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + </properties> + </leafNode> + #include <include/ip-protocol.xml.i> + <node name="protocol"> + <properties> + <help>Customize protocol specific timers, one protocol configuration per rule</help> + </properties> + <children> + #include <include/conntrack/timeout-common-protocols.xml.i> + </children> + </node> + <node name="source"> + <properties> + <help>Source parameters</help> + </properties> + <children> + #include <include/nat-address.xml.i> + #include <include/nat-port.xml.i> + </children> + </node> + </children> + </tagNode> </children> </node> + #include <include/conntrack/timeout-common-protocols.xml.i> </children> </node> </children> diff --git a/interface-definitions/system-console.xml.in b/interface-definitions/system-console.xml.in index 2897e5e97..5acd3e90b 100644 --- a/interface-definitions/system-console.xml.in +++ b/interface-definitions/system-console.xml.in @@ -28,7 +28,7 @@ <description>Xen console</description> </valueHelp> <constraint> - <regex>^(ttyS[0-9]+|hvc[0-9]+|usb[0-9]+b.*)$</regex> + <regex>(ttyS[0-9]+|hvc[0-9]+|usb[0-9]+b.*)</regex> </constraint> </properties> <children> @@ -71,7 +71,7 @@ <description>115200 bps</description> </valueHelp> <constraint> - <regex>^(1200|2400|4800|9600|19200|38400|57600|115200)$</regex> + <regex>(1200|2400|4800|9600|19200|38400|57600|115200)</regex> </constraint> </properties> <defaultValue>115200</defaultValue> diff --git a/interface-definitions/system-ip.xml.in b/interface-definitions/system-ip.xml.in index 86fbe5701..21d70694b 100644 --- a/interface-definitions/system-ip.xml.in +++ b/interface-definitions/system-ip.xml.in @@ -5,7 +5,8 @@ <node name="ip" owner="${vyos_conf_scripts_dir}/system-ip.py"> <properties> <help>IPv4 Settings</help> - <priority>400</priority> + <!-- must be before any interface, check /opt/vyatta/sbin/priority.pl --> + <priority>290</priority> </properties> <children> <node name="arp"> @@ -13,18 +14,7 @@ <help>Parameters for ARP cache</help> </properties> <children> - <leafNode name="table-size"> - <properties> - <help>Maximum number of entries to keep in the ARP cache (default: 8192)</help> - <completionHelp> - <list>1024 2048 4096 8192 16384 32768</list> - </completionHelp> - <constraint> - <regex>^(1024|2048|4096|8192|16384|32768)$</regex> - </constraint> - </properties> - <defaultValue>8192</defaultValue> - </leafNode> + #include <include/arp-ndp-table-size.xml.i> </children> </node> <leafNode name="disable-forwarding"> diff --git a/interface-definitions/system-ipv6.xml.in b/interface-definitions/system-ipv6.xml.in index 5ee7adf54..63260d00c 100644 --- a/interface-definitions/system-ipv6.xml.in +++ b/interface-definitions/system-ipv6.xml.in @@ -5,6 +5,7 @@ <node name="ipv6" owner="${vyos_conf_scripts_dir}/system-ipv6.py"> <properties> <help>IPv6 Settings</help> + <!-- must be before any interface, check /opt/vyatta/sbin/priority.pl --> <priority>290</priority> </properties> <children> @@ -14,12 +15,6 @@ <valueless/> </properties> </leafNode> - <leafNode name="disable"> - <properties> - <help>Disable assignment of IPv6 addresses on all interfaces</help> - <valueless/> - </properties> - </leafNode> <node name="multipath"> <properties> <help>IPv6 multipath settings</help> @@ -35,20 +30,10 @@ </node> <node name="neighbor"> <properties> - <help>Parameters for Neighbor cache</help> + <help>Parameters for neighbor discovery cache</help> </properties> <children> - <leafNode name="table-size"> - <properties> - <help>Maximum number of entries to keep in the Neighbor cache</help> - <completionHelp> - <list>1024 2048 4096 8192 16384 32768</list> - </completionHelp> - <constraint> - <regex>^(1024|2048|4096|8192|16384|32768)$</regex> - </constraint> - </properties> - </leafNode> + #include <include/arp-ndp-table-size.xml.i> </children> </node> <leafNode name="strict-dad"> diff --git a/interface-definitions/system-lcd.xml.in b/interface-definitions/system-lcd.xml.in index 4c9d5c92e..9b1a15317 100644 --- a/interface-definitions/system-lcd.xml.in +++ b/interface-definitions/system-lcd.xml.in @@ -39,7 +39,7 @@ <description>Lanner, Watchguard, Nexcom NSA, Sophos UTM appliances</description> </valueHelp> <constraint> - <regex>^(cfa-533|cfa-631|cfa-633|cfa-635|hd44780|sdec)$</regex> + <regex>(cfa-533|cfa-631|cfa-633|cfa-635|hd44780|sdec)</regex> </constraint> </properties> </leafNode> @@ -59,7 +59,7 @@ <description>TTY device name, USB based</description> </valueHelp> <constraint> - <regex>^(ttyS[0-9]+|usb[0-9]+b.*)$</regex> + <regex>(ttyS[0-9]+|usb[0-9]+b.*)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/system-login-banner.xml.in b/interface-definitions/system-login-banner.xml.in index c4bb14bd6..bdd0ad96a 100644 --- a/interface-definitions/system-login-banner.xml.in +++ b/interface-definitions/system-login-banner.xml.in @@ -15,12 +15,12 @@ <children> <leafNode name="post-login"> <properties> - <help>System loging banner post-login</help> + <help>A system banner after the user logs in </help> </properties> </leafNode> <leafNode name="pre-login"> <properties> - <help>System loging banner pre-login</help> + <help>A system banner before the user logs in</help> </properties> </leafNode> </children> diff --git a/interface-definitions/system-login.xml.in b/interface-definitions/system-login.xml.in index 4bfe82268..24eeee355 100644 --- a/interface-definitions/system-login.xml.in +++ b/interface-definitions/system-login.xml.in @@ -12,7 +12,7 @@ <properties> <help>Local user account information</help> <constraint> - <regex>^[-_a-zA-Z0-9.]{1,100}</regex> + <regex>[-_a-zA-Z0-9.]{1,100}</regex> </constraint> <constraintErrorMessage>Username contains illegal characters or\nexceeds 100 character limitation.</constraintErrorMessage> </properties> @@ -27,7 +27,7 @@ <help>Encrypted password</help> <constraint> <regex>(\*|\!)</regex> - <regex>[a-zA-Z0-9\.\/]{13}$</regex> + <regex>[a-zA-Z0-9\.\/]{13}</regex> <regex>\$1\$[a-zA-Z0-9\./]*\$[a-zA-Z0-9\./]{22}</regex> <regex>\$5\$[a-zA-Z0-9\./]*\$[a-zA-Z0-9\./]{43}</regex> <regex>\$6\$[a-zA-Z0-9\./]*\$[a-zA-Z0-9\./]{86}</regex> @@ -90,7 +90,7 @@ <description/> </valueHelp> <constraint> - <regex>^(ssh-dss|ssh-rsa|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|ssh-ed25519)$</regex> + <regex>(ssh-dss|ssh-rsa|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|ssh-ed25519)</regex> </constraint> </properties> </leafNode> @@ -102,7 +102,7 @@ <properties> <help>Full name of the user (use quotes for names with spaces)</help> <constraint> - <regex>[^:]*$</regex> + <regex>[^:]*</regex> </constraint> <constraintErrorMessage>Cannot use ':' in full name</constraintErrorMessage> </properties> @@ -124,7 +124,7 @@ <help>Session timeout</help> <valueHelp> <format>u32:1-30</format> - <description>Session timeout in seconds (default: 2)</description> + <description>Session timeout in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-30"/> @@ -138,7 +138,7 @@ <help>Server priority</help> <valueHelp> <format>u32:1-255</format> - <description>Server priority (default: 255)</description> + <description>Server priority</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-255"/> diff --git a/interface-definitions/system-logs.xml.in b/interface-definitions/system-logs.xml.in new file mode 100644 index 000000000..1caa7abb6 --- /dev/null +++ b/interface-definitions/system-logs.xml.in @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interfaceDefinition> + <node name="system"> + <children> + <node name="logs" owner="${vyos_conf_scripts_dir}/system-logs.py"> + <properties> + <help>Logging options</help> + <priority>9999</priority> + </properties> + <children> + <node name="logrotate"> + <properties> + <help>Logrotate options</help> + </properties> + <children> + <node name="atop"> + <properties> + <help>Atop logs options (system resources usage)</help> + </properties> + <children> + <leafNode name="max-size"> + <properties> + <help>Size of a single log file that triggers rotation</help> + <valueHelp> + <format>u32:1-1024</format> + <description>Size in MB</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-1024" /> + </constraint> + <constraintErrorMessage>The size must be between 1 and 1024 MB</constraintErrorMessage> + </properties> + <defaultValue>10</defaultValue> + </leafNode> + <leafNode name="rotate"> + <properties> + <help>Count of rotations before old logs will be deleted</help> + <valueHelp> + <format>u32:1-100</format> + <description>Rotations</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-100" /> + </constraint> + <constraintErrorMessage>The count must be between 1 and 100</constraintErrorMessage> + </properties> + <defaultValue>10</defaultValue> + </leafNode> + </children> + </node> + <node name="messages"> + <properties> + <help>The /var/log/messages file rotation</help> + </properties> + <children> + <leafNode name="max-size"> + <properties> + <help>Size of a single log file that triggers rotation</help> + <valueHelp> + <format>u32:1-1024</format> + <description>Size in MB</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-1024" /> + </constraint> + <constraintErrorMessage>The size must be between 1 and 1024 MB</constraintErrorMessage> + </properties> + <defaultValue>1</defaultValue> + </leafNode> + <leafNode name="rotate"> + <properties> + <help>Count of rotations before old logs will be deleted</help> + <valueHelp> + <format>u32:1-100</format> + <description>Rotations</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-100" /> + </constraint> + <constraintErrorMessage>The count must be between 1 and 100</constraintErrorMessage> + </properties> + <defaultValue>10</defaultValue> + </leafNode> + </children> + </node> + </children> + </node> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/interface-definitions/system-option.xml.in b/interface-definitions/system-option.xml.in index 75fa67271..8cd25799b 100644 --- a/interface-definitions/system-option.xml.in +++ b/interface-definitions/system-option.xml.in @@ -27,7 +27,7 @@ <description>Poweroff system</description> </valueHelp> <constraint> - <regex>^(ignore|reboot|poweroff)$</regex> + <regex>(ignore|reboot|poweroff)</regex> </constraint> <constraintErrorMessage>Must be ignore, reboot, or poweroff</constraintErrorMessage> </properties> @@ -84,7 +84,7 @@ <description>Tune for low network latency</description> </valueHelp> <constraint> - <regex>^(throughput|latency)$</regex> + <regex>(throughput|latency)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/system-proxy.xml.in b/interface-definitions/system-proxy.xml.in index ade168522..1c06b347f 100644 --- a/interface-definitions/system-proxy.xml.in +++ b/interface-definitions/system-proxy.xml.in @@ -11,7 +11,7 @@ <properties> <help>Proxy URL</help> <constraint> - <regex>http:\/\/[a-z0-9\.]+$</regex> + <regex>http:\/\/[a-z0-9\.]+</regex> </constraint> </properties> </leafNode> @@ -20,7 +20,7 @@ <properties> <help>Proxy username</help> <constraint> - <regex>[a-z0-9-_\.]{1,100}$</regex> + <regex>[a-z0-9-_\.]{1,100}</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/system-syslog.xml.in b/interface-definitions/system-syslog.xml.in index 9280a43c8..480cb1ca6 100644 --- a/interface-definitions/system-syslog.xml.in +++ b/interface-definitions/system-syslog.xml.in @@ -28,7 +28,7 @@ <list>auth authpriv cron daemon kern lpr mail mark news protocols security syslog user uucp local0 local1 local2 local3 local4 local5 local6 local7 all</list> </completionHelp> <constraint> - <regex>^(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)$</regex> + <regex>(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)</regex> </constraint> <constraintErrorMessage>Invalid facility type</constraintErrorMessage> <valueHelp> @@ -132,7 +132,7 @@ <list>emerg alert crit err warning notice info debug all</list> </completionHelp> <constraint> - <regex>^(emerg|alert|crit|err|warning|notice|info|debug|all)$</regex> + <regex>(emerg|alert|crit|err|warning|notice|info|debug|all)</regex> </constraint> <constraintErrorMessage>Invalid loglevel</constraintErrorMessage> <valueHelp> @@ -203,7 +203,7 @@ <list>auth authpriv cron daemon kern lpr mail mark news protocols security syslog user uucp local0 local1 local2 local3 local4 local5 local6 local7 all</list> </completionHelp> <constraint> - <regex>^(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)$</regex> + <regex>(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)</regex> </constraint> <constraintErrorMessage>Invalid facility type</constraintErrorMessage> <valueHelp> @@ -315,7 +315,7 @@ <list>udp tcp</list> </completionHelp> <constraint> - <regex>^(udp|tcp)$</regex> + <regex>(udp|tcp)</regex> </constraint> <constraintErrorMessage>invalid protocol name</constraintErrorMessage> </properties> @@ -327,7 +327,7 @@ <list>emerg alert crit err warning notice info debug all</list> </completionHelp> <constraint> - <regex>^(emerg|alert|crit|err|warning|notice|info|debug|all)$</regex> + <regex>(emerg|alert|crit|err|warning|notice|info|debug|all)</regex> </constraint> <constraintErrorMessage>Invalid loglevel</constraintErrorMessage> <valueHelp> @@ -422,7 +422,7 @@ <list>auth authpriv cron daemon kern lpr mail mark news protocols security syslog user uucp local0 local1 local2 local3 local4 local5 local6 local7 all</list> </completionHelp> <constraint> - <regex>^(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)$</regex> + <regex>(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)</regex> </constraint> <constraintErrorMessage>Invalid facility type</constraintErrorMessage> <valueHelp> @@ -526,7 +526,7 @@ <list>emerg alert crit err warning notice info debug all</list> </completionHelp> <constraint> - <regex>^(emerg|alert|crit|err|warning|notice|info|debug|all)$</regex> + <regex>(emerg|alert|crit|err|warning|notice|info|debug|all)</regex> </constraint> <constraintErrorMessage>Invalid loglevel</constraintErrorMessage> <valueHelp> @@ -633,7 +633,7 @@ <list>auth authpriv cron daemon kern lpr mail mark news protocols security syslog user uucp local0 local1 local2 local3 local4 local5 local6 local7 all</list> </completionHelp> <constraint> - <regex>^(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)$</regex> + <regex>(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)</regex> </constraint> <constraintErrorMessage>Invalid facility type</constraintErrorMessage> <valueHelp> @@ -737,7 +737,7 @@ <list>emerg alert crit err warning notice info debug all</list> </completionHelp> <constraint> - <regex>^(emerg|alert|crit|err|warning|notice|info|debug|all)$</regex> + <regex>(emerg|alert|crit|err|warning|notice|info|debug|all)</regex> </constraint> <constraintErrorMessage>Invalid loglevel</constraintErrorMessage> <valueHelp> @@ -794,7 +794,7 @@ <list>auth authpriv cron daemon kern lpr mail mark news protocols security syslog user uucp local0 local1 local2 local3 local4 local5 local6 local7 all</list> </completionHelp> <constraint> - <regex>^(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)$</regex> + <regex>(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)</regex> </constraint> <constraintErrorMessage>Invalid facility type</constraintErrorMessage> <valueHelp> @@ -898,7 +898,7 @@ <list>emerg alert crit err warning notice info debug all</list> </completionHelp> <constraint> - <regex>^(emerg|alert|crit|err|warning|notice|info|debug|all)$</regex> + <regex>(emerg|alert|crit|err|warning|notice|info|debug|all)</regex> </constraint> <constraintErrorMessage>Invalid loglevel</constraintErrorMessage> <valueHelp> diff --git a/interface-definitions/tftp-server.xml.in b/interface-definitions/tftp-server.xml.in index 037c097ca..4963eab3c 100644 --- a/interface-definitions/tftp-server.xml.in +++ b/interface-definitions/tftp-server.xml.in @@ -24,7 +24,7 @@ <leafNode name="port"> <defaultValue>69</defaultValue> </leafNode> - #include <include/listen-address.xml.i> + #include <include/listen-address-vrf.xml.i> </children> </node> </children> diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in index e82249d44..555ba689f 100644 --- a/interface-definitions/vpn_ipsec.xml.in +++ b/interface-definitions/vpn_ipsec.xml.in @@ -13,13 +13,13 @@ <children> <leafNode name="disable-uniqreqids"> <properties> - <help>Option to disable requirement for unique IDs in the Security Database</help> + <help>Disable requirement for unique IDs in the Security Database</help> <valueless/> </properties> </leafNode> <tagNode name="esp-group"> <properties> - <help>Name of Encapsulating Security Payload (ESP) group</help> + <help>Encapsulated Security Payload (ESP) group name</help> </properties> <children> <leafNode name="compression"> @@ -30,14 +30,14 @@ </completionHelp> <valueHelp> <format>disable</format> - <description>Disable ESP compression (default)</description> + <description>Disable ESP compression</description> </valueHelp> <valueHelp> <format>enable</format> <description>Enable ESP compression</description> </valueHelp> <constraint> - <regex>^(disable|enable)$</regex> + <regex>(disable|enable)</regex> </constraint> </properties> <defaultValue>disable</defaultValue> @@ -47,7 +47,7 @@ <help>ESP lifetime</help> <valueHelp> <format>u32:30-86400</format> - <description>ESP lifetime in seconds (default 3600)</description> + <description>ESP lifetime in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 30-86400"/> @@ -55,6 +55,30 @@ </properties> <defaultValue>3600</defaultValue> </leafNode> + <leafNode name="life-bytes"> + <properties> + <help>ESP life in bytes</help> + <valueHelp> + <format>u32:1024-26843545600000</format> + <description>ESP life in bytes</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1024-26843545600000"/> + </constraint> + </properties> + </leafNode> + <leafNode name="life-packets"> + <properties> + <help>ESP life in packets</help> + <valueHelp> + <format>u32:1000-26843545600000</format> + <description>ESP life in packets</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1000-26843545600000"/> + </constraint> + </properties> + </leafNode> <leafNode name="mode"> <properties> <help>ESP mode</help> @@ -63,14 +87,14 @@ </completionHelp> <valueHelp> <format>tunnel</format> - <description>Tunnel mode (default)</description> + <description>Tunnel mode</description> </valueHelp> <valueHelp> <format>transport</format> <description>Transport mode</description> </valueHelp> <constraint> - <regex>^(tunnel|transport)$</regex> + <regex>(tunnel|transport)</regex> </constraint> </properties> <defaultValue>tunnel</defaultValue> @@ -83,7 +107,7 @@ </completionHelp> <valueHelp> <format>enable</format> - <description>Inherit Diffie-Hellman group from IKE group - default</description> + <description>Inherit Diffie-Hellman group from the IKE group</description> </valueHelp> <valueHelp> <format>dh-group1</format> @@ -178,17 +202,17 @@ <description>Disable PFS</description> </valueHelp> <constraint> - <regex>^(enable|dh-group1|dh-group2|dh-group5|dh-group14|dh-group15|dh-group16|dh-group17|dh-group18|dh-group19|dh-group20|dh-group21|dh-group22|dh-group23|dh-group24|dh-group25|dh-group26|dh-group27|dh-group28|dh-group29|dh-group30|dh-group31|dh-group32|disable)$</regex> + <regex>(enable|dh-group1|dh-group2|dh-group5|dh-group14|dh-group15|dh-group16|dh-group17|dh-group18|dh-group19|dh-group20|dh-group21|dh-group22|dh-group23|dh-group24|dh-group25|dh-group26|dh-group27|dh-group28|dh-group29|dh-group30|dh-group31|dh-group32|disable)</regex> </constraint> </properties> <defaultValue>enable</defaultValue> </leafNode> <tagNode name="proposal"> <properties> - <help>ESP-group proposal [REQUIRED]</help> + <help>ESP group proposal [REQUIRED]</help> <valueHelp> <format>u32:1-65535</format> - <description>ESP-group proposal number</description> + <description>ESP group proposal number</description> </valueHelp> </properties> <children> @@ -200,33 +224,29 @@ </tagNode> <tagNode name="ike-group"> <properties> - <help>Name of Internet Key Exchange (IKE) group</help> + <help>Internet Key Exchange (IKE) group name</help> </properties> <children> <leafNode name="close-action"> <properties> - <help>close-action_help</help> + <help>Action to take if a child SA is unexpectedly closed</help> <completionHelp> - <list>none hold clear restart</list> + <list>none hold restart</list> </completionHelp> <valueHelp> <format>none</format> - <description>Set action to none (default)</description> + <description>Do nothing</description> </valueHelp> <valueHelp> <format>hold</format> - <description>Set action to hold</description> - </valueHelp> - <valueHelp> - <format>clear</format> - <description>Set action to clear</description> + <description>Attempt to re-negotiate when matching traffic is seen</description> </valueHelp> <valueHelp> <format>restart</format> - <description>Set action to restart</description> + <description>Attempt to re-negotiate the connection immediately</description> </valueHelp> <constraint> - <regex>^(none|hold|clear|restart)$</regex> + <regex>(none|hold|restart)</regex> </constraint> </properties> </leafNode> @@ -243,18 +263,18 @@ </completionHelp> <valueHelp> <format>hold</format> - <description>Set action to hold (default)</description> + <description>Attempt to re-negotiate the connection when matching traffic is seen</description> </valueHelp> <valueHelp> <format>clear</format> - <description>Set action to clear</description> + <description>Remove the connection immediately</description> </valueHelp> <valueHelp> <format>restart</format> - <description>Set action to restart</description> + <description>Attempt to re-negotiate the connection immediately</description> </valueHelp> <constraint> - <regex>^(hold|clear|restart)$</regex> + <regex>(hold|clear|restart)</regex> </constraint> </properties> </leafNode> @@ -263,30 +283,32 @@ <help>Keep-alive interval</help> <valueHelp> <format>u32:2-86400</format> - <description>Keep-alive interval in seconds (default 30)</description> + <description>Keep-alive interval in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 2-86400"/> </constraint> </properties> + <defaultValue>30</defaultValue> </leafNode> <leafNode name="timeout"> <properties> - <help>Dead-Peer-Detection keep-alive timeout (IKEv1 only)</help> + <help>Dead Peer Detection keep-alive timeout (IKEv1 only)</help> <valueHelp> <format>u32:2-86400</format> - <description>Keep-alive timeout in seconds (default 120)</description> + <description>Keep-alive timeout in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 2-86400"/> </constraint> </properties> + <defaultValue>120</defaultValue> </leafNode> </children> </node> <leafNode name="ikev2-reauth"> <properties> - <help>ikev2-reauth_help</help> + <help>Re-authentication of the remote peer during an IKE re-key - IKEv2 only</help> <completionHelp> <list>yes no</list> </completionHelp> @@ -296,29 +318,29 @@ </valueHelp> <valueHelp> <format>no</format> - <description>Disable remote host re-authenticaton during an IKE rekey. (Default)</description> + <description>Disable remote host re-authenticaton during an IKE rekey</description> </valueHelp> <constraint> - <regex>^(yes|no)$</regex> + <regex>(yes|no)</regex> </constraint> </properties> </leafNode> <leafNode name="key-exchange"> <properties> - <help>Key Exchange Version</help> + <help>IKE version</help> <completionHelp> <list>ikev1 ikev2</list> </completionHelp> <valueHelp> <format>ikev1</format> - <description>Use IKEv1 for Key Exchange [DEFAULT]</description> + <description>Use IKEv1 for key exchange</description> </valueHelp> <valueHelp> <format>ikev2</format> - <description>Use IKEv2 for Key Exchange</description> + <description>Use IKEv2 for key exchange</description> </valueHelp> <constraint> - <regex>^(ikev1|ikev2)$</regex> + <regex>(ikev1|ikev2)</regex> </constraint> </properties> </leafNode> @@ -327,7 +349,7 @@ <help>IKE lifetime</help> <valueHelp> <format>u32:30-86400</format> - <description>IKE lifetime in seconds (default 28800)</description> + <description>IKE lifetime in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 30-86400"/> @@ -337,48 +359,50 @@ </leafNode> <leafNode name="mobike"> <properties> - <help>Enable MOBIKE Support. MOBIKE is only available for IKEv2.</help> + <help>Enable MOBIKE Support (IKEv2 only)</help> <completionHelp> <list>enable disable</list> </completionHelp> <valueHelp> <format>enable</format> - <description>Enable MOBIKE (default for IKEv2)</description> + <description>Enable MOBIKE</description> </valueHelp> <valueHelp> <format>disable</format> <description>Disable MOBIKE</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> + <defaultValue>enable</defaultValue> </leafNode> <leafNode name="mode"> <properties> - <help>IKEv1 Phase 1 Mode Selection</help> + <help>IKEv1 phase 1 mode selection</help> <completionHelp> <list>main aggressive</list> </completionHelp> <valueHelp> <format>main</format> - <description>Use Main mode for Key Exchanges in the IKEv1 Protocol (Recommended Default)</description> + <description>Use the main mode (recommended)</description> </valueHelp> <valueHelp> <format>aggressive</format> - <description>Use Aggressive mode for Key Exchanges in the IKEv1 protocol - We do not recommend users to use aggressive mode as it is much more insecure compared to Main mode.</description> + <description>Use the aggressive mode (insecure, not recommended)</description> </valueHelp> <constraint> - <regex>^(main|aggressive)$</regex> + <regex>(main|aggressive)</regex> </constraint> </properties> + <defaultValue>main</defaultValue> </leafNode> <tagNode name="proposal"> <properties> - <help>proposal_help</help> + <help>IKE proposal</help> <valueHelp> <format>u32:1-65535</format> - <description>IKE-group proposal</description> + <description>IKE group proposal</description> </valueHelp> </properties> <children> @@ -477,7 +501,7 @@ <description>Diffie-Hellman group 32 (curve448)</description> </valueHelp> <constraint> - <regex>^(1|2|5|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32)$</regex> + <regex>(1|2|5|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32)</regex> </constraint> </properties> <defaultValue>2</defaultValue> @@ -490,12 +514,12 @@ </tagNode> <leafNode name="include-ipsec-conf"> <properties> - <help>Sets to include an additional configuration directive file for strongSwan. Use an absolute path to specify the included file</help> + <help>Absolute path to specify a strongSwan config include file</help> </properties> </leafNode> <leafNode name="include-ipsec-secrets"> <properties> - <help>Sets to include an additional secrets file for strongSwan. Use an absolute path to specify the included file.</help> + <help>Absolute path to a strongSwan secrets include file</help> </properties> </leafNode> #include <include/generic-interface-multi.xml.i> @@ -506,10 +530,10 @@ <children> <leafNode name="level"> <properties> - <help>strongSwan Logger Level</help> + <help>strongSwan logging Level</help> <valueHelp> <format>0</format> - <description>Very basic auditing logs e.g. SA up/SA down (default)</description> + <description>Very basic auditing logs e.g. SA up/SA down</description> </valueHelp> <valueHelp> <format>1</format> @@ -527,7 +551,7 @@ </leafNode> <leafNode name="subsystem"> <properties> - <help>Subsystem in the daemon the log comes from</help> + <help>Subsystem logging levels</help> <completionHelp> <list>dmn mgr ike chd job cfg knl net asn enc lib esp tls tnc imc imv pts any</list> </completionHelp> @@ -604,7 +628,7 @@ <description>Any subsystem</description> </valueHelp> <constraint> - <regex>^(dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|lib|esp|tls|tnc|imc|imv|pts|any)$</regex> + <regex>(dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|lib|esp|tls|tnc|imc|imv|pts|any)</regex> </constraint> <multi/> </properties> @@ -622,11 +646,24 @@ <valueless/> </properties> </leafNode> + <leafNode name="flexvpn"> + <properties> + <help>Allow FlexVPN vendor ID payload (IKEv2 only)</help> + <valueless/> + </properties> + </leafNode> + #include <include/generic-interface.xml.i> + <leafNode name="virtual-ip"> + <properties> + <help>Allow install virtual-ip addresses</help> + <valueless/> + </properties> + </leafNode> </children> </node> <tagNode name="profile"> <properties> - <help>VPN IPSec Profile</help> + <help>VPN IPSec profile</help> </properties> <children> #include <include/generic-disable-node.xml.i> @@ -643,7 +680,7 @@ </completionHelp> <valueHelp> <format>pre-shared-secret</format> - <description>Use pre shared secret key</description> + <description>Use a pre-shared secret key</description> </valueHelp> </properties> </leafNode> @@ -657,13 +694,13 @@ <children> <leafNode name="tunnel"> <properties> - <help>Tunnel interface associated with this configuration profile</help> + <help>Tunnel interface associated with this profile</help> <completionHelp> <path>interfaces tunnel</path> </completionHelp> <valueHelp> <format>txt</format> - <description>Associated interface to this configuration profile</description> + <description>Associated interface to this profile</description> </valueHelp> <multi/> </properties> @@ -699,18 +736,18 @@ </completionHelp> <valueHelp> <format>eap-tls</format> - <description>Client uses EAP-TLS authentication</description> + <description>Use EAP-TLS authentication</description> </valueHelp> <valueHelp> <format>eap-mschapv2</format> - <description>Client uses EAP-MSCHAPv2 authentication</description> + <description>Use EAP-MSCHAPv2 authentication</description> </valueHelp> <valueHelp> <format>eap-radius</format> - <description>Client uses EAP-RADIUS authentication</description> + <description>Use EAP-RADIUS authentication</description> </valueHelp> <constraint> - <regex>^(eap-tls|eap-mschapv2|eap-radius)$</regex> + <regex>(eap-tls|eap-mschapv2|eap-radius)</regex> </constraint> </properties> <defaultValue>eap-mschapv2</defaultValue> @@ -724,14 +761,14 @@ </completionHelp> <valueHelp> <format>pre-shared-secret</format> - <description>Authentication pre-shared-secret</description> + <description>Use a pre-shared secret key</description> </valueHelp> <valueHelp> <format>x509</format> - <description>Authentication x509</description> + <description>Use x.509 certificate</description> </valueHelp> <constraint> - <regex>^(pre-shared-secret|x509)$</regex> + <regex>(pre-shared-secret|x509)</regex> </constraint> </properties> <defaultValue>x509</defaultValue> @@ -754,7 +791,7 @@ </valueHelp> <valueHelp> <format>u32:1-86400</format> - <description>Timeout in seconds (default 28800)</description> + <description>Timeout in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-86400"/> @@ -764,14 +801,14 @@ </leafNode> <leafNode name="pool"> <properties> - <help>Pool name used for IP address assignments</help> + <help>IP address pool</help> <completionHelp> <path>vpn ipsec remote-access pool</path> <list>dhcp radius</list> </completionHelp> <valueHelp> <format>txt</format> - <description>Name of predefined IP pool</description> + <description>Predefined IP pool name</description> </valueHelp> <valueHelp> <format>dhcp</format> @@ -786,24 +823,24 @@ </leafNode> <leafNode name="unique"> <properties> - <help>Connection uniqueness policy to enforce</help> + <help>Connection uniqueness enforcement policy</help> <completionHelp> <list>never keep replace</list> </completionHelp> <valueHelp> <format>never</format> - <description>Never enforce connection uniqueness policy</description> + <description>Never enforce connection uniqueness</description> </valueHelp> <valueHelp> <format>keep</format> - <description>Rejects new connection attempts if the same user already has an active connection</description> + <description>Reject new connection attempts if the same user already has an active connection</description> </valueHelp> <valueHelp> <format>replace</format> <description>Delete any existing connection if a new one for the same user gets established</description> </valueHelp> <constraint> - <regex>^(never|keep|replace)$</regex> + <regex>(never|keep|replace)</regex> </constraint> </properties> </leafNode> @@ -811,7 +848,7 @@ </tagNode> <node name="dhcp"> <properties> - <help>DHCP pool options for remote-access</help> + <help>DHCP pool options for remote access</help> </properties> <children> #include <include/generic-interface.xml.i> @@ -831,18 +868,18 @@ </node> <tagNode name="pool"> <properties> - <help>IP address pool for remote-access users</help> + <help>IP address pool for remote access users</help> </properties> <children> <leafNode name="exclude"> <properties> <help>Local IPv4 or IPv6 pool prefix exclusions</help> <valueHelp> - <format>ipv4</format> + <format>ipv4net</format> <description>Local IPv4 pool prefix exclusion</description> </valueHelp> <valueHelp> - <format>ipv6</format> + <format>ipv6net</format> <description>Local IPv6 pool prefix exclusion</description> </valueHelp> <constraint> @@ -856,11 +893,11 @@ <properties> <help>Local IPv4 or IPv6 pool prefix</help> <valueHelp> - <format>ipv4</format> + <format>ipv4net</format> <description>Local IPv4 pool prefix</description> </valueHelp> <valueHelp> - <format>ipv6</format> + <format>ipv6net</format> <description>Local IPv6 pool prefix</description> </valueHelp> <constraint> @@ -936,10 +973,10 @@ </valueHelp> <valueHelp> <format>x509</format> - <description>Use X.509 certificate</description> + <description>Use x.509 certificate</description> </valueHelp> <constraint> - <regex>^(pre-shared-secret|rsa|x509)$</regex> + <regex>(pre-shared-secret|rsa|x509)</regex> </constraint> </properties> </leafNode> @@ -965,7 +1002,7 @@ <properties> <help>Connection type</help> <completionHelp> - <list>initiate respond</list> + <list>initiate respond none</list> </completionHelp> <valueHelp> <format>initiate</format> @@ -975,8 +1012,12 @@ <format>respond</format> <description>Bring the connection up only if traffic is detected</description> </valueHelp> + <valueHelp> + <format>none</format> + <description>Load the connection only</description> + </valueHelp> <constraint> - <regex>^(initiate|respond)$</regex> + <regex>(initiate|respond|none)</regex> </constraint> </properties> </leafNode> @@ -992,27 +1033,27 @@ #include <include/dhcp-interface.xml.i> <leafNode name="force-encapsulation"> <properties> - <help>Force UDP Encapsulation for ESP Payloads</help> + <help>Force UDP Encapsulation for ESP payloads</help> <completionHelp> <list>enable disable</list> </completionHelp> <valueHelp> <format>enable</format> - <description>This endpoint will force UDP encapsulation for this peer</description> + <description>Force UDP encapsulation</description> </valueHelp> <valueHelp> <format>disable</format> - <description>This endpoint will not force UDP encapsulation for this peer</description> + <description>Do not force UDP encapsulation</description> </valueHelp> <constraint> - <regex>^(enable|disable)$</regex> + <regex>(enable|disable)</regex> </constraint> </properties> </leafNode> #include <include/ipsec/ike-group.xml.i> <leafNode name="ikev2-reauth"> <properties> - <help>Re-authentication of the remote peer during an IKE re-key. IKEv2 option only</help> + <help>Re-authentication of the remote peer during an IKE re-key (IKEv2 only)</help> <completionHelp> <list>yes no inherit</list> </completionHelp> @@ -1026,10 +1067,10 @@ </valueHelp> <valueHelp> <format>inherit</format> - <description>Inherit the reauth configuration form your IKE-group (Default)</description> + <description>Inherit the reauth configuration form your IKE-group</description> </valueHelp> <constraint> - <regex>^(yes|no|inherit)$</regex> + <regex>(yes|no|inherit)</regex> </constraint> </properties> </leafNode> @@ -1047,9 +1088,21 @@ #include <include/ipsec/esp-group.xml.i> #include <include/ipsec/local-traffic-selector.xml.i> #include <include/ip-protocol.xml.i> + <leafNode name="priority"> + <properties> + <help>Priority for IPSec policy (lowest value more preferable)</help> + <valueHelp> + <format>u32:1-100</format> + <description>Priority for IPSec policy (lowest value more preferable)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-100"/> + </constraint> + </properties> + </leafNode> <node name="remote"> <properties> - <help>Remote parameters for interesting traffic</help> + <help>Match remote addresses</help> </properties> <children> #include <include/port-number.xml.i> @@ -1057,11 +1110,11 @@ <properties> <help>Remote IPv4 or IPv6 prefix</help> <valueHelp> - <format>ipv4</format> + <format>ipv4net</format> <description>Remote IPv4 prefix</description> </valueHelp> <valueHelp> - <format>ipv6</format> + <format>ipv6net</format> <description>Remote IPv6 prefix</description> </valueHelp> <constraint> @@ -1075,6 +1128,20 @@ </node> </children> </tagNode> + <leafNode name="virtual-address"> + <properties> + <help>Initiator request virtual-address from peer</help> + <valueHelp> + <format>ipv4</format> + <description>Request IPv4 address from peer</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>Request IPv6 address from peer</description> + </valueHelp> + <multi/> + </properties> + </leafNode> <node name="vti"> <properties> <help>Virtual tunnel interface [REQUIRED]</help> diff --git a/interface-definitions/vpn_l2tp.xml.in b/interface-definitions/vpn_l2tp.xml.in index 6a88756a7..f734283e7 100644 --- a/interface-definitions/vpn_l2tp.xml.in +++ b/interface-definitions/vpn_l2tp.xml.in @@ -72,7 +72,7 @@ <description>Use X.509 certificate for IPsec authentication</description> </valueHelp> <constraint> - <regex>^(pre-shared-secret|x509)$</regex> + <regex>(pre-shared-secret|x509)</regex> </constraint> <completionHelp> <list>pre-shared-secret x509</list> @@ -88,7 +88,7 @@ <help>IKE lifetime</help> <valueHelp> <format>u32:30-86400</format> - <description>IKE lifetime in seconds (default 3600)</description> + <description>IKE lifetime in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 30-86400"/> @@ -101,7 +101,7 @@ <help>ESP lifetime</help> <valueHelp> <format>u32:30-86400</format> - <description>IKE lifetime in seconds (default 3600)</description> + <description>IKE lifetime in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 30-86400"/> @@ -135,7 +135,7 @@ <help>PPP idle timeout</help> <valueHelp> <format>u32:30-86400</format> - <description>PPP idle timeout in seconds (default 1800)</description> + <description>PPP idle timeout in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 30-86400"/> @@ -167,7 +167,7 @@ <description>Require the peer to authenticate itself using MS-CHAPv2 [Microsoft Challenge Handshake Authentication Protocol, Version 2].</description> </valueHelp> <constraint> - <regex>^(pap|chap|mschap|mschap-v2)$</regex> + <regex>(pap|chap|mschap|mschap-v2)</regex> </constraint> <completionHelp> <list>pap chap mschap mschap-v2</list> @@ -206,7 +206,7 @@ </leafNode> <leafNode name="acct-timeout"> <properties> - <help>Timeout to wait reply for Interim-Update packets. (default 3 seconds)</help> + <help>Timeout to wait reply for Interim-Update packets</help> </properties> </leafNode> <leafNode name="max-try"> @@ -244,7 +244,7 @@ <children> <leafNode name="attribute"> <properties> - <help>Specifies which radius attribute contains rate information. (default is Filter-Id)</help> + <help>Specifies which radius attribute contains rate information</help> </properties> </leafNode> <leafNode name="vendor"> diff --git a/interface-definitions/vpn_openconnect.xml.in b/interface-definitions/vpn_openconnect.xml.in index 0db5e79d0..21b47125d 100644 --- a/interface-definitions/vpn_openconnect.xml.in +++ b/interface-definitions/vpn_openconnect.xml.in @@ -13,26 +13,120 @@ <help>Authentication for remote access SSL VPN Server</help> </properties> <children> - <leafNode name="mode"> + <node name="mode"> <properties> <help>Authentication mode used by this server</help> - <valueHelp> - <format>local</format> - <description>Use local username/password configuration</description> - </valueHelp> - <valueHelp> - <format>radius</format> - <description>Use RADIUS server for user autentication</description> - </valueHelp> - <constraint> - <regex>^(local|radius)$</regex> - </constraint> - <completionHelp> - <list>local radius</list> - </completionHelp> </properties> - </leafNode> + <children> + <leafNode name="local"> + <properties> + <help>Use local username/password configuration (OTP supported)</help> + <valueHelp> + <format>password</format> + <description>Password-only local authentication</description> + </valueHelp> + <valueHelp> + <format>otp</format> + <description>OTP-only local authentication</description> + </valueHelp> + <valueHelp> + <format>password-otp</format> + <description>Password (first) + OTP local authentication</description> + </valueHelp> + <constraint> + <regex>(password|otp|password-otp)</regex> + </constraint> + <constraintErrorMessage>Invalid authentication mode. Must be one of: password, otp or password-otp </constraintErrorMessage> + <completionHelp> + <list>otp password password-otp</list> + </completionHelp> + </properties> + </leafNode> + <leafNode name="radius"> + <properties> + <help>Use RADIUS server for user autentication</help> + <valueless/> + </properties> + </leafNode> + </children> + </node> #include <include/auth-local-users.xml.i> + <node name="local-users"> + <children> + <tagNode name="username"> + <children> + <node name="otp"> + <properties> + <help>2FA OTP authentication parameters</help> + </properties> + <children> + <leafNode name="key"> + <properties> + <help>Token Key Secret key for the token algorithm (see RFC 4226)</help> + <valueHelp> + <format>txt</format> + <description>OTP key in hex-encoded format</description> + </valueHelp> + <constraint> + <regex>[a-fA-F0-9]{20,10000}</regex> + </constraint> + <constraintErrorMessage>Key name must only include hex characters and be at least 20 characters long</constraintErrorMessage> + </properties> + </leafNode> + <leafNode name="otp-length"> + <properties> + <help>Number of digits in OTP code</help> + <valueHelp> + <format>u32:6-8</format> + <description>Number of digits in OTP code</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 6-8"/> + </constraint> + <constraintErrorMessage>Number of digits in OTP code must be between 6 and 8</constraintErrorMessage> + </properties> + <defaultValue>6</defaultValue> + </leafNode> + <leafNode name="interval"> + <properties> + <help>Time tokens interval in seconds</help> + <valueHelp> + <format>u32:5-86400</format> + <description>Time tokens interval in seconds.</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 5-86400"/> + </constraint> + <constraintErrorMessage>Time token interval must be between 5 and 86400 seconds</constraintErrorMessage> + </properties> + <defaultValue>30</defaultValue> + </leafNode> + <leafNode name="token-type"> + <properties> + <help>Token type</help> + <valueHelp> + <format>hotp-time</format> + <description>Time-based OTP algorithm</description> + </valueHelp> + <valueHelp> + <format>hotp-event</format> + <description>Event-based OTP algorithm</description> + </valueHelp> + <constraint> + <regex>(hotp-time|hotp-event)</regex> + </constraint> + <completionHelp> + <list>hotp-time hotp-event</list> + </completionHelp> + </properties> + <defaultValue>hotp-time</defaultValue> + </leafNode> + </children> + </node> + </children> + </tagNode> + </children> + </node> #include <include/radius-server-ipv4.xml.i> <node name="radius"> <children> @@ -40,13 +134,13 @@ <properties> <help>Session timeout</help> <valueHelp> - <format>u32:1-30</format> + <format>u32:1-240</format> <description>Session timeout in seconds (default: 2)</description> </valueHelp> <constraint> - <validator name="numeric" argument="--range 1-30"/> + <validator name="numeric" argument="--range 1-240"/> </constraint> - <constraintErrorMessage>Timeout must be between 1 and 30 seconds</constraintErrorMessage> + <constraintErrorMessage>Timeout must be between 1 and 240 seconds</constraintErrorMessage> </properties> <defaultValue>2</defaultValue> </leafNode> @@ -61,10 +155,10 @@ <children> <leafNode name="tcp"> <properties> - <help>tcp port number to accept connections (default: 443)</help> + <help>tcp port number to accept connections</help> <valueHelp> <format>u32:1-65535</format> - <description>Numeric IP port (default: 443)</description> + <description>Numeric IP port</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-65535"/> @@ -74,10 +168,10 @@ </leafNode> <leafNode name="udp"> <properties> - <help>udp port number to accept connections (default: 443)</help> + <help>udp port number to accept connections</help> <valueHelp> <format>u32:1-65535</format> - <description>Numeric IP port (default: 443)</description> + <description>Numeric IP port</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-65535"/> @@ -160,7 +254,7 @@ <help>Prefix length used for individual client</help> <valueHelp> <format>u32:48-128</format> - <description>Client prefix length (default: 64)</description> + <description>Client prefix length</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 48-128"/> diff --git a/interface-definitions/vpn_pptp.xml.in b/interface-definitions/vpn_pptp.xml.in index 0d1690013..28a53acb9 100644 --- a/interface-definitions/vpn_pptp.xml.in +++ b/interface-definitions/vpn_pptp.xml.in @@ -75,7 +75,7 @@ <description>ask client for mppe, if it rejects drop connection</description> </valueHelp> <constraint> - <regex>^(deny|prefer|require)$</regex> + <regex>(deny|prefer|require)</regex> </constraint> <completionHelp> <list>deny prefer require</list> diff --git a/interface-definitions/vrf.xml.in b/interface-definitions/vrf.xml.in index d6a602f53..25a573887 100644 --- a/interface-definitions/vrf.xml.in +++ b/interface-definitions/vrf.xml.in @@ -28,6 +28,22 @@ <children> #include <include/interface/description.xml.i> #include <include/interface/disable.xml.i> + <node name="ip"> + <properties> + <help>IPv4 routing parameters</help> + </properties> + <children> + #include <include/interface/disable-forwarding.xml.i> + </children> + </node> + <node name="ipv6"> + <properties> + <help>IPv6 routing parameters</help> + </properties> + <children> + #include <include/interface/disable-forwarding.xml.i> + </children> + </node> <node name="protocols"> <properties> <help>Routing protocol parameters</help> @@ -60,6 +76,15 @@ #include <include/ospf/protocol-common-config.xml.i> </children> </node> + <node name="ospfv3" owner="${vyos_conf_scripts_dir}/protocols_ospfv3.py $VAR(../../@)"> + <properties> + <help>Open Shortest Path First (OSPF) for IPv6</help> + <priority>621</priority> + </properties> + <children> + #include <include/ospfv3/protocol-common-config.xml.i> + </children> + </node> <node name="static" owner="${vyos_conf_scripts_dir}/protocols_static.py $VAR(../../@)"> <properties> <help>Static route parameters</help> diff --git a/interface-definitions/xml-component-version.xml.in b/interface-definitions/xml-component-version.xml.in new file mode 100644 index 000000000..b7f063a6c --- /dev/null +++ b/interface-definitions/xml-component-version.xml.in @@ -0,0 +1,44 @@ +<?xml version="1.0"?> +<interfaceDefinition> + #include <include/version/bgp-version.xml.i> + #include <include/version/broadcast-relay-version.xml.i> + #include <include/version/cluster-version.xml.i> + #include <include/version/config-management-version.xml.i> + #include <include/version/conntrack-sync-version.xml.i> + #include <include/version/conntrack-version.xml.i> + #include <include/version/dhcp-relay-version.xml.i> + #include <include/version/dhcp-server-version.xml.i> + #include <include/version/dhcpv6-server-version.xml.i> + #include <include/version/dns-forwarding-version.xml.i> + #include <include/version/firewall-version.xml.i> + #include <include/version/flow-accounting-version.xml.i> + #include <include/version/https-version.xml.i> + #include <include/version/interfaces-version.xml.i> + #include <include/version/ipoe-server-version.xml.i> + #include <include/version/ipsec-version.xml.i> + #include <include/version/isis-version.xml.i> + #include <include/version/l2tp-version.xml.i> + #include <include/version/lldp-version.xml.i> + #include <include/version/mdns-version.xml.i> + #include <include/version/nat66-version.xml.i> + #include <include/version/nat-version.xml.i> + #include <include/version/ntp-version.xml.i> + #include <include/version/openconnect-version.xml.i> + #include <include/version/ospf-version.xml.i> + #include <include/version/policy-version.xml.i> + #include <include/version/pppoe-server-version.xml.i> + #include <include/version/pptp-version.xml.i> + #include <include/version/qos-version.xml.i> + #include <include/version/quagga-version.xml.i> + #include <include/version/rpki-version.xml.i> + #include <include/version/salt-version.xml.i> + #include <include/version/snmp-version.xml.i> + #include <include/version/ssh-version.xml.i> + #include <include/version/sstp-version.xml.i> + #include <include/version/system-version.xml.i> + #include <include/version/vrf-version.xml.i> + #include <include/version/vrrp-version.xml.i> + #include <include/version/vyos-accel-ppp-version.xml.i> + #include <include/version/wanloadbalance-version.xml.i> + #include <include/version/webproxy-version.xml.i> +</interfaceDefinition> diff --git a/interface-definitions/zone-policy.xml.in b/interface-definitions/zone-policy.xml.in new file mode 100644 index 000000000..8af0dcfb6 --- /dev/null +++ b/interface-definitions/zone-policy.xml.in @@ -0,0 +1,147 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="zone-policy" owner="${vyos_conf_scripts_dir}/zone_policy.py"> + <properties> + <help>Configure zone-policy</help> + <priority>250</priority> + </properties> + <children> + <tagNode name="zone"> + <properties> + <help>Zone name</help> + <valueHelp> + <format>txt</format> + <description>Zone name</description> + </valueHelp> + <constraint> + <regex>[a-zA-Z0-9][\w\-\.]*</regex> + </constraint> + </properties> + <children> + #include <include/generic-description.xml.i> + <leafNode name="default-action"> + <properties> + <help>Default-action for traffic coming into this zone</help> + <completionHelp> + <list>drop reject</list> + </completionHelp> + <valueHelp> + <format>drop</format> + <description>Drop silently</description> + </valueHelp> + <valueHelp> + <format>reject</format> + <description>Drop and notify source</description> + </valueHelp> + <constraint> + <regex>(drop|reject)</regex> + </constraint> + </properties> + <defaultValue>drop</defaultValue> + </leafNode> + <tagNode name="from"> + <properties> + <help>Zone from which to filter traffic</help> + <completionHelp> + <path>zone-policy zone</path> + </completionHelp> + </properties> + <children> + <node name="firewall"> + <properties> + <help>Firewall options</help> + </properties> + <children> + <leafNode name="ipv6-name"> + <properties> + <help>IPv6 firewall ruleset</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="name"> + <properties> + <help>IPv4 firewall ruleset</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + </children> + </tagNode> + <leafNode name="interface"> + <properties> + <help>Interface associated with zone</help> + <valueHelp> + <format>txt</format> + <description>Interface associated with zone</description> + </valueHelp> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + <multi/> + </properties> + </leafNode> + <node name="intra-zone-filtering"> + <properties> + <help>Intra-zone filtering</help> + </properties> + <children> + <leafNode name="action"> + <properties> + <help>Action for intra-zone traffic</help> + <completionHelp> + <list>accept drop</list> + </completionHelp> + <valueHelp> + <format>accept</format> + <description>Accept traffic</description> + </valueHelp> + <valueHelp> + <format>drop</format> + <description>Drop silently</description> + </valueHelp> + <constraint> + <regex>(accept|drop)</regex> + </constraint> + </properties> + </leafNode> + <node name="firewall"> + <properties> + <help>Use the specified firewall chain</help> + </properties> + <children> + <leafNode name="ipv6-name"> + <properties> + <help>IPv6 firewall ruleset</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + </leafNode> + <leafNode name="name"> + <properties> + <help>IPv4 firewall ruleset</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + </children> + </node> + <leafNode name="local-zone"> + <properties> + <help>Zone to be local-zone</help> + <valueless/> + </properties> + </leafNode> + </children> + </tagNode> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/conntrack-sync.xml.in b/op-mode-definitions/conntrack-sync.xml.in index 41a71b04a..3e29ecd39 100644 --- a/op-mode-definitions/conntrack-sync.xml.in +++ b/op-mode-definitions/conntrack-sync.xml.in @@ -87,6 +87,18 @@ </node> </children> </node> + <leafNode name="statistics"> + <properties> + <help>Show connection syncing statistics</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/conntrack_sync.py --show-statistics</command> + </leafNode> + <leafNode name="status"> + <properties> + <help>Show conntrack-sync status</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/conntrack_sync.py --show-status</command> + </leafNode> </children> </node> </children> diff --git a/op-mode-definitions/containers.xml.in b/op-mode-definitions/container.xml.in index b2b318786..fa66402dc 100644 --- a/op-mode-definitions/containers.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 ${vyos_op_scripts_dir}/containers_op.py --pull "${4}"</command> + <command>sudo podman image pull "${4}"</command> </tagNode> </children> </node> @@ -44,7 +44,51 @@ <script>sudo podman image ls -q</script> </completionHelp> </properties> - <command>sudo ${vyos_op_scripts_dir}/containers_op.py --remove "${4}"</command> + <command>sudo podman image rm --force "${4}"</command> + </tagNode> + </children> + </node> + </children> + </node> + <node name="generate"> + <children> + <node name="container"> + <properties> + <help>Generate Container Image</help> + </properties> + <children> + <tagNode name="image"> + <properties> + <help>Name of container image (tag)</help> + </properties> + <children> + <tagNode name="path"> + <properties> + <help>Path to Dockerfile</help> + <completionHelp> + <list><filename></list> + </completionHelp> + </properties> + <command>sudo podman build --layers --force-rm --tag "$4" $6</command> + </tagNode> + </children> + </tagNode> + </children> + </node> + </children> + </node> + <node name="monitor"> + <children> + <node name="log"> + <children> + <tagNode name="container"> + <properties> + <help>Monitor last lines of container logs</help> + <completionHelp> + <path>container name</path> + </completionHelp> + </properties> + <command>sudo podman logs --follow --names "$4"</command> </tagNode> </children> </node> @@ -56,13 +100,13 @@ <properties> <help>Show containers</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/containers_op.py --all</command> + <command>sudo podman ps --all</command> <children> <leafNode name="image"> <properties> - <help>Delete container image</help> + <help>Show container image</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/containers_op.py --image</command> + <command>sudo podman image ls</command> </leafNode> <tagNode name="log"> <properties> @@ -77,7 +121,7 @@ <properties> <help>Show available container networks</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/containers_op.py --networks</command> + <command>sudo podman network ls</command> </leafNode> </children> </node> @@ -118,12 +162,12 @@ <children> <tagNode name="image"> <properties> - <help>Delete container image</help> + <help>Update container image</help> <completionHelp> <path>container name</path> </completionHelp> </properties> - <command>sudo ${vyos_op_scripts_dir}/containers_op.py --update "${4}"</command> + <command>if cli-shell-api existsActive container name "$4"; then sudo podman pull $(cli-shell-api returnActiveValue container name "$4" image); else echo "Container $4 does not exist"; fi</command> </tagNode> </children> </node> diff --git a/op-mode-definitions/disks.xml.in b/op-mode-definitions/disks.xml.in index 2102a2e8e..117ac5065 100644 --- a/op-mode-definitions/disks.xml.in +++ b/op-mode-definitions/disks.xml.in @@ -20,7 +20,7 @@ <script>${vyos_completion_dir}/list_disks.py --exclude ${COMP_WORDS[2]}</script> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/format_disk.py --target $3 --proto $5</command> + <command>sudo ${vyos_op_scripts_dir}/format_disk.py --target $3 --proto $5</command> </tagNode> </children> </tagNode> diff --git a/op-mode-definitions/firewall.xml.in b/op-mode-definitions/firewall.xml.in new file mode 100644 index 000000000..b5dee7c9e --- /dev/null +++ b/op-mode-definitions/firewall.xml.in @@ -0,0 +1,191 @@ +<?xml version="1.0"?> +<interfaceDefinition> +<!-- + <node name="clear"> + <children> + <node name="firewall"> + <properties> + <help>Clear firewall statistics</help> + </properties> + <children> + <tagNode name="ipv6-name"> + <properties> + <help>Clear firewall statistics for chain</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + <children> + <leafNode name="counters"> + <properties> + <help>Clear counters for specified chain</help> + </properties> + <command>echo "TODO"</command> + </leafNode> + <tagNode name="rule"> + <properties> + <help>Clear firewall statistics for a rule</help> + <completionHelp> + <path>firewall ipv6-name ${COMP_WORDS[4]} rule</path> + </completionHelp> + </properties> + <children> + <leafNode name="counters"> + <properties> + <help>Clear counters for specified rule</help> + </properties> + <command>echo "TODO"</command> + </leafNode> + </children> + </tagNode> + </children> + </tagNode> + <tagNode name="name"> + <properties> + <help>Clear firewall statistics for chain</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + <children> + <leafNode name="counters"> + <properties> + <help>Clear counters for specified chain</help> + </properties> + <command>echo "TODO"</command> + </leafNode> + <tagNode name="rule"> + <properties> + <help>Clear firewall statistics for a rule</help> + <completionHelp> + <path>firewall name ${COMP_WORDS[4]} rule</path> + </completionHelp> + </properties> + <children> + <leafNode name="counters"> + <properties> + <help>Clear counters for specified rule</help> + </properties> + <command>echo "TODO"</command> + </leafNode> + </children> + </tagNode> + </children> + </tagNode> + </children> + </node> + </children> + </node> +--> +<!-- + <node name="reset"> + <children> + <node name="firewall"> + <properties> + <help>Reset a firewall group</help> + </properties> + <children> + <tagNode name="address-group"> + <properties> + <help>Reset a firewall address group</help> + </properties> + </tagNode> + <tagNode name="network-group"> + <properties> + <help>Reset a firewall network group</help> + </properties> + </tagNode> + <tagNode name="port-group"> + <properties> + <help>Reset a firewall port group</help> + </properties> + </tagNode> + </children> + </node> + </children> + </node> +--> + <node name="show"> + <children> + <node name="firewall"> + <properties> + <help>Show firewall information</help> + </properties> + <children> + <tagNode name="group"> + <properties> + <help>Show firewall group</help> + <completionHelp> + <path>firewall group address-group</path> + <path>firewall group network-group</path> + <path>firewall group port-group</path> + <path>firewall group ipv6-address-group</path> + <path>firewall group ipv6-network-group</path> + </completionHelp> + </properties> + <command>sudo ${vyos_op_scripts_dir}/firewall.py --action show_group --name $4</command> + </tagNode> + <leafNode name="group"> + <properties> + <help>Show firewall group</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/firewall.py --action show_group</command> + </leafNode> + <tagNode name="ipv6-name"> + <properties> + <help>Show IPv6 firewall chains</help> + <completionHelp> + <path>firewall ipv6-name</path> + </completionHelp> + </properties> + <children> + <tagNode name="rule"> + <properties> + <help>Show summary of IPv6 firewall rules</help> + <completionHelp> + <path>firewall ipv6-name ${COMP_WORDS[6]} rule</path> + </completionHelp> + </properties> + <command>sudo ${vyos_op_scripts_dir}/firewall.py --action show --name $4 --rule $6 --ipv6</command> + </tagNode> + </children> + <command>sudo ${vyos_op_scripts_dir}/firewall.py --action show --name $4 --ipv6</command> + </tagNode> + <tagNode name="name"> + <properties> + <help>Show IPv4 firewall chains</help> + <completionHelp> + <path>firewall name</path> + </completionHelp> + </properties> + <children> + <tagNode name="rule"> + <properties> + <help>Show summary of IPv4 firewall rules</help> + <completionHelp> + <path>firewall name ${COMP_WORDS[6]} rule</path> + </completionHelp> + </properties> + <command>sudo ${vyos_op_scripts_dir}/firewall.py --action show --name $4 --rule $6</command> + </tagNode> + </children> + <command>sudo ${vyos_op_scripts_dir}/firewall.py --action show --name $4</command> + </tagNode> + <leafNode name="statistics"> + <properties> + <help>Show statistics of firewall application</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/firewall.py --action show_statistics</command> + </leafNode> + <leafNode name="summary"> + <properties> + <help>Show summary of firewall application</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/firewall.py --action show_summary</command> + </leafNode> + </children> + <command>sudo ${vyos_op_scripts_dir}/firewall.py --action show_all</command> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/generate-openconnect-user-key.xml.in b/op-mode-definitions/generate-openconnect-user-key.xml.in new file mode 100644 index 000000000..80cdfb3d7 --- /dev/null +++ b/op-mode-definitions/generate-openconnect-user-key.xml.in @@ -0,0 +1,67 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="generate"> + <children> + <node name="openconnect"> + <properties> + <help>Generate OpenConnect client parameters</help> + </properties> + <children> + <tagNode name="username"> + <properties> + <help>Username used for authentication</help> + <completionHelp> + <list><username></list> + </completionHelp> + </properties> + <children> + <node name="otp-key"> + <properties> + <help>Generate OpenConnect OTP token</help> + </properties> + <children> + <node name="hotp-time"> + <properties> + <help>HOTP time-based token</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/generate_openconnect_otp_key.py --username "$4" --interval 30 --digits 6</command> + <children> + <tagNode name="interval"> + <properties> + <help>Duration of single time interval</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/generate_openconnect_otp_key.py --username "$4" --interval "$8" --digits 6</command> + <children> + <tagNode name="digits"> + <properties> + <help>The number of digits in the one-time password</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/generate_openconnect_otp_key.py --username "$4" --interval "$8" --digits "${10}"</command> + </tagNode> + </children> + </tagNode> + <tagNode name="digits"> + <properties> + <help>The number of digits in the one-time password</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/generate_openconnect_otp_key.py --username "$4" --interval 30 --digits "$8"</command> + <children> + <tagNode name="interval"> + <properties> + <help>Duration of single time interval</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/generate_openconnect_otp_key.py --username "$4" --interval "${10}" --digits $8</command> + </tagNode> + </children> + </tagNode> + </children> + </node> + </children> + </node> + </children> + </tagNode> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/generate-openvpn-config-client.xml.in b/op-mode-definitions/generate-openvpn-config-client.xml.in new file mode 100644 index 000000000..4f9f31bfe --- /dev/null +++ b/op-mode-definitions/generate-openvpn-config-client.xml.in @@ -0,0 +1,58 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="generate"> + <children> + <node name="openvpn"> + <properties> + <help>Generate OpenVPN client configuration ovpn file</help> + </properties> + <children> + <node name="client-config"> + <properties> + <help>Generate Client config</help> + </properties> + <children> + <tagNode name="interface"> + <properties> + <help>Local interface used for connection</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py --type openvpn</script> + </completionHelp> + </properties> + <children> + <tagNode name="ca"> + <properties> + <help>CA certificate</help> + <completionHelp> + <path>pki ca</path> + </completionHelp> + </properties> + <children> + <tagNode name="certificate"> + <properties> + <help>Cerificate used by client</help> + <completionHelp> + <path>pki certificate</path> + </completionHelp> + </properties> + <children> + <tagNode name="key"> + <properties> + <help>Certificate key used by client</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/generate_ovpn_client_file.py --interface "$5" --ca "$7" --cert "$9" --key "${11}"</command> + </tagNode> + </children> + <command>sudo ${vyos_op_scripts_dir}/generate_ovpn_client_file.py --interface "$5" --ca "$7" --cert "$9"</command> + </tagNode> + </children> + </tagNode> + </children> + </tagNode> + </children> + </node> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/include/bgp/afi-common.xml.i b/op-mode-definitions/include/bgp/afi-common.xml.i index 4d5f56656..acf20d950 100644 --- a/op-mode-definitions/include/bgp/afi-common.xml.i +++ b/op-mode-definitions/include/bgp/afi-common.xml.i @@ -61,5 +61,4 @@ </leafNode> </children> </node> -#include <include/vtysh-generic-wide.xml.i> <!-- included end --> diff --git a/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i index a51595b7f..084f5da83 100644 --- a/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i +++ b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i @@ -230,4 +230,5 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> </tagNode> +#include <include/vtysh-generic-wide.xml.i> <!-- included end --> diff --git a/op-mode-definitions/include/bgp/afi-ipv4-ipv6-flowspec.xml.i b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-flowspec.xml.i new file mode 100644 index 000000000..34228fdd1 --- /dev/null +++ b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-flowspec.xml.i @@ -0,0 +1,25 @@ +<!-- included start from bgp/afi-ipv4-ipv6-flowspec.xml.i --> +<tagNode name="flowspec"> + <properties> + <help>Network in the BGP routing table to display</help> + <completionHelp> + <list><x.x.x.x> <x.x.x.x/x> <h:h:h:h:h:h:h:h> <h:h:h:h:h:h:h:h/x></list> + </completionHelp> + </properties> + <children> + #include <include/bgp/prefix-bestpath-multipath.xml.i> + </children> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</tagNode> +<node name="flowspec"> + <properties> + <help>Flowspec Address Family modifier</help> + </properties> + <children> + #include <include/bgp/afi-common.xml.i> + #include <include/bgp/afi-ipv4-ipv6-common.xml.i> + #include <include/vtysh-generic-detail.xml.i> + </children> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</node> +<!-- included end --> diff --git a/op-mode-definitions/include/bgp/show-bgp-common.xml.i b/op-mode-definitions/include/bgp/show-bgp-common.xml.i index e81b26b3e..c9a112fca 100644 --- a/op-mode-definitions/include/bgp/show-bgp-common.xml.i +++ b/op-mode-definitions/include/bgp/show-bgp-common.xml.i @@ -20,6 +20,7 @@ <children> #include <include/bgp/afi-common.xml.i> #include <include/bgp/afi-ipv4-ipv6-common.xml.i> + #include <include/bgp/afi-ipv4-ipv6-flowspec.xml.i> #include <include/bgp/afi-ipv4-ipv6-vpn.xml.i> </children> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> diff --git a/op-mode-definitions/include/ospf-common.xml.i b/op-mode-definitions/include/ospf-common.xml.i index 0edc3c37f..23769c8ba 100644 --- a/op-mode-definitions/include/ospf-common.xml.i +++ b/op-mode-definitions/include/ospf-common.xml.i @@ -523,15 +523,6 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - <tagNode name="address"> - <properties> - <help>Show IPv4 OSPF neighbor information for specified IP address</help> - <completionHelp> - <list><x.x.x.x></list> - </completionHelp> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </tagNode> <node name="detail"> <properties> <help>Show detailed IPv4 OSPF neighbor information</help> diff --git a/op-mode-definitions/include/ospfv3/border-routers.xml.i b/op-mode-definitions/include/ospfv3/border-routers.xml.i new file mode 100644 index 000000000..b6fac6785 --- /dev/null +++ b/op-mode-definitions/include/ospfv3/border-routers.xml.i @@ -0,0 +1,20 @@ +<!-- included start from ospfv3/border-routers.xml.i --> +<node name="border-routers"> + <properties> + <help>Show OSPFv3 border-router (ABR and ASBR) information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + </children> +</node> +<tagNode name="border-routers"> + <properties> + <help>Border router ID</help> + <completionHelp> + <list><x.x.x.x></list> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</tagNode> +<!-- included end --> diff --git a/op-mode-definitions/include/ospfv3/database.xml.i b/op-mode-definitions/include/ospfv3/database.xml.i new file mode 100644 index 000000000..e98f9e35b --- /dev/null +++ b/op-mode-definitions/include/ospfv3/database.xml.i @@ -0,0 +1,238 @@ +<!-- included start from ospfv3/database.xml.i --> +<node name="database"> + <properties> + <help>Show OSPFv3 Link state database information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + <tagNode name="adv-router"> + <properties> + <help>Search by Advertising Router ID</help> + <completionHelp> + <list><x.x.x.x></list> + </completionHelp> + </properties> + <children> + #include <include/ospfv3/linkstate-id.xml.i> + </children> + </tagNode> + <node name="any"> + <properties> + <help>Search by Any Link state Type</help> + </properties> + <children> + <tagNode name="any"> + <properties> + <help>Search by Link state ID</help> + <completionHelp> + <list><x.x.x.x></list> + </completionHelp> + </properties> + <children> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + </children> + </tagNode> + </children> + </node> + <tagNode name="any"> + <properties> + <help>Search by Link state ID</help> + <completionHelp> + <list><x.x.x.x></list> + </completionHelp> + </properties> + <command>vtysh -c "show ipv6 ospf6 database * $6"</command> + <children> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/adv-router-id-node-tag.xml.i> + </children> + </tagNode> + <node name="as-external"> + <properties> + <help>Show AS-External LSAs</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/adv-router.xml.i> + <tagNode name="any"> + <properties> + <help>Search by Advertising Router ID</help> + <completionHelp> + <list><x.x.x.x></list> + </completionHelp> + </properties> + <command>vtysh -c "show ipv6 ospf6 database as-external * $7"</command> + <children> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + </children> + </tagNode> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/self-originated.xml.i> + </children> + </node> + <tagNode name="as-external"> + <properties> + <help>Search by Advertising Router IDs</help> + <completionHelp> + <list><x.x.x.x></list> + </completionHelp> + </properties> + <children> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/self-originated.xml.i> + #include <include/ospfv3/adv-router-id-node-tag.xml.i> + </children> + </tagNode> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/self-originated.xml.i> + <node name="group-membership"> + <properties> + <help>Show Group-Membership LSAs</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/adv-router.xml.i> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/linkstate-id-node-tag.xml.i> + #include <include/ospfv3/self-originated.xml.i> + </children> + </node> + <node name="inter-prefix"> + <properties> + <help>Show Inter-Area-Prefix LSAs</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/adv-router.xml.i> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/linkstate-id-node-tag.xml.i> + #include <include/ospfv3/self-originated.xml.i> + </children> + </node> + <node name="inter-router"> + <properties> + <help>Show Inter-Area-Router LSAs</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/adv-router.xml.i> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/linkstate-id-node-tag.xml.i> + #include <include/ospfv3/self-originated.xml.i> + </children> + </node> + <node name="intra-prefix"> + <properties> + <help>Show Intra-Area-Prefix LSAs</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/adv-router.xml.i> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/linkstate-id-node-tag.xml.i> + #include <include/ospfv3/self-originated.xml.i> + </children> + </node> + <node name="link"> + <properties> + <help>Show Link LSAs</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/adv-router.xml.i> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/linkstate-id-node-tag.xml.i> + #include <include/ospfv3/self-originated.xml.i> + </children> + </node> + <node name="network"> + <properties> + <help>Show Network LSAs</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/adv-router.xml.i> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/linkstate-id-node-tag.xml.i> + #include <include/ospfv3/self-originated.xml.i> + </children> + </node> + <node name="node.tag"> + <properties> + <help>Show LSAs</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/adv-router.xml.i> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/linkstate-id-node-tag.xml.i> + #include <include/ospfv3/self-originated.xml.i> + </children> + </node> + <node name="router"> + <properties> + <help>Show router LSAs</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/adv-router.xml.i> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/linkstate-id-node-tag.xml.i> + #include <include/ospfv3/self-originated.xml.i> + </children> + </node> + <node name="type-7"> + <properties> + <help>Show Type-7 LSAs</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/adv-router.xml.i> + #include <include/ospfv3/detail.xml.i> + #include <include/ospfv3/dump.xml.i> + #include <include/ospfv3/internal.xml.i> + #include <include/ospfv3/linkstate-id.xml.i> + #include <include/ospfv3/linkstate-id-node-tag.xml.i> + #include <include/ospfv3/self-originated.xml.i> + </children> + </node> + </children> +</node> +<!-- included end --> diff --git a/op-mode-definitions/include/ospfv3/interface.xml.i b/op-mode-definitions/include/ospfv3/interface.xml.i new file mode 100644 index 000000000..0fb66257d --- /dev/null +++ b/op-mode-definitions/include/ospfv3/interface.xml.i @@ -0,0 +1,75 @@ +<!-- included start from ospfv3/interface.xml.i --> +<node name="interface"> + <properties> + <help>Show OSPFv3 interface information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + <node name="prefix"> + <properties> + <help>Show connected prefixes to advertise</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + </children> + </node> + <tagNode name="prefix"> + <properties> + <help>Show interface prefix route specific information</help> + <completionHelp> + <list><h:h:h:h:h:h:h:h> <h:h:h:h:h:h:h:h/x></list> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + <node name="match"> + <properties> + <help>Matched interface prefix information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </node> + </children> + </tagNode> + </children> +</node> +<tagNode name="interface"> + <properties> + <help>Specific insterface to examine</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + <node name="prefix"> + <properties> + <help>Show connected prefixes to advertise</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + </children> + </node> + <tagNode name="prefix"> + <properties> + <help>Show interface prefix route specific information</help> + <completionHelp> + <list><h:h:h:h:h:h:h:h> <h:h:h:h:h:h:h:h/x></list> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + <node name="match"> + <properties> + <help>Matched interface prefix information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </node> + </children> + </tagNode> + </children> +</tagNode> +<!-- included end --> diff --git a/op-mode-definitions/include/ospfv3/linkstate.xml.i b/op-mode-definitions/include/ospfv3/linkstate.xml.i new file mode 100644 index 000000000..78ef3efa1 --- /dev/null +++ b/op-mode-definitions/include/ospfv3/linkstate.xml.i @@ -0,0 +1,38 @@ +<!-- included start from ospfv3/linkstate.xml.i --> +<node name="linkstate"> + <properties> + <help>Show OSPFv3 linkstate routing information</help> + </properties> + <children> + #include <include/ospfv3/detail.xml.i> + <tagNode name="network"> + <properties> + <help>Show linkstate Network information</help> + <completionHelp> + <list><x.x.x.x></list> + </completionHelp> + </properties> + <children> + <node name="node.tag"> + <properties> + <help>Specify Link state ID as IPv4 address notation</help> + <completionHelp> + <list><x.x.x.x></list> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </node> + </children> + </tagNode> + <tagNode name="router"> + <properties> + <help>Show linkstate Router information</help> + <completionHelp> + <list><x.x.x.x></list> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </tagNode> + </children> +</node> +<!-- included end --> diff --git a/op-mode-definitions/include/ospfv3/neighbor.xml.i b/op-mode-definitions/include/ospfv3/neighbor.xml.i new file mode 100644 index 000000000..37859f815 --- /dev/null +++ b/op-mode-definitions/include/ospfv3/neighbor.xml.i @@ -0,0 +1,17 @@ +<!-- included start from ospfv3/neighbor.xml.i --> +<node name="neighbor"> + <properties> + <help>Show OSPFv3 neighbor information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + <node name="drchoice"> + <properties> + <help>Show neighbor DR choice information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </node> + </children> +</node> +<!-- included end --> diff --git a/op-mode-definitions/include/ospfv3/redistribute.xml.i b/op-mode-definitions/include/ospfv3/redistribute.xml.i new file mode 100644 index 000000000..1c2d6494f --- /dev/null +++ b/op-mode-definitions/include/ospfv3/redistribute.xml.i @@ -0,0 +1,8 @@ +<!-- included start from ospfv3/redistribute.xml.i --> +<node name="redistribute"> + <properties> + <help>Show OSPFv3 redistribute external information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</node> +<!-- included end --> diff --git a/op-mode-definitions/include/ospfv3/route.xml.i b/op-mode-definitions/include/ospfv3/route.xml.i new file mode 100644 index 000000000..9271c9c3a --- /dev/null +++ b/op-mode-definitions/include/ospfv3/route.xml.i @@ -0,0 +1,79 @@ +<!-- included start from ospfv3/route.xml.i --> +<node name="route"> + <properties> + <help>Show OSPFv3 routing table information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + <node name="external-1"> + <properties> + <help>Show Type-1 External route information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + </children> + </node> + <node name="external-2"> + <properties> + <help>Show Type-2 External route information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + </children> + </node> + <node name="inter-area"> + <properties> + <help>Show Inter-Area route information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + </children> + </node> + <node name="intra-area"> + <properties> + <help>Show Intra-Area route information</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + </children> + </node> + #include <include/ospfv3/detail.xml.i> + <node name="summary"> + <properties> + <help>Show route table summary</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </node> + </children> +</node> +<tagNode name="route"> + <properties> + <help>Show specified route/prefix information</help> + <completionHelp> + <list><h:h:h:h:h:h:h:h> <h:h:h:h:h:h:h:h/x></list> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + <node name="longer"> + <properties> + <help>Show routes longer than specified prefix</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </node> + <node name="match"> + <properties> + <help>Show routes matching specified prefix</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/ospfv3/detail.xml.i> + </children> + </node> + </children> +</tagNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-bgp.xml.i b/op-mode-definitions/include/show-route-bgp.xml.i new file mode 100644 index 000000000..5c26bf43f --- /dev/null +++ b/op-mode-definitions/include/show-route-bgp.xml.i @@ -0,0 +1,8 @@ +<!-- included start from show-route-bgp.xml.i --> +<leafNode name="bgp"> + <properties> + <help>Border Gateway Protocol (BGP)</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</leafNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-connected.xml.i b/op-mode-definitions/include/show-route-connected.xml.i new file mode 100644 index 000000000..37364de64 --- /dev/null +++ b/op-mode-definitions/include/show-route-connected.xml.i @@ -0,0 +1,8 @@ +<!-- included start from show-route-connected.xml.i --> +<leafNode name="connected"> + <properties> + <help>Connected routes (directly attached subnet or host)</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</leafNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-isis.xml.i b/op-mode-definitions/include/show-route-isis.xml.i new file mode 100644 index 000000000..9ff2ccdc5 --- /dev/null +++ b/op-mode-definitions/include/show-route-isis.xml.i @@ -0,0 +1,8 @@ +<!-- included start from show-route-isis.xml.i --> +<leafNode name="isis"> + <properties> + <help>Intermediate System to Intermediate System (IS-IS)</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</leafNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-kernel.xml.i b/op-mode-definitions/include/show-route-kernel.xml.i new file mode 100644 index 000000000..8c5ac414e --- /dev/null +++ b/op-mode-definitions/include/show-route-kernel.xml.i @@ -0,0 +1,8 @@ +<!-- included start from show-route-kernel.xml.i --> +<leafNode name="kernel"> + <properties> + <help>Kernel routes (not installed via the zebra RIB)</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</leafNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-ospf.xml.i b/op-mode-definitions/include/show-route-ospf.xml.i new file mode 100644 index 000000000..1122aaba5 --- /dev/null +++ b/op-mode-definitions/include/show-route-ospf.xml.i @@ -0,0 +1,8 @@ +<!-- included start from show-route-ospf.xml.i --> +<leafNode name="ospf"> + <properties> + <help>Open Shortest Path First (OSPFv2)</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</leafNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-ospfv3.xml.i b/op-mode-definitions/include/show-route-ospfv3.xml.i new file mode 100644 index 000000000..c7a11b7ba --- /dev/null +++ b/op-mode-definitions/include/show-route-ospfv3.xml.i @@ -0,0 +1,8 @@ +<!-- included start from show-route-ospfv3.xml.i --> +<leafNode name="ospfv3"> + <properties> + <help>Open Shortest Path First (IPv6) (OSPFv3)</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</leafNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-rip.xml.i b/op-mode-definitions/include/show-route-rip.xml.i new file mode 100644 index 000000000..3c2fede28 --- /dev/null +++ b/op-mode-definitions/include/show-route-rip.xml.i @@ -0,0 +1,8 @@ +<!-- included start from show-route-rip.xml.i --> +<leafNode name="rip"> + <properties> + <help>Routing Information Protocol (RIP)</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</leafNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-ripng.xml.i b/op-mode-definitions/include/show-route-ripng.xml.i new file mode 100644 index 000000000..6e59cb054 --- /dev/null +++ b/op-mode-definitions/include/show-route-ripng.xml.i @@ -0,0 +1,8 @@ +<!-- included start from show-route-ripng.xml.i --> +<leafNode name="ripng"> + <properties> + <help>Routing Information Protocol next-generation (IPv6) (RIPng)</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</leafNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-static.xml.i b/op-mode-definitions/include/show-route-static.xml.i new file mode 100644 index 000000000..c2e396763 --- /dev/null +++ b/op-mode-definitions/include/show-route-static.xml.i @@ -0,0 +1,8 @@ +<!-- included start from show-route-static.xml.i --> +<leafNode name="static"> + <properties> + <help>Statically configured routes</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</leafNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-summary.xml.i b/op-mode-definitions/include/show-route-summary.xml.i new file mode 100644 index 000000000..471124562 --- /dev/null +++ b/op-mode-definitions/include/show-route-summary.xml.i @@ -0,0 +1,8 @@ +<!-- 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/include/show-route-supernets-only.xml.i b/op-mode-definitions/include/show-route-supernets-only.xml.i new file mode 100644 index 000000000..4d1e7c51f --- /dev/null +++ b/op-mode-definitions/include/show-route-supernets-only.xml.i @@ -0,0 +1,8 @@ +<!-- included start from show-route-supernets-only.xml.i --> +<leafNode name="supernets-only"> + <properties> + <help>Show supernet entries only</help> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</leafNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-table.xml.i b/op-mode-definitions/include/show-route-table.xml.i new file mode 100644 index 000000000..c3cf82a86 --- /dev/null +++ b/op-mode-definitions/include/show-route-table.xml.i @@ -0,0 +1,17 @@ +<!-- included start from show-route-table.xml.i --> +<node name="table"> + <properties> + <help>Table to display</help> + </properties> +</node> +<tagNode name="table"> + <properties> + <help>The table number to display</help> + <completionHelp> + <list>all</list> + <path>protocols static table</path> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</tagNode> +<!-- included end --> diff --git a/op-mode-definitions/include/show-route-tag.xml.i b/op-mode-definitions/include/show-route-tag.xml.i new file mode 100644 index 000000000..8bfa0ae4e --- /dev/null +++ b/op-mode-definitions/include/show-route-tag.xml.i @@ -0,0 +1,16 @@ +<!-- included start from show-route-tag.xml.i --> +<node name="tag"> + <properties> + <help>Show only routes with tag</help> + </properties> +</node> +<tagNode name="tag"> + <properties> + <help>Tag value</help> + <completionHelp> + <list><1-4294967295></list> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> +</tagNode> +<!-- included end --> diff --git a/op-mode-definitions/monitor-log.xml.in b/op-mode-definitions/monitor-log.xml.in index 352c84ff1..7ecce4f78 100644 --- a/op-mode-definitions/monitor-log.xml.in +++ b/op-mode-definitions/monitor-log.xml.in @@ -6,13 +6,181 @@ <properties> <help>Monitor last lines of messages file</help> </properties> - <command>tail --follow=name /var/log/messages</command> + <command>journalctl --no-hostname --follow --boot</command> <children> <node name="colored"> <properties> <help>Output log in a colored fashion</help> </properties> - <command>grc tail --follow=name /var/log/messages</command> + <command>grc journalctl --no-hostname --follow --boot</command> + </node> + <node name="dhcp"> + <properties> + <help>Monitor last lines of Dynamic Host Control Protocol (DHCP)</help> + </properties> + <children> + <node name="server"> + <properties> + <help>Monitor last lines of DHCP server</help> + </properties> + <command>journalctl --no-hostname --follow --boot --unit isc-dhcp-server.service</command> + </node> + <node name="client"> + <properties> + <help>Monitor last lines of DHCP client</help> + </properties> + <command>journalctl --no-hostname --follow --boot --unit "dhclient@*.service"</command> + <children> + <tagNode name="interface"> + <properties> + <help>Show DHCP client log on specific interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script> + </completionHelp> + </properties> + <command>journalctl --no-hostname --follow --boot --unit "dhclient@$6.service"</command> + </tagNode> + </children> + </node> + </children> + </node> + <node name="dhcpv6"> + <properties> + <help>Monitor last lines of Dynamic Host Control Protocol IPv6 (DHCPv6)</help> + </properties> + <children> + <node name="server"> + <properties> + <help>Monitor last lines of DHCPv6 server</help> + </properties> + <command>journalctl --no-hostname --follow --boot --unit isc-dhcp-server6.service</command> + </node> + <node name="client"> + <properties> + <help>Monitor last lines of DHCPv6 client</help> + </properties> + <command>journalctl --no-hostname --follow --boot --unit "dhcp6c@*.service"</command> + <children> + <tagNode name="interface"> + <properties> + <help>Show DHCPv6 client log on specific interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + </properties> + <command>journalctl --no-hostname --follow --boot --unit "dhcp6c@$6.service"</command> + </tagNode> + </children> + </node> + </children> + </node> + <leafNode name="flow-accounting"> + <properties> + <help>Monitor last lines of flow-accounting log</help> + </properties> + <command>journalctl --no-hostname --boot --follow --unit uacctd.service</command> + </leafNode> + <leafNode name="kernel"> + <properties> + <help>Monitor last lines of Linux Kernel log</help> + </properties> + <command>journalctl --no-hostname --boot --follow --dmesg</command> + </leafNode> + <leafNode name="nhrp"> + <properties> + <help>Monitor last lines of NHRP log</help> + </properties> + <command>journalctl --no-hostname --boot --unit opennhrp.service</command> + </leafNode> + <node name="pppoe"> + <properties> + <help>Monitor last lines of PPPoE log</help> + </properties> + <command>journalctl --no-hostname --boot --follow --unit "ppp@pppoe*.service"</command> + <children> + <tagNode name="interface"> + <properties> + <help>Monitor last lines of PPPoE log for specific interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py -t pppoe</script> + </completionHelp> + </properties> + <command>journalctl --no-hostname --boot --follow --unit "ppp@$6.service"</command> + </tagNode> + </children> + </node> + <node name="protocol"> + <properties> + <help>Monitor log for Routing Protocols</help> + </properties> + <children> + <leafNode name="ospf"> + <properties> + <help>Monitor log for OSPF</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/ospfd</command> + </leafNode> + <leafNode name="ospfv3"> + <properties> + <help>Monitor log for OSPF for IPv6</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/ospf6d</command> + </leafNode> + <leafNode name="bgp"> + <properties> + <help>Monitor log for BGP</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/bgpd</command> + </leafNode> + <leafNode name="rip"> + <properties> + <help>Monitor log for RIP</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/ripd</command> + </leafNode> + <leafNode name="ripng"> + <properties> + <help>Monitor log for RIPng</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/ripngd</command> + </leafNode> + <leafNode name="static"> + <properties> + <help>Monitor log for static route</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/staticd</command> + </leafNode> + <leafNode name="multicast"> + <properties> + <help>Monitor log for Multicast protocol</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/pimd</command> + </leafNode> + <leafNode name="isis"> + <properties> + <help>Monitor log for ISIS</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/isisd</command> + </leafNode> + <leafNode name="nhrp"> + <properties> + <help>Monitor log for NHRP</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/nhrpd</command> + </leafNode> + <leafNode name="bfd"> + <properties> + <help>Monitor log for BFD</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/bfdd</command> + </leafNode> + <leafNode name="mpls"> + <properties> + <help>Monitor log for MPLS</help> + </properties> + <command>journalctl --follow --no-hostname --boot /usr/lib/frr/ldpd</command> + </leafNode> + </children> </node> </children> </node> diff --git a/op-mode-definitions/policy-route.xml.in b/op-mode-definitions/policy-route.xml.in new file mode 100644 index 000000000..bd4a61dc9 --- /dev/null +++ b/op-mode-definitions/policy-route.xml.in @@ -0,0 +1,143 @@ +<?xml version="1.0"?> +<interfaceDefinition> +<!-- + <node name="clear"> + <children> + <node name="policy"> + <properties> + <help>Clear policy statistics</help> + </properties> + <children> + <tagNode name="ipv6-route"> + <properties> + <help>Clear policy statistics for chain</help> + <completionHelp> + <path>policy ipv6-route</path> + </completionHelp> + </properties> + <children> + <leafNode name="counters"> + <properties> + <help>Clear counters for specified chain</help> + </properties> + <command>echo "TODO"</command> + </leafNode> + <tagNode name="rule"> + <properties> + <help>Clear policy statistics for a rule</help> + <completionHelp> + <path>policy ipv6-route ${COMP_WORDS[4]} rule</path> + </completionHelp> + </properties> + <children> + <leafNode name="counters"> + <properties> + <help>Clear counters for specified rule</help> + </properties> + <command>echo "TODO"</command> + </leafNode> + </children> + </tagNode> + </children> + </tagNode> + <tagNode name="route"> + <properties> + <help>Clear policy statistics for chain</help> + <completionHelp> + <path>policy route</path> + </completionHelp> + </properties> + <children> + <leafNode name="counters"> + <properties> + <help>Clear counters for specified chain</help> + </properties> + <command>echo "TODO"</command> + </leafNode> + <tagNode name="rule"> + <properties> + <help>Clear policy statistics for a rule</help> + <completionHelp> + <path>policy route ${COMP_WORDS[4]} rule</path> + </completionHelp> + </properties> + <children> + <leafNode name="counters"> + <properties> + <help>Clear counters for specified rule</help> + </properties> + <command>echo "TODO"</command> + </leafNode> + </children> + </tagNode> + </children> + </tagNode> + </children> + </node> + </children> + </node> +--> + <node name="show"> + <children> + <node name="policy"> + <properties> + <help>Show policy information</help> + </properties> + <children> + <node name="route6"> + <properties> + <help>Show IPv6 policy chain</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/policy_route.py --action show_all --ipv6</command> + </node> + <tagNode name="route6"> + <properties> + <help>Show IPv6 policy chains</help> + <completionHelp> + <path>policy route6</path> + </completionHelp> + </properties> + <children> + <tagNode name="rule"> + <properties> + <help>Show summary of IPv6 policy rules</help> + <completionHelp> + <path>policy route6 ${COMP_WORDS[4]} rule</path> + </completionHelp> + </properties> + <command>sudo ${vyos_op_scripts_dir}/policy_route.py --action show --name $4 --rule $6 --ipv6</command> + </tagNode> + </children> + <command>sudo ${vyos_op_scripts_dir}/policy_route.py --action show --name $4 --ipv6</command> + </tagNode> + <node name="route"> + <properties> + <help>Show IPv4 policy chain</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/policy_route.py --action show_all</command> + </node> + <tagNode name="route"> + <properties> + <help>Show IPv4 policy chains</help> + <completionHelp> + <path>policy route</path> + </completionHelp> + </properties> + <children> + <tagNode name="rule"> + <properties> + <help>Show summary of IPv4 policy rules</help> + <completionHelp> + <path>policy route ${COMP_WORDS[4]} rule</path> + </completionHelp> + </properties> + <command>sudo ${vyos_op_scripts_dir}/policy_route.py --action show --name $4 --rule $6</command> + </tagNode> + </children> + <command>sudo ${vyos_op_scripts_dir}/policy_route.py --action show --name $4</command> + </tagNode> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/reboot.xml.in b/op-mode-definitions/reboot.xml.in index 2c8daec5d..6414742d9 100644 --- a/op-mode-definitions/reboot.xml.in +++ b/op-mode-definitions/reboot.xml.in @@ -25,7 +25,7 @@ <list><Minutes></list> </completionHelp> </properties> - <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --yes --reboot $3 $4</command> + <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --yes --reboot_in $3 $4</command> </tagNode> <tagNode name="at"> <properties> @@ -40,7 +40,7 @@ <properties> <help>Reboot at a specific date</help> <completionHelp> - <list><DDMMYYYY> <DD/MM/YYYY> <DD.MM.YYYY> <DD:MM:YYYY></list> + <list><DD/MM/YYYY> <DD.MM.YYYY> <DD:MM:YYYY></list> </completionHelp> </properties> <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --yes --reboot $3 $5</command> diff --git a/op-mode-definitions/restart-frr.xml.in b/op-mode-definitions/restart-frr.xml.in index 475bd1ee8..4e2be1bf2 100644 --- a/op-mode-definitions/restart-frr.xml.in +++ b/op-mode-definitions/restart-frr.xml.in @@ -26,6 +26,12 @@ </properties> <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon isisd</command> </leafNode> + <leafNode name="ldp"> + <properties> + <help>Restart the Label Distribution Protocol (LDP) daemon</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ldpd</command> + </leafNode> <leafNode name="ospf"> <properties> <help>Restart Open Shortest Path First (OSPF) routing daemon</help> diff --git a/op-mode-definitions/show-bfd.xml.in b/op-mode-definitions/show-bfd.xml.in new file mode 100644 index 000000000..39e42e6ec --- /dev/null +++ b/op-mode-definitions/show-bfd.xml.in @@ -0,0 +1,56 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="show"> + <children> + <node name="bfd"> + <properties> + <help>Show Bidirectional Forwarding Detection (BFD)</help> + </properties> + <children> + <node name="peer"> + <properties> + <help>Show all Bidirectional Forwarding Detection (BFD) peer status</help> + </properties> + </node> + <tagNode name="peer"> + <properties> + <help>Show Bidirectional Forwarding Detection (BFD) peer status</help> + <completionHelp> + <script>vtysh -c "show bfd peers" | awk '/[:blank:]*peer/ { printf "%s\n", $2 }'</script> + </completionHelp> + </properties> + <command>vtysh -c "show bfd peers" | sed -n "/peer $4 /,/^$/p"</command> + <children> + <leafNode name="counters"> + <properties> + <help>Show Bidirectional Forwarding Detection (BFD) peer counters</help> + </properties> + <command>vtysh -c "show bfd peers counters" | sed -n "/peer $4 /,/^$/p"</command> + </leafNode> + </children> + </tagNode> + <node name="peers"> + <properties> + <help>Show Bidirectional Forwarding Detection peers</help> + </properties> + <command>vtysh -c "show bfd peers"</command> + <children> + <leafNode name="counters"> + <properties> + <help>Show Bidirectional Forwarding Detection (BFD) peer counters</help> + </properties> + <command>vtysh -c "show bfd peers counters"</command> + </leafNode> + <leafNode name="brief"> + <properties> + <help>Show Bidirectional Forwarding Detection (BFD) peers brief</help> + </properties> + <command>vtysh -c "show bfd peers brief"</command> + </leafNode> + </children> + </node> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/show-configuration.xml.in b/op-mode-definitions/show-configuration.xml.in index 318942ab0..5a2fdedfa 100644 --- a/op-mode-definitions/show-configuration.xml.in +++ b/op-mode-definitions/show-configuration.xml.in @@ -30,6 +30,21 @@ <!-- no admin check --> <command>${vyos_op_scripts_dir}/show_configuration_files.sh</command> </node> + <node name="json"> + <properties> + <help>Show running configuration in JSON format</help> + </properties> + <!-- no admin check --> + <command>${vyos_op_scripts_dir}/show_configuration_json.py</command> + <children> + <node name="pretty"> + <properties> + <help>Show running configuration in readable JSON format</help> + </properties> + <command>${vyos_op_scripts_dir}/show_configuration_json.py --pretty</command> + </node> + </children> + </node> </children> </node> </children> diff --git a/op-mode-definitions/show-interfaces-geneve.xml.in b/op-mode-definitions/show-interfaces-geneve.xml.in new file mode 100644 index 000000000..a47933315 --- /dev/null +++ b/op-mode-definitions/show-interfaces-geneve.xml.in @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="show"> + <children> + <node name="interfaces"> + <children> + <tagNode name="geneve"> + <properties> + <help>Show specified GENEVE interface information</help> + <completionHelp> + <path>interfaces geneve</path> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/show_interfaces.py --intf="$4"</command> + <children> + <leafNode name="brief"> + <properties> + <help>Show summary of the specified GENEVE interface information</help> + </properties> + <command>${vyos_op_scripts_dir}/show_interfaces.py --intf="$4" --action=show-brief</command> + </leafNode> + </children> + </tagNode> + <node name="geneve"> + <properties> + <help>Show GENEVE interface information</help> + </properties> + <command>${vyos_op_scripts_dir}/show_interfaces.py --intf-type=geneve --action=show-brief</command> + <children> + <leafNode name="detail"> + <properties> + <help>Show detailed GENEVE interface information</help> + </properties> + <command>${vyos_op_scripts_dir}/show_interfaces.py --intf-type=geneve --action=show</command> + </leafNode> + </children> + </node> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/show-ip-route.xml.in b/op-mode-definitions/show-ip-route.xml.in index fdbb6859d..1e906672d 100644 --- a/op-mode-definitions/show-ip-route.xml.in +++ b/op-mode-definitions/show-ip-route.xml.in @@ -13,12 +13,7 @@ </properties> <command>vtysh -c "show ip route"</command> <children> - <leafNode name="bgp"> - <properties> - <help>Show IP BGP routes</help> - </properties> - <command>vtysh -c "show ip route bgp"</command> - </leafNode> + #include <include/show-route-bgp.xml.i> <node name="cache"> <properties> <help>Show kernel route cache</help> @@ -34,12 +29,7 @@ </properties> <command>ip -s route list cache $5</command> </tagNode> - <leafNode name="connected"> - <properties> - <help>Show IP connected routes</help> - </properties> - <command>vtysh -c "show ip route connected"</command> - </leafNode> + #include <include/show-route-connected.xml.i> <node name="forward"> <properties> <help>Show kernel route table</help> @@ -55,76 +45,15 @@ </properties> <command>ip -s route list $5</command> </tagNode> - <leafNode name="isis"> - <properties> - <help>Show IP IS-IS routes</help> - </properties> - <command>vtysh -c "show ip route isis"</command> - </leafNode> - <leafNode name="kernel"> - <properties> - <help>Show IP kernel routes</help> - </properties> - <command>vtysh -c "show ip route kernel"</command> - </leafNode> - <leafNode name="ospf"> - <properties> - <help>Show IP OSPF routes</help> - </properties> - <command>vtysh -c "show ip route ospf"</command> - </leafNode> - <leafNode name="rip"> - <properties> - <help>Show IP RIP routes</help> - </properties> - <command>vtysh -c "show ip route rip"</command> - </leafNode> - <leafNode name="static"> - <properties> - <help>Show IP static routes</help> - </properties> - <command>vtysh -c "show ip route static"</command> - </leafNode> - <leafNode name="summary"> - <properties> - <help>Show IP routes summary</help> - </properties> - <command>vtysh -c "show ip route summary"</command> - </leafNode> - <leafNode name="supernets-only"> - <properties> - <help>Show IP supernet routes</help> - </properties> - <command>vtysh -c "show ip route supernets-only"</command> - </leafNode> - <node name="table"> - <properties> - <help>Show IP routes in policy table</help> - </properties> - </node> - <tagNode name="table"> - <properties> - <help>Show IP routes in policy table</help> - <completionHelp> - <list><1-200></list> - </completionHelp> - </properties> - <command>vtysh -c "show ip route table $5"</command> - </tagNode> - <node name="tag"> - <properties> - <help>Show only routes with tag</help> - </properties> - </node> - <tagNode name="tag"> - <properties> - <help>Tag value</help> - <completionHelp> - <list><1-4294967295></list> - </completionHelp> - </properties> - <command>vtysh -c "show ip route tag $5"</command> - </tagNode> + #include <include/show-route-isis.xml.i> + #include <include/show-route-kernel.xml.i> + #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> <tagNode name="vrf"> <properties> <help>Show IP routes in VRF</help> @@ -133,7 +62,19 @@ <path>vrf name</path> </completionHelp> </properties> - <command>vtysh -c "show ip route vrf $5"</command> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/show-route-bgp.xml.i> + #include <include/show-route-connected.xml.i> + #include <include/show-route-isis.xml.i> + #include <include/show-route-kernel.xml.i> + #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> </tagNode> </children> </node> @@ -144,7 +85,7 @@ <list><x.x.x.x> <x.x.x.x/x></list> </completionHelp> </properties> - <command>vtysh -c "show ip route $4"</command> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> <leafNode name="longer-prefixes"> <properties> diff --git a/op-mode-definitions/show-ipv6-ospfv3.xml.in b/op-mode-definitions/show-ipv6-ospfv3.xml.in index e6c8a6700..a63465472 100644 --- a/op-mode-definitions/show-ipv6-ospfv3.xml.in +++ b/op-mode-definitions/show-ipv6-ospfv3.xml.in @@ -11,7 +11,7 @@ <properties> <help>Show IPv6 Open Shortest Path First (OSPF)</help> </properties> - <command>vtysh -c "show ipv6 ospf6"</command> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> <node name="area"> <properties> @@ -39,467 +39,74 @@ </tagNode> </children> </tagNode> - <node name="border-routers"> + #include <include/ospfv3/border-routers.xml.i> + #include <include/ospfv3/database.xml.i> + #include <include/ospfv3/interface.xml.i> + #include <include/ospfv3/linkstate.xml.i> + #include <include/ospfv3/neighbor.xml.i> + #include <include/ospfv3/redistribute.xml.i> + #include <include/ospfv3/route.xml.i> + <node name="vrf"> <properties> - <help>Show OSPFv3 border-router (ABR and ASBR) information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/detail.xml.i> - </children> - </node> - <tagNode name="border-routers"> - <properties> - <help>Border router ID</help> + <help>Specify the VRF</help> <completionHelp> - <list><x.x.x.x></list> + <list>all</list> + <path>vrf name</path> </completionHelp> </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </tagNode> - <node name="database"> - <properties> - <help>Show OSPFv3 Link state database information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - <tagNode name="adv-router"> - <properties> - <help>Search by Advertising Router ID</help> - <completionHelp> - <list><x.x.x.x></list> - </completionHelp> - </properties> - <children> - #include <include/ospfv3/linkstate-id.xml.i> - </children> - </tagNode> - <node name="any"> - <properties> - <help>Search by Any Link state Type</help> - </properties> - <children> - <tagNode name="any"> - <properties> - <help>Search by Link state ID</help> - <completionHelp> - <list><x.x.x.x></list> - </completionHelp> - </properties> - <children> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - </children> - </tagNode> - </children> - </node> - <tagNode name="any"> - <properties> - <help>Search by Link state ID</help> - <completionHelp> - <list><x.x.x.x></list> - </completionHelp> - </properties> - <command>vtysh -c "show ipv6 ospf6 database * $6"</command> - <children> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/adv-router-id-node-tag.xml.i> - </children> - </tagNode> - <node name="as-external"> - <properties> - <help>Show AS-External LSAs</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/adv-router.xml.i> - <tagNode name="any"> - <properties> - <help>Search by Advertising Router ID</help> - <completionHelp> - <list><x.x.x.x></list> - </completionHelp> - </properties> - <command>vtysh -c "show ipv6 ospf6 database as-external * $7"</command> - <children> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - </children> - </tagNode> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/self-originated.xml.i> - </children> - </node> - <tagNode name="as-external"> - <properties> - <help>Search by Advertising Router IDs</help> - <completionHelp> - <list><x.x.x.x></list> - </completionHelp> - </properties> - <children> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/self-originated.xml.i> - #include <include/ospfv3/adv-router-id-node-tag.xml.i> - </children> - </tagNode> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/self-originated.xml.i> - <node name="group-membership"> - <properties> - <help>Show Group-Membership LSAs</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/linkstate-id-node-tag.xml.i> - #include <include/ospfv3/self-originated.xml.i> - </children> - </node> - <node name="inter-prefix"> - <properties> - <help>Show Inter-Area-Prefix LSAs</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/linkstate-id-node-tag.xml.i> - #include <include/ospfv3/self-originated.xml.i> - </children> - </node> - <node name="inter-router"> - <properties> - <help>Show Inter-Area-Router LSAs</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/linkstate-id-node-tag.xml.i> - #include <include/ospfv3/self-originated.xml.i> - </children> - </node> - <node name="intra-prefix"> - <properties> - <help>Show Intra-Area-Prefix LSAs</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/linkstate-id-node-tag.xml.i> - #include <include/ospfv3/self-originated.xml.i> - </children> - </node> - <node name="link"> - <properties> - <help>Show Link LSAs</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/linkstate-id-node-tag.xml.i> - #include <include/ospfv3/self-originated.xml.i> - </children> - </node> - <node name="network"> - <properties> - <help>Show Network LSAs</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/linkstate-id-node-tag.xml.i> - #include <include/ospfv3/self-originated.xml.i> - </children> - </node> - <node name="node.tag"> - <properties> - <help>Show LSAs</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/linkstate-id-node-tag.xml.i> - #include <include/ospfv3/self-originated.xml.i> - </children> - </node> - <node name="router"> - <properties> - <help>Show router LSAs</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/linkstate-id-node-tag.xml.i> - #include <include/ospfv3/self-originated.xml.i> - </children> - </node> - <node name="type-7"> - <properties> - <help>Show Type-7 LSAs</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> - #include <include/ospfv3/dump.xml.i> - #include <include/ospfv3/internal.xml.i> - #include <include/ospfv3/linkstate-id.xml.i> - #include <include/ospfv3/linkstate-id-node-tag.xml.i> - #include <include/ospfv3/self-originated.xml.i> - </children> - </node> - </children> </node> - <node name="interface"> + <tagNode name="vrf"> <properties> - <help>Show OSPFv3 interface information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - <node name="prefix"> - <properties> - <help>Show connected prefixes to advertise</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/detail.xml.i> - </children> - </node> - <tagNode name="prefix"> - <properties> - <help>Show interface prefix route specific information</help> - <completionHelp> - <list><h:h:h:h:h:h:h:h> <h:h:h:h:h:h:h:h/x></list> - </completionHelp> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/detail.xml.i> - <node name="match"> - <properties> - <help>Matched interface prefix information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </node> - </children> - </tagNode> - </children> - </node> - <tagNode name="interface"> - <properties> - <help>Specific insterface to examine</help> + <help>VRF name</help> <completionHelp> - <script>${vyos_completion_dir}/list_interfaces.py</script> + <list>all</list> + <path>vrf name</path> </completionHelp> </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - <node name="prefix"> + <node name="area"> <properties> - <help>Show connected prefixes to advertise</help> + <help>Show Shortest Path First tree information</help> </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/detail.xml.i> - </children> + <command>vtysh -c "show ipv6 ospf6 vrf $5 spf tree"</command> </node> - <tagNode name="prefix"> + <tagNode name="area"> <properties> - <help>Show interface prefix route specific information</help> + <help>Area ID (as an IPv4 notation)</help> <completionHelp> - <list><h:h:h:h:h:h:h:h> <h:h:h:h:h:h:h:h/x></list> + <path>protocols ospfv3 area</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <command>vtysh -c "show ipv6 ospf6 vrf $5 area $7 spf tree"</command> <children> - #include <include/ospfv3/detail.xml.i> - <node name="match"> + <tagNode name="router"> <properties> - <help>Matched interface prefix information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </node> - </children> - </tagNode> - </children> - </tagNode> - <node name="linkstate"> - <properties> - <help>Show OSPFv3 linkstate routing information</help> - </properties> - <children> - #include <include/ospfv3/detail.xml.i> - <tagNode name="network"> - <properties> - <help>Show linkstate Network information</help> - <completionHelp> - <list><x.x.x.x></list> - </completionHelp> - </properties> - <children> - <node name="node.tag"> - <properties> - <help>Specify Link state ID as IPv4 address notation</help> + <help> Simulate view point (Router ID)</help> <completionHelp> <list><x.x.x.x></list> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </node> + <command>vtysh -c "show ipv6 ospf6 vrf $5 simulate spf-tree $9 $6 $7"</command> + </tagNode> </children> </tagNode> - <tagNode name="router"> - <properties> - <help>Show linkstate Router information</help> - <completionHelp> - <list><x.x.x.x></list> - </completionHelp> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </tagNode> - </children> - </node> - <node name="neighbor"> - <properties> - <help>Show OSPFv3 neighbor information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/detail.xml.i> - <node name="drchoice"> - <properties> - <help>Show neighbor DR choice information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </node> + #include <include/ospfv3/border-routers.xml.i> + #include <include/ospfv3/database.xml.i> + #include <include/ospfv3/interface.xml.i> + #include <include/ospfv3/linkstate.xml.i> + #include <include/ospfv3/neighbor.xml.i> + #include <include/ospfv3/redistribute.xml.i> + #include <include/ospfv3/route.xml.i> </children> - </node> - <node name="redistribute"> - <properties> - <help>Show OSPFv3 redistribute external information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </node> - <node name="route"> - <properties> - <help>Show OSPFv3 routing table information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - <node name="external-1"> - <properties> - <help>Show Type-1 External route information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/detail.xml.i> - </children> - </node> - <node name="external-2"> - <properties> - <help>Show Type-2 External route information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/detail.xml.i> - </children> - </node> - <node name="inter-area"> - <properties> - <help>Show Inter-Area route information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/detail.xml.i> - </children> - </node> - <node name="intra-area"> - <properties> - <help>Show Intra-Area route information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/detail.xml.i> - </children> - </node> - #include <include/ospfv3/detail.xml.i> - <node name="summary"> - <properties> - <help>Show route table summary</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </node> - </children> - </node> - <tagNode name="route"> + </tagNode> + <leafNode name="vrfs"> <properties> - <help>Show specified route/prefix information</help> - <completionHelp> - <list><h:h:h:h:h:h:h:h> <h:h:h:h:h:h:h:h/x></list> - </completionHelp> + <help>Show OSPFv3 VRFs</help> </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - <node name="longer"> - <properties> - <help>Show routes longer than specified prefix</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </node> - <node name="match"> - <properties> - <help>Show routes matching specified prefix</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - <children> - #include <include/ospfv3/detail.xml.i> - </children> - </node> - </children> - </tagNode> + </leafNode> </children> </node> </children> diff --git a/op-mode-definitions/show-ipv6-route.xml.in b/op-mode-definitions/show-ipv6-route.xml.in index 8624574ac..2c5024991 100644 --- a/op-mode-definitions/show-ipv6-route.xml.in +++ b/op-mode-definitions/show-ipv6-route.xml.in @@ -13,12 +13,7 @@ </properties> <command>vtysh -c "show ipv6 route"</command> <children> - <node name="bgp"> - <properties> - <help>Show IPv6 BGP routes</help> - </properties> - <command>vtysh -c "show ipv6 route bgp"</command> - </node> + #include <include/show-route-bgp.xml.i> <node name="cache"> <properties> <help>Show kernel IPv6 route cache</help> @@ -34,12 +29,7 @@ </properties> <command>ip -s -f inet6 route list cache $5</command> </tagNode> - <node name="connected"> - <properties> - <help>Show IPv6 connected routes</help> - </properties> - <command>vtysh -c "show ipv6 route connected"</command> - </node> + #include <include/show-route-connected.xml.i> <node name="forward"> <properties> <help>Show kernel IPv6 route table</help> @@ -55,71 +45,36 @@ </properties> <command>ip -s -f inet6 route list $5</command> </tagNode> - <node name="isis"> - <properties> - <help>Show IPv6 IS-IS routes</help> - </properties> - <command>vtysh -c "show ipv6 route isis"</command> - </node> - <node name="kernel"> - <properties> - <help>Show IPv6 Kernel routes</help> - </properties> - <command>vtysh -c "show ipv6 route kernel"</command> - </node> - <node name="ospfv3"> - <properties> - <help>Show IPv6 OSPF routes</help> - </properties> - <command>vtysh -c "show ipv6 route ospf6"</command> - </node> - <node name="ripng"> - <properties> - <help>Show IPv6 RIPNG routes</help> - </properties> - <command>vtysh -c "show ipv6 route ripng"</command> - </node> - <node name="static"> - <properties> - <help>Show IPv6 static routes</help> - </properties> - <command>vtysh -c "show ipv6 route static"</command> - </node> - <node name="summary"> - <properties> - <help>Show IPv6 routes summary</help> - </properties> - <command>vtysh -c "show ipv6 route summary"</command> - </node> - <node name="table"> - <properties> - <help>Show IPv6 routes in policy tables</help> - </properties> - <command>vtysh -c "show ipv6 route table all"</command> - </node> - <tagNode name="table"> - <properties> - <help>Show IPv6 routes in specific policy table</help> - <completionHelp> - <path>protocols static table</path> - </completionHelp> - </properties> - <command>vtysh -c "show ipv6 route table $5"</command> - </tagNode> - <node name="vrf"> - <properties> - <help>Show IPv6 routes in VRFs</help> - </properties> - <command>vtysh -c "show ipv6 route vrf all"</command> - </node> + #include <include/show-route-isis.xml.i> + #include <include/show-route-kernel.xml.i> + #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> <tagNode name="vrf"> <properties> - <help>Show IPv6 routes in specific VRF</help> + <help>Show IPv6 routes in VRF</help> <completionHelp> + <list>all</list> <path>vrf name</path> </completionHelp> </properties> - <command>vtysh -c "show ipv6 route vrf $5"</command> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + <children> + #include <include/show-route-bgp.xml.i> + #include <include/show-route-connected.xml.i> + #include <include/show-route-isis.xml.i> + #include <include/show-route-kernel.xml.i> + #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> + </children> </tagNode> </children> </node> diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in index 4c0a7913b..76879e5d6 100644 --- a/op-mode-definitions/show-log.xml.in +++ b/op-mode-definitions/show-log.xml.in @@ -139,6 +139,12 @@ </tagNode> </children> </node> + <leafNode name="flow-accounting"> + <properties> + <help>Show log for flow-accounting</help> + </properties> + <command>journalctl --no-hostname --boot --unit uacctd.service</command> + </leafNode> <leafNode name="https"> <properties> <help>Show log for HTTPs</help> @@ -179,9 +185,9 @@ </tagNode> <leafNode name="kernel"> <properties> - <help>Show messages in kernel ring buffer</help> + <help>Show log for Linux Kernel</help> </properties> - <command>sudo dmesg</command> + <command>journalctl --no-hostname --boot --dmesg</command> </leafNode> <leafNode name="lldp"> <properties> @@ -195,6 +201,12 @@ </properties> <command>egrep -i "kernel:.*\[NAT-[A-Z]{3,}-[0-9]+(-MASQ)?\]" $(find /var/log -maxdepth 1 -type f -name messages\* | sort -t. -k2nr)</command> </leafNode> + <leafNode name="nhrp"> + <properties> + <help>Show log for NHRP</help> + </properties> + <command>journalctl --no-hostname --boot --unit opennhrp.service</command> + </leafNode> <node name="openvpn"> <properties> <help>Show log for OpenVPN</help> @@ -212,6 +224,96 @@ </tagNode> </children> </node> + <node name="pppoe"> + <properties> + <help>Show log for PPPoE</help> + </properties> + <command>journalctl --no-hostname --boot --unit "ppp@pppoe*.service"</command> + <children> + <tagNode name="interface"> + <properties> + <help>Show PPPoE log on specific interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py -t pppoe</script> + </completionHelp> + </properties> + <command>journalctl --no-hostname --boot --unit "ppp@$6.service"</command> + </tagNode> + </children> + </node> + <node name="protocol"> + <properties> + <help>Show log for Routing Protocols</help> + </properties> + <children> + <leafNode name="ospf"> + <properties> + <help>Show log for OSPF</help> + </properties> + <command>journalctl --boot /usr/lib/frr/ospfd</command> + </leafNode> + <leafNode name="ospfv3"> + <properties> + <help>Show log for OSPF for IPv6</help> + </properties> + <command>journalctl --boot /usr/lib/frr/ospf6d</command> + </leafNode> + <leafNode name="bgp"> + <properties> + <help>Show log for BGP</help> + </properties> + <command>journalctl --boot /usr/lib/frr/bgpd</command> + </leafNode> + <leafNode name="rip"> + <properties> + <help>Show log for RIP</help> + </properties> + <command>journalctl --boot /usr/lib/frr/ripd</command> + </leafNode> + <leafNode name="ripng"> + <properties> + <help>Show log for RIPng</help> + </properties> + <command>journalctl --boot /usr/lib/frr/ripngd</command> + </leafNode> + <leafNode name="static"> + <properties> + <help>Show log for static route</help> + </properties> + <command>journalctl --boot /usr/lib/frr/staticd</command> + </leafNode> + <leafNode name="multicast"> + <properties> + <help>Show log for Multicast protocol</help> + </properties> + <command>journalctl --boot /usr/lib/frr/pimd</command> + </leafNode> + <leafNode name="isis"> + <properties> + <help>Show log for ISIS</help> + </properties> + <command>journalctl --boot /usr/lib/frr/isisd</command> + </leafNode> + <leafNode name="nhrp"> + <properties> + <help>Show log for NHRP</help> + </properties> + <command>journalctl --boot /usr/lib/frr/nhrpd</command> + </leafNode> + <leafNode name="bfd"> + <properties> + <help>Show log for BFD</help> + </properties> + <command>journalctl --boot /usr/lib/frr/bfdd</command> + </leafNode> + <leafNode name="mpls"> + <properties> + <help>Show log for MPLS</help> + </properties> + <command>journalctl --boot /usr/lib/frr/ldpd</command> + </leafNode> + </children> + </node> <leafNode name="snmp"> <properties> <help>Show log for Simple Network Monitoring Protocol (SNMP)</help> diff --git a/op-mode-definitions/show-netns.xml.in b/op-mode-definitions/show-netns.xml.in new file mode 100644 index 000000000..8d5072d4e --- /dev/null +++ b/op-mode-definitions/show-netns.xml.in @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="show"> + <children> + <node name="netns"> + <properties> + <help>Show network namespace information</help> + </properties> + <command>ip netns ls</command> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/show-protocols.xml.in b/op-mode-definitions/show-protocols.xml.in index d595e2c3c..698001b76 100644 --- a/op-mode-definitions/show-protocols.xml.in +++ b/op-mode-definitions/show-protocols.xml.in @@ -7,50 +7,6 @@ <help>Show protocol specific information</help> </properties> <children> - <node name="bfd"> - <properties> - <help>Show Bidirectional Forwarding Detection (BFD)</help> - </properties> - <children> - <node name="peer"> - <properties> - <help>Show all Bidirectional Forwarding Detection (BFD) peer status</help> - </properties> - <command>vtysh -c "show bfd peers"</command> - <children> - <leafNode name="counters"> - <properties> - <help>Show Bidirectional Forwarding Detection (BFD) peer counters</help> - </properties> - <command>vtysh -c "show bfd peers counters"</command> - </leafNode> - </children> - </node> - <tagNode name="peer"> - <properties> - <help>Show Bidirectional Forwarding Detection (BFD) peer status</help> - <completionHelp> - <script>vtysh -c "show bfd peers" | awk '/[:blank:]*peer/ { printf "%s\n", $2 }'</script> - </completionHelp> - </properties> - <command>vtysh -c "show bfd peers" | awk -v BFD_PEER=$5 'BEGIN { regex = sprintf("(peer %s.*)vrf", BFD_PEER) } { if (match($0, regex, bfd_peer_value)) peer=bfd_peer_value[1] } END { if (peer) system("vtysh -c \"show bfd " peer "\"") }'</command> - <children> - <leafNode name="counters"> - <properties> - <help>Show Bidirectional Forwarding Detection (BFD) peer counters</help> - </properties> - <command>vtysh -c "show bfd peers" | awk -v BFD_PEER=$5 'BEGIN { regex = sprintf("(peer %s.*)vrf", BFD_PEER) } { if (match($0, regex, bfd_peer_value)) peer=bfd_peer_value[1] } END { if (peer) system("vtysh -c \"show bfd " peer " counters\"") }'</command> - </leafNode> - </children> - </tagNode> - <leafNode name="peers"> - <properties> - <help>Show Bidirectional Forwarding Detection (BFD) peers brief</help> - </properties> - <command>vtysh -c "show bfd peers brief"</command> - </leafNode> - </children> - </node> <node name="static"> <properties> <help>Show static protocol parameters</help> diff --git a/op-mode-definitions/show-system.xml.in b/op-mode-definitions/show-system.xml.in index 0f852164e..68b473bc1 100644 --- a/op-mode-definitions/show-system.xml.in +++ b/op-mode-definitions/show-system.xml.in @@ -166,9 +166,9 @@ </leafNode> <leafNode name="uptime"> <properties> - <help>Show how long the system has been up</help> + <help>Show system uptime and load averages</help> </properties> - <command>uptime</command> + <command>${vyos_op_scripts_dir}/show_uptime.py</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-virtual-server.xml.in b/op-mode-definitions/show-virtual-server.xml.in new file mode 100644 index 000000000..5dbd3c759 --- /dev/null +++ b/op-mode-definitions/show-virtual-server.xml.in @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interfaceDefinition> + <node name="show"> + <children> + <node name="virtual-server"> + <properties> + <help>Show virtual server information</help> + </properties> + <command>${vyos_op_scripts_dir}/show_virtual_server.py</command> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/traceroute.xml.in b/op-mode-definitions/traceroute.xml.in index e3217235c..aba0f45e3 100644 --- a/op-mode-definitions/traceroute.xml.in +++ b/op-mode-definitions/traceroute.xml.in @@ -2,226 +2,22 @@ <interfaceDefinition> <tagNode name="traceroute"> <properties> - <help>Track network path to node</help> - <completionHelp> - <list><hostname> <x.x.x.x> <h:h:h:h:h:h:h:h></list> - </completionHelp> - </properties> - <command>/usr/bin/traceroute "$2"</command> - </tagNode> - <node name="traceroute"> - <properties> - <help>Track network path to node</help> + <help>Trace network path to node</help> <completionHelp> <list><hostname> <x.x.x.x> <h:h:h:h:h:h:h:h></list> </completionHelp> </properties> + <command>${vyos_op_scripts_dir}/traceroute.py ${@:2}</command> <children> - <tagNode name="ipv4"> + <leafNode name="node.tag"> <properties> - <help>Explicitly use IPv4 when tracing the path</help> + <help>Traceroute options</help> <completionHelp> - <list><hostname> <x.x.x.x></list> + <script>${vyos_op_scripts_dir}/traceroute.py --get-options "${COMP_WORDS[@]}"</script> </completionHelp> </properties> - <command>/usr/bin/traceroute -4 "$3"</command> - <children> - <node name="tcp"> - <properties> - <help>Route tracing and port detection using TCP</help> - </properties> - <command>sudo /usr/bin/tcptraceroute "$3" </command> - <children> - <tagNode name="port"> - <properties> - <help>TCP port to connect to for path tracing</help> - <completionHelp> - <list>0-65535</list> - </completionHelp> - </properties> - <command>sudo /usr/bin/tcptraceroute "$3" $6</command> - </tagNode> - </children> - </node> - </children> - </tagNode> - <tagNode name="ipv6"> - <properties> - <help>Explicitly use IPv6 when tracing the path</help> - <completionHelp> - <list><hostname> <h:h:h:h:h:h:h:h></list> - </completionHelp> - </properties> - <command>/usr/bin/traceroute -6 "$3"</command> - <children> - <node name="tcp"> - <properties> - <help>Use TCP/IPv6 packets to perform a traceroute</help> - </properties> - <command>sudo /usr/bin/tcptraceroute6 "$3" </command> - <children> - <tagNode name="port"> - <properties> - <help>TCP port to connect to for path tracing</help> - <completionHelp> - <list>0-65535</list> - </completionHelp> - </properties> - <command>sudo /usr/bin/tcptraceroute6 "$3" $6</command> - </tagNode> - </children> - </node> - </children> - </tagNode> - <tagNode name="vrf"> - <properties> - <help>Track network path to specified node via given VRF</help> - <completionHelp> - <path>vrf name</path> - </completionHelp> - </properties> - <children> - <!-- we need an empty tagNode to pass in a plain fqdn/ip address and - let traceroute decide how to handle this parameter --> - <tagNode name=""> - <properties> - <help>Track network path to specified node via given VRF</help> - <completionHelp> - <list><hostname> <x.x.x.x> <h:h:h:h:h:h:h:h></list> - </completionHelp> - </properties> - <command>sudo ip vrf exec "$3" /usr/bin/traceroute "$4"</command> - </tagNode> - <tagNode name="ipv4"> - <properties> - <help>Explicitly use IPv4 when tracing the path via given VRF</help> - <completionHelp> - <list><hostname> <x.x.x.x></list> - </completionHelp> - </properties> - <command>sudo ip vrf exec "$3" /usr/bin/traceroute -4 "$5"</command> - <children> - <node name="tcp"> - <properties> - <help>Route tracing and port detection using TCP</help> - </properties> - <command>sudo ip vrf exec "$3" /usr/bin/tcptraceroute "$5" </command> - <children> - <tagNode name="port"> - <properties> - <help>TCP port to connect to for path tracing</help> - <completionHelp> - <list>0-65535</list> - </completionHelp> - </properties> - <command>sudo ip vrf exec "$3" /usr/bin/tcptraceroute "$5" $8</command> - </tagNode> - </children> - </node> - </children> - </tagNode> - <tagNode name="ipv6"> - <properties> - <help>Explicitly use IPv6 when tracing the path via given VRF</help> - <completionHelp> - <list><hostname> <h:h:h:h:h:h:h:h></list> - </completionHelp> - </properties> - <command>sudo ip vrf exec "$3" /usr/bin/traceroute -6 "$5"</command> - <children> - <node name="tcp"> - <properties> - <help>Use TCP/IPv6 packets to perform a traceroute</help> - </properties> - <command>sudo ip vrf exec "$3" /usr/bin/tcptraceroute6 "$5" </command> - <children> - <tagNode name="port"> - <properties> - <help>TCP port to connect to for path tracing</help> - <completionHelp> - <list>0-65535</list> - </completionHelp> - </properties> - <command>sudo ip vrf exec "$3" /usr/bin/tcptraceroute6 "$5" $8</command> - </tagNode> - </children> - </node> - </children> - </tagNode> - </children> - </tagNode> - </children> - </node> - <node name="monitor"> - <children> - <tagNode name="traceroute"> - <properties> - <help>Monitor path to destination in realtime</help> - <completionHelp> - <list><hostname> <x.x.x.x> <h:h:h:h:h:h:h:h></list> - </completionHelp> - </properties> - <command>/usr/bin/mtr "$3"</command> - </tagNode> - <node name="traceroute"> - <children> - <tagNode name="ipv4"> - <properties> - <help>IPv4 fully qualified domain name (FQDN)</help> - <completionHelp> - <list><fqdn></list> - </completionHelp> - </properties> - <command>/usr/bin/mtr -4 "$4"</command> - </tagNode> - <tagNode name="ipv6"> - <properties> - <help>IPv6 fully qualified domain name (FQDN)</help> - <completionHelp> - <list><fqdn></list> - </completionHelp> - </properties> - <command>/usr/bin/mtr -6 "$4"</command> - </tagNode> - <tagNode name="vrf"> - <properties> - <help>Monitor path to destination in realtime via given VRF</help> - <completionHelp> - <path>vrf name</path> - </completionHelp> - </properties> - <children> - <tagNode name="ipv4"> - <properties> - <help>IPv4 fully qualified domain name (FQDN)</help> - <completionHelp> - <list><fqdn></list> - </completionHelp> - </properties> - <command>sudo ip vrf exec "$4" /usr/bin/mtr -4 "$6"</command> - </tagNode> - <tagNode name="ipv6"> - <properties> - <help>IPv6 fully qualified domain name (FQDN)</help> - <completionHelp> - <list><fqdn></list> - </completionHelp> - </properties> - <command>sudo ip vrf exec "$4" /usr/bin/mtr -6 "$6"</command> - </tagNode> - <tagNode name=""> - <properties> - <help>Track network path to specified node via given VRF</help> - <completionHelp> - <list><hostname> <x.x.x.x> <h:h:h:h:h:h:h:h></list> - </completionHelp> - </properties> - <command>sudo ip vrf exec "$4" /usr/bin/mtr "$5"</command> - </tagNode> - </children> - </tagNode> - </children> - </node> + <command>${vyos_op_scripts_dir}/traceroute.py ${@:2}</command> + </leafNode> </children> - </node> + </tagNode> </interfaceDefinition> diff --git a/op-mode-definitions/zone-policy.xml.in b/op-mode-definitions/zone-policy.xml.in new file mode 100644 index 000000000..c4b02bcee --- /dev/null +++ b/op-mode-definitions/zone-policy.xml.in @@ -0,0 +1,24 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="show"> + <children> + <node name="zone-policy"> + <properties> + <help>Show zone policy information</help> + </properties> + <children> + <tagNode name="zone"> + <properties> + <help>Show summary of zone policy for a specific zone</help> + <completionHelp> + <path>zone-policy zone</path> + </completionHelp> + </properties> + <command>sudo ${vyos_op_scripts_dir}/zone_policy.py --action show --name $4</command> + </tagNode> + </children> + <command>sudo ${vyos_op_scripts_dir}/zone_policy.py --action show</command> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/python/vyos/base.py b/python/vyos/base.py index 4e23714e5..78067d5b2 100644 --- a/python/vyos/base.py +++ b/python/vyos/base.py @@ -1,4 +1,4 @@ -# Copyright 2018 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2018-2022 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 @@ -13,6 +13,23 @@ # 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/>. +from textwrap import fill + +class Warning(): + def __init__(self, message): + # Reformat the message and trim it to 72 characters in length + message = fill(message, width=72) + print(f'\nWARNING: {message}') + +class DeprecationWarning(): + def __init__(self, message): + # Reformat the message and trim it to 72 characters in length + message = fill(message, width=72) + print(f'\nDEPRECATION WARNING: {message}\n') class ConfigError(Exception): - pass + def __init__(self, message): + # Reformat the message and trim it to 72 characters in length + message = fill(message, width=72) + # Call the base class constructor with the parameters it needs + super().__init__(message) diff --git a/python/vyos/config.py b/python/vyos/config.py index a5c1ad122..287fd2ed1 100644 --- a/python/vyos/config.py +++ b/python/vyos/config.py @@ -142,31 +142,41 @@ class Config(object): def exists(self, path): """ - Checks if a node with given path exists in the running or proposed config + Checks if a node or value with given path exists in the proposed config. + + Args: + path (str): Configuration tree path Returns: - True if node exists, False otherwise + True if node or value exists in the proposed config, False otherwise Note: - This function cannot be used outside a configuration sessions. + This function should not be used outside of configuration sessions. In operational mode scripts, use ``exists_effective``. """ - if not self._session_config: + if self._session_config is None: return False + + # Assume the path is a node path first if self._session_config.exists(self._make_path(path)): return True else: + # If that check fails, it may mean the path has a value at the end. # libvyosconfig exists() works only for _nodes_, not _values_ - # libvyattacfg one also worked for values, so we emulate that case here + # libvyattacfg also worked for values, so we emulate that case here if isinstance(path, str): path = re.split(r'\s+', path) path_without_value = path[:-1] - path_str = " ".join(path_without_value) try: - value = self._session_config.return_value(self._make_path(path_str)) - return (value == path[-1]) + # return_values() is safe to use with single-value nodes, + # it simply returns a single-item list in that case. + values = self._session_config.return_values(self._make_path(path_without_value)) + + # If we got this far, the node does exist and has values, + # so we need to check if it has the value in question among its values. + return (path[-1] in values) except vyos.configtree.ConfigTreeError: - # node doesn't exist at all + # Even the parent node doesn't exist at all return False def session_changed(self): @@ -380,7 +390,7 @@ class Config(object): def exists_effective(self, path): """ - Check if a node exists in the running (effective) config + Checks if a node or value exists in the running (effective) config. Args: path (str): Configuration tree path @@ -392,10 +402,31 @@ class Config(object): This function is safe to use in operational mode. In configuration mode, it ignores uncommited changes. """ - if self._running_config: - return(self._running_config.exists(self._make_path(path))) + if self._running_config is None: + return False + + # Assume the path is a node path first + if self._running_config.exists(self._make_path(path)): + return True + else: + # If that check fails, it may mean the path has a value at the end. + # libvyosconfig exists() works only for _nodes_, not _values_ + # libvyattacfg also worked for values, so we emulate that case here + if isinstance(path, str): + path = re.split(r'\s+', path) + path_without_value = path[:-1] + try: + # return_values() is safe to use with single-value nodes, + # it simply returns a single-item list in that case. + values = self._running_config.return_values(self._make_path(path_without_value)) + + # If we got this far, the node does exist and has values, + # so we need to check if it has the value in question among its values. + return (path[-1] in values) + except vyos.configtree.ConfigTreeError: + # Even the parent node doesn't exist at all + return False - return False def return_effective_value(self, path, default=None): """ diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index 425a2e416..04ddc10e9 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -1,4 +1,4 @@ -# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2022 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 @@ -104,6 +104,11 @@ def list_diff(first, second): second = set(second) return [item for item in first if item not in second] +def is_node_changed(conf, path): + from vyos.configdiff import get_config_diff + D = get_config_diff(conf, key_mangling=('-', '_')) + return D.is_node_changed(path) + def leaf_node_changed(conf, path): """ Check if a leaf node was altered. If it has been altered - values has been @@ -114,9 +119,14 @@ def leaf_node_changed(conf, path): """ from vyos.configdiff import get_config_diff D = get_config_diff(conf, key_mangling=('-', '_')) - D.set_level(conf.get_level()) (new, old) = D.get_value_diff(path) if new != old: + if isinstance(old, dict): + # valueLess nodes return {} if node is deleted + return True + if old is None and isinstance(new, dict): + # valueLess nodes return {} if node was added + return True if old is None: return [] if isinstance(old, str): @@ -130,7 +140,7 @@ def leaf_node_changed(conf, path): return None -def node_changed(conf, path, key_mangling=None): +def node_changed(conf, path, key_mangling=None, recursive=False): """ Check if a leaf node was altered. If it has been altered - values has been changed, or it was added/removed, we will return the old value. If nothing @@ -138,12 +148,11 @@ def node_changed(conf, path, key_mangling=None): """ from vyos.configdiff import get_config_diff, Diff D = get_config_diff(conf, key_mangling) - D.set_level(conf.get_level()) # get_child_nodes() will return dict_keys(), mangle this into a list with PEP448 - keys = D.get_child_nodes_diff(path, expand_nodes=Diff.DELETE)['delete'].keys() + keys = D.get_child_nodes_diff(path, expand_nodes=Diff.DELETE, recursive=recursive)['delete'].keys() return list(keys) -def get_removed_vlans(conf, dict): +def get_removed_vlans(conf, path, dict): """ Common function to parse a dictionary retrieved via get_config_dict() and determine any added/removed VLAN interfaces - be it 802.1q or Q-in-Q. @@ -153,16 +162,17 @@ def get_removed_vlans(conf, dict): # Check vif, vif-s/vif-c VLAN interfaces for removal D = get_config_diff(conf, key_mangling=('-', '_')) D.set_level(conf.get_level()) + # get_child_nodes() will return dict_keys(), mangle this into a list with PEP448 - keys = D.get_child_nodes_diff(['vif'], expand_nodes=Diff.DELETE)['delete'].keys() + keys = D.get_child_nodes_diff(path + ['vif'], expand_nodes=Diff.DELETE)['delete'].keys() if keys: dict['vif_remove'] = [*keys] # get_child_nodes() will return dict_keys(), mangle this into a list with PEP448 - keys = D.get_child_nodes_diff(['vif-s'], expand_nodes=Diff.DELETE)['delete'].keys() + keys = D.get_child_nodes_diff(path + ['vif-s'], expand_nodes=Diff.DELETE)['delete'].keys() if keys: dict['vif_s_remove'] = [*keys] for vif in dict.get('vif_s', {}).keys(): - keys = D.get_child_nodes_diff(['vif-s', vif, 'vif-c'], expand_nodes=Diff.DELETE)['delete'].keys() + keys = D.get_child_nodes_diff(path + ['vif-s', vif, 'vif-c'], expand_nodes=Diff.DELETE)['delete'].keys() if keys: dict['vif_s'][vif]['vif_c_remove'] = [*keys] return dict @@ -196,7 +206,7 @@ def is_member(conf, interface, intftype=None): interface name -> Interface is a member of this interface False -> interface type cannot have members """ - ret_val = None + ret_val = {} intftypes = ['bonding', 'bridge'] if intftype not in intftypes + [None]: @@ -206,20 +216,15 @@ def is_member(conf, interface, intftype=None): intftype = intftypes if intftype == None else [intftype] - # set config level to root - old_level = conf.get_level() - conf.set_level([]) - for iftype in intftype: base = ['interfaces', iftype] for intf in conf.list_nodes(base): member = base + [intf, 'member', 'interface', interface] if conf.exists(member): tmp = conf.get_config_dict(member, key_mangling=('-', '_'), - get_first_key=True) - ret_val = {intf : tmp} + get_first_key=True, no_tag_node_value_mangle=True) + ret_val.update({intf : tmp}) - old_level = conf.set_level(old_level) return ret_val def is_mirror_intf(conf, interface, direction=None): @@ -241,8 +246,6 @@ def is_mirror_intf(conf, interface, direction=None): direction = directions if direction == None else [direction] ret_val = None - old_level = conf.get_level() - conf.set_level([]) base = ['interfaces'] for dir in direction: @@ -256,7 +259,6 @@ def is_mirror_intf(conf, interface, direction=None): get_first_key=True) ret_val = {intf : tmp} - old_level = conf.set_level(old_level) return ret_val def has_vlan_subinterface_configured(conf, intf): @@ -270,15 +272,11 @@ def has_vlan_subinterface_configured(conf, intf): from vyos.ifconfig import Section ret = False - old_level = conf.get_level() - conf.set_level([]) - intfpath = ['interfaces', Section.section(intf), intf] if ( conf.exists(intfpath + ['vif']) or conf.exists(intfpath + ['vif-s'])): ret = True - conf.set_level(old_level) return ret def is_source_interface(conf, interface, intftype=None): @@ -300,11 +298,6 @@ def is_source_interface(conf, interface, intftype=None): 'have a source-interface') intftype = intftypes if intftype == None else [intftype] - - # set config level to root - old_level = conf.get_level() - conf.set_level([]) - for it in intftype: base = ['interfaces', it] for intf in conf.list_nodes(base): @@ -313,43 +306,77 @@ def is_source_interface(conf, interface, intftype=None): ret_val = intf break - old_level = conf.set_level(old_level) return ret_val def get_dhcp_interfaces(conf, vrf=None): """ Common helper functions to retrieve all interfaces from current CLI sessions that have DHCP configured. """ - dhcp_interfaces = [] + dhcp_interfaces = {} dict = conf.get_config_dict(['interfaces'], get_first_key=True) if not dict: return dhcp_interfaces - def check_dhcp(config, ifname): - out = [] + def check_dhcp(config): + ifname = config['ifname'] + tmp = {} if 'address' in config and 'dhcp' in config['address']: + options = {} + if dict_search('dhcp_options.default_route_distance', config) != None: + options.update({'dhcp_options' : config['dhcp_options']}) if 'vrf' in config: - if vrf is config['vrf']: out.append(ifname) - else: out.append(ifname) - return out + if vrf is config['vrf']: tmp.update({ifname : options}) + else: tmp.update({ifname : options}) + + return tmp for section, interface in dict.items(): - for ifname, ifconfig in interface.items(): - tmp = check_dhcp(ifconfig, ifname) - dhcp_interfaces.extend(tmp) + for ifname in interface: + # always reset config level, as get_interface_dict() will alter it + conf.set_level([]) + # we already have a dict representation of the config from get_config_dict(), + # but with the extended information from get_interface_dict() we also + # get the DHCP client default-route-distance default option if not specified. + _, ifconfig = get_interface_dict(conf, ['interfaces', section], ifname) + + tmp = check_dhcp(ifconfig) + dhcp_interfaces.update(tmp) # check per VLAN interfaces for vif, vif_config in ifconfig.get('vif', {}).items(): - tmp = check_dhcp(vif_config, f'{ifname}.{vif}') - dhcp_interfaces.extend(tmp) + tmp = check_dhcp(vif_config) + dhcp_interfaces.update(tmp) # check QinQ VLAN interfaces - for vif_s, vif_s_config in ifconfig.get('vif-s', {}).items(): - tmp = check_dhcp(vif_s_config, f'{ifname}.{vif_s}') - dhcp_interfaces.extend(tmp) - for vif_c, vif_c_config in vif_s_config.get('vif-c', {}).items(): - tmp = check_dhcp(vif_c_config, f'{ifname}.{vif_s}.{vif_c}') - dhcp_interfaces.extend(tmp) + for vif_s, vif_s_config in ifconfig.get('vif_s', {}).items(): + tmp = check_dhcp(vif_s_config) + dhcp_interfaces.update(tmp) + for vif_c, vif_c_config in vif_s_config.get('vif_c', {}).items(): + tmp = check_dhcp(vif_c_config) + dhcp_interfaces.update(tmp) return dhcp_interfaces +def get_pppoe_interfaces(conf, vrf=None): + """ Common helper functions to retrieve all interfaces from current CLI + sessions that have DHCP configured. """ + pppoe_interfaces = {} + for ifname in conf.list_nodes(['interfaces', 'pppoe']): + # always reset config level, as get_interface_dict() will alter it + conf.set_level([]) + # we already have a dict representation of the config from get_config_dict(), + # but with the extended information from get_interface_dict() we also + # get the DHCP client default-route-distance default option if not specified. + ifconfig = get_interface_dict(conf, ['interfaces', 'pppoe'], ifname) + + options = {} + if 'default_route_distance' in ifconfig: + options.update({'default_route_distance' : ifconfig['default_route_distance']}) + if 'no_default_route' in ifconfig: + options.update({'no_default_route' : {}}) + if 'vrf' in ifconfig: + if vrf is ifconfig['vrf']: pppoe_interfaces.update({ifname : options}) + else: pppoe_interfaces.update({ifname : options}) + + return pppoe_interfaces + def get_interface_dict(config, base, ifname=''): """ Common utility function to retrieve and mangle the interfaces configuration @@ -359,7 +386,6 @@ def get_interface_dict(config, base, ifname=''): Return a dictionary with the necessary interface config keys. """ - if not ifname: from vyos import ConfigError # determine tagNode instance @@ -376,9 +402,8 @@ def get_interface_dict(config, base, ifname=''): for vif in ['vif', 'vif_s']: if vif in default_values: del default_values[vif] - # setup config level which is extracted in get_removed_vlans() - config.set_level(base + [ifname]) - dict = config.get_config_dict([], key_mangling=('-', '_'), get_first_key=True, + dict = config.get_config_dict(base + [ifname], key_mangling=('-', '_'), + get_first_key=True, no_tag_node_value_mangle=True) # Check if interface has been removed. We must use exists() as @@ -386,8 +411,8 @@ def get_interface_dict(config, base, ifname=''): # node like the following exists. # +macsec macsec1 { # +} - if not config.exists([]): - dict.update({'deleted' : ''}) + if not config.exists(base + [ifname]): + dict.update({'deleted' : {}}) # Add interface instance name into dictionary dict.update({'ifname': ifname}) @@ -405,10 +430,16 @@ def get_interface_dict(config, base, ifname=''): if 'deleted' not in dict: dict = dict_merge(default_values, dict) + # If interface does not request an IPv4 DHCP address there is no need + # to keep the dhcp-options key + if 'address' not in dict or 'dhcp' not in dict['address']: + if 'dhcp_options' in dict: + del dict['dhcp_options'] + # XXX: T2665: blend in proper DHCPv6-PD default values dict = T2665_set_dhcpv6pd_defaults(dict) - address = leaf_node_changed(config, ['address']) + address = leaf_node_changed(config, base + [ifname, 'address']) if address: dict.update({'address_old' : address}) # Check if we are a member of a bridge device @@ -423,6 +454,10 @@ def get_interface_dict(config, base, ifname=''): bond = is_member(config, ifname, 'bonding') if bond: dict.update({'is_bond_member' : bond}) + # Check if any DHCP options changed which require a client restat + dhcp = node_changed(config, ['dhcp-options'], recursive=True) + if dhcp: dict.update({'dhcp_options_changed' : ''}) + # Some interfaces come with a source_interface which must also not be part # of any other bond or bridge interface as it is exclusivly assigned as the # Kernels "lower" interface to this new "virtual/upper" interface. @@ -435,10 +470,10 @@ def get_interface_dict(config, base, ifname=''): tmp = is_member(config, dict['source_interface'], 'bonding') if tmp: dict.update({'source_interface_is_bond_member' : tmp}) - mac = leaf_node_changed(config, ['mac']) + mac = leaf_node_changed(config, base + [ifname, 'mac']) if mac: dict.update({'mac_old' : mac}) - eui64 = leaf_node_changed(config, ['ipv6', 'address', 'eui64']) + eui64 = leaf_node_changed(config, base + [ifname, 'ipv6', 'address', 'eui64']) if eui64: tmp = dict_search('ipv6.address', dict) if not tmp: @@ -450,6 +485,9 @@ def get_interface_dict(config, base, ifname=''): # identical for all types of VLAN interfaces as they all include the same # XML definitions which hold the defaults. for vif, vif_config in dict.get('vif', {}).items(): + # Add subinterface name to dictionary + dict['vif'][vif].update({'ifname' : f'{ifname}.{vif}'}) + default_vif_values = defaults(base + ['vif']) # XXX: T2665: When there is no DHCPv6-PD configuration given, we can safely # remove the default values from the dict. @@ -459,15 +497,31 @@ def get_interface_dict(config, base, ifname=''): # Only add defaults if interface is not about to be deleted - this is # to keep a cleaner config dict. if 'deleted' not in dict: - dict['vif'][vif] = dict_merge(default_vif_values, vif_config) + address = leaf_node_changed(config, base + [ifname, 'vif', vif, 'address']) + if address: dict['vif'][vif].update({'address_old' : address}) + + dict['vif'][vif] = dict_merge(default_vif_values, dict['vif'][vif]) # XXX: T2665: blend in proper DHCPv6-PD default values dict['vif'][vif] = T2665_set_dhcpv6pd_defaults(dict['vif'][vif]) + # If interface does not request an IPv4 DHCP address there is no need + # to keep the dhcp-options key + if 'address' not in dict['vif'][vif] or 'dhcp' not in dict['vif'][vif]['address']: + if 'dhcp_options' in dict['vif'][vif]: + del dict['vif'][vif]['dhcp_options'] + # Check if we are a member of a bridge device bridge = is_member(config, f'{ifname}.{vif}', 'bridge') if bridge: dict['vif'][vif].update({'is_bridge_member' : bridge}) + # Check if any DHCP options changed which require a client restat + dhcp = node_changed(config, ['vif', vif, 'dhcp-options'], recursive=True) + if dhcp: dict['vif'][vif].update({'dhcp_options_changed' : ''}) + for vif_s, vif_s_config in dict.get('vif_s', {}).items(): + # Add subinterface name to dictionary + dict['vif_s'][vif_s].update({'ifname' : f'{ifname}.{vif_s}'}) + default_vif_s_values = defaults(base + ['vif-s']) # XXX: T2665: we only wan't the vif-s defaults - do not care about vif-c if 'vif_c' in default_vif_s_values: del default_vif_s_values['vif_c'] @@ -480,15 +534,33 @@ def get_interface_dict(config, base, ifname=''): # Only add defaults if interface is not about to be deleted - this is # to keep a cleaner config dict. if 'deleted' not in dict: - dict['vif_s'][vif_s] = dict_merge(default_vif_s_values, vif_s_config) + address = leaf_node_changed(config, base + [ifname, 'vif-s', vif_s, 'address']) + if address: dict['vif_s'][vif_s].update({'address_old' : address}) + + dict['vif_s'][vif_s] = dict_merge(default_vif_s_values, + dict['vif_s'][vif_s]) # XXX: T2665: blend in proper DHCPv6-PD default values dict['vif_s'][vif_s] = T2665_set_dhcpv6pd_defaults(dict['vif_s'][vif_s]) + # If interface does not request an IPv4 DHCP address there is no need + # to keep the dhcp-options key + if 'address' not in dict['vif_s'][vif_s] or 'dhcp' not in \ + dict['vif_s'][vif_s]['address']: + if 'dhcp_options' in dict['vif_s'][vif_s]: + del dict['vif_s'][vif_s]['dhcp_options'] + # Check if we are a member of a bridge device bridge = is_member(config, f'{ifname}.{vif_s}', 'bridge') if bridge: dict['vif_s'][vif_s].update({'is_bridge_member' : bridge}) + # Check if any DHCP options changed which require a client restat + dhcp = node_changed(config, ['vif-s', vif_s, 'dhcp-options'], recursive=True) + if dhcp: dict['vif_s'][vif_s].update({'dhcp_options_changed' : ''}) + for vif_c, vif_c_config in vif_s_config.get('vif_c', {}).items(): + # Add subinterface name to dictionary + dict['vif_s'][vif_s]['vif_c'][vif_c].update({'ifname' : f'{ifname}.{vif_s}.{vif_c}'}) + default_vif_c_values = defaults(base + ['vif-s', 'vif-c']) # XXX: T2665: When there is no DHCPv6-PD configuration given, we can safely @@ -499,20 +571,35 @@ def get_interface_dict(config, base, ifname=''): # Only add defaults if interface is not about to be deleted - this is # to keep a cleaner config dict. if 'deleted' not in dict: + address = leaf_node_changed(config, base + [ifname, 'vif-s', vif_s, 'vif-c', vif_c, 'address']) + if address: dict['vif_s'][vif_s]['vif_c'][vif_c].update( + {'address_old' : address}) + dict['vif_s'][vif_s]['vif_c'][vif_c] = dict_merge( - default_vif_c_values, vif_c_config) + default_vif_c_values, dict['vif_s'][vif_s]['vif_c'][vif_c]) # XXX: T2665: blend in proper DHCPv6-PD default values dict['vif_s'][vif_s]['vif_c'][vif_c] = T2665_set_dhcpv6pd_defaults( dict['vif_s'][vif_s]['vif_c'][vif_c]) + # If interface does not request an IPv4 DHCP address there is no need + # to keep the dhcp-options key + if 'address' not in dict['vif_s'][vif_s]['vif_c'][vif_c] or 'dhcp' \ + not in dict['vif_s'][vif_s]['vif_c'][vif_c]['address']: + if 'dhcp_options' in dict['vif_s'][vif_s]['vif_c'][vif_c]: + del dict['vif_s'][vif_s]['vif_c'][vif_c]['dhcp_options'] + # Check if we are a member of a bridge device bridge = is_member(config, f'{ifname}.{vif_s}.{vif_c}', 'bridge') if bridge: dict['vif_s'][vif_s]['vif_c'][vif_c].update( {'is_bridge_member' : bridge}) + # Check if any DHCP options changed which require a client restat + dhcp = node_changed(config, ['vif-s', vif_s, 'vif-c', vif_c, 'dhcp-options'], recursive=True) + if dhcp: dict['vif_s'][vif_s]['vif_c'][vif_c].update({'dhcp_options_changed' : ''}) + # Check vif, vif-s/vif-c VLAN interfaces for removal - dict = get_removed_vlans(config, dict) - return dict + dict = get_removed_vlans(config, base + [ifname], dict) + return ifname, dict def get_vlan_ids(interface): """ @@ -534,7 +621,6 @@ def get_vlan_ids(interface): return vlan_ids - def get_accel_dict(config, base, chap_secrets): """ Common utility function to retrieve and mangle the Accel-PPP configuration diff --git a/python/vyos/configdiff.py b/python/vyos/configdiff.py index 0e41fbe27..9185575df 100644 --- a/python/vyos/configdiff.py +++ b/python/vyos/configdiff.py @@ -16,8 +16,11 @@ from enum import IntFlag, auto from vyos.config import Config +from vyos.configtree import DiffTree from vyos.configdict import dict_merge +from vyos.configdict import list_diff from vyos.util import get_sub_dict, mangle_dict_keys +from vyos.util import dict_search_args from vyos.xml import defaults class ConfigDiffError(Exception): @@ -36,6 +39,8 @@ class Diff(IntFlag): ADD = auto() STABLE = auto() +ALL = Diff.MERGE | Diff.DELETE | Diff.ADD | Diff.STABLE + requires_effective = [enum_to_key(Diff.DELETE)] target_defaults = [enum_to_key(Diff.MERGE)] @@ -73,19 +78,24 @@ def get_config_diff(config, key_mangling=None): isinstance(key_mangling[1], str)): raise ValueError("key_mangling must be a tuple of two strings") - return ConfigDiff(config, key_mangling) + diff_t = DiffTree(config._running_config, config._session_config) + + return ConfigDiff(config, key_mangling, diff_tree=diff_t) 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): + def __init__(self, config, key_mangling=None, diff_tree=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 {} + # mirrored from Config; allow path arguments relative to level def _make_path(self, path): if isinstance(path, str): @@ -134,7 +144,45 @@ class ConfigDiff(object): self._key_mangling[1]) return config_dict - def get_child_nodes_diff(self, path=[], expand_nodes=Diff(0), no_defaults=False): + def is_node_changed(self, path=[]): + if self._diff_tree is None: + raise NotImplementedError("diff_tree class not available") + + if (self._diff_tree.add.exists(self._make_path(path)) or + self._diff_tree.sub.exists(self._make_path(path))): + return True + return False + + def get_child_nodes_diff_str(self, path=[]): + ret = {'add': {}, 'change': {}, 'delete': {}} + + diff = self.get_child_nodes_diff(path, + expand_nodes=Diff.ADD | Diff.DELETE | Diff.MERGE | Diff.STABLE, + no_defaults=True) + + def parse_dict(diff_dict, diff_type, prefix=[]): + for k, v in diff_dict.items(): + if isinstance(v, dict): + parse_dict(v, diff_type, prefix + [k]) + else: + path_str = ' '.join(prefix + [k]) + if diff_type == 'add' or diff_type == 'delete': + if isinstance(v, list): + v = ', '.join(v) + ret[diff_type][path_str] = v + elif diff_type == 'merge': + old_value = dict_search_args(diff['stable'], *prefix, k) + if old_value and old_value != v: + ret['change'][path_str] = [old_value, v] + + parse_dict(diff['merge'], 'merge') + parse_dict(diff['add'], 'add') + parse_dict(diff['delete'], 'delete') + + return ret + + def get_child_nodes_diff(self, path=[], expand_nodes=Diff(0), no_defaults=False, + recursive=False): """ Args: path (str|list): config path @@ -144,6 +192,8 @@ class ConfigDiff(object): value no_detaults=False: if expand_nodes & Diff.MERGE, do not merge default values to ret['merge'] + recursive: if true, use config_tree diff algorithm provided by + diff_tree class Returns: dict of lists, representing differences between session and effective config, under path @@ -154,6 +204,34 @@ class ConfigDiff(object): """ session_dict = get_sub_dict(self._session_config_dict, self._make_path(path), get_first_key=True) + + if recursive: + 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) + ret = {} + ret[enum_to_key(Diff.MERGE)] = session_dict + ret[enum_to_key(Diff.DELETE)] = get_sub_dict(sub, self._make_path(path), + get_first_key=True) + ret[enum_to_key(Diff.ADD)] = get_sub_dict(add, self._make_path(path), + get_first_key=True) + ret[enum_to_key(Diff.STABLE)] = get_sub_dict(inter, self._make_path(path), + get_first_key=True) + for e in Diff: + k = enum_to_key(e) + if not (e & expand_nodes): + ret[k] = list(ret[k]) + else: + if self._key_mangling: + ret[k] = self._mangle_dict_keys(ret[k]) + if k in target_defaults and not no_defaults: + default_values = defaults(self._make_path(path)) + ret[k] = dict_merge(default_values, ret[k]) + return ret + effective_dict = get_sub_dict(self._effective_config_dict, self._make_path(path), get_first_key=True) @@ -179,7 +257,8 @@ class ConfigDiff(object): return ret - def get_node_diff(self, path=[], expand_nodes=Diff(0), no_defaults=False): + def get_node_diff(self, path=[], expand_nodes=Diff(0), no_defaults=False, + recursive=False): """ Args: path (str|list): config path @@ -189,6 +268,8 @@ class ConfigDiff(object): value no_detaults=False: if expand_nodes & Diff.MERGE, do not merge default values to ret['merge'] + recursive: if true, use config_tree diff algorithm provided by + diff_tree class Returns: dict of lists, representing differences between session and effective config, at path @@ -198,6 +279,31 @@ class ConfigDiff(object): dict['stable'] = config values in both session and effective """ session_dict = get_sub_dict(self._session_config_dict, self._make_path(path)) + + if recursive: + 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) + ret = {} + ret[enum_to_key(Diff.MERGE)] = session_dict + ret[enum_to_key(Diff.DELETE)] = get_sub_dict(sub, self._make_path(path)) + ret[enum_to_key(Diff.ADD)] = get_sub_dict(add, self._make_path(path)) + ret[enum_to_key(Diff.STABLE)] = get_sub_dict(inter, self._make_path(path)) + for e in Diff: + k = enum_to_key(e) + if not (e & expand_nodes): + ret[k] = list(ret[k]) + else: + if self._key_mangling: + ret[k] = self._mangle_dict_keys(ret[k]) + if k in target_defaults and not no_defaults: + default_values = defaults(self._make_path(path)) + ret[k] = dict_merge(default_values, ret[k]) + return ret + effective_dict = get_sub_dict(self._effective_config_dict, self._make_path(path)) ret = _key_sets_from_dicts(session_dict, effective_dict) diff --git a/python/vyos/configquery.py b/python/vyos/configquery.py index 1cdcbcf39..5b097b312 100644 --- a/python/vyos/configquery.py +++ b/python/vyos/configquery.py @@ -18,16 +18,15 @@ A small library that allows querying existence or value(s) of config settings from op mode, and execution of arbitrary op mode commands. ''' -import re -import json -from copy import deepcopy +import os from subprocess import STDOUT -import vyos.util -import vyos.xml +from vyos.util import popen, boot_configuration_complete from vyos.config import Config -from vyos.configtree import ConfigTree -from vyos.configsource import ConfigSourceSession +from vyos.configsource import ConfigSourceSession, ConfigSourceString +from vyos.defaults import directories + +config_file = os.path.join(directories['config'], 'config.boot') class ConfigQueryError(Exception): pass @@ -58,21 +57,21 @@ class CliShellApiConfigQuery(GenericConfigQuery): def exists(self, path: list): cmd = ' '.join(path) - (_, err) = vyos.util.popen(f'cli-shell-api existsActive {cmd}') + (_, err) = popen(f'cli-shell-api existsActive {cmd}') if err: return False return True def value(self, path: list): cmd = ' '.join(path) - (out, err) = vyos.util.popen(f'cli-shell-api returnActiveValue {cmd}') + (out, err) = popen(f'cli-shell-api returnActiveValue {cmd}') if err: raise ConfigQueryError('No value for given path') return out def values(self, path: list): cmd = ' '.join(path) - (out, err) = vyos.util.popen(f'cli-shell-api returnActiveValues {cmd}') + (out, err) = popen(f'cli-shell-api returnActiveValues {cmd}') if err: raise ConfigQueryError('No values for given path') return out @@ -81,25 +80,36 @@ class ConfigTreeQuery(GenericConfigQuery): def __init__(self): super().__init__() - config_source = ConfigSourceSession() - self.configtree = Config(config_source=config_source) + if boot_configuration_complete(): + config_source = ConfigSourceSession() + self.config = Config(config_source=config_source) + else: + try: + with open(config_file) as f: + config_string = f.read() + except OSError as err: + raise ConfigQueryError('No config file available') from err + + config_source = ConfigSourceString(running_config_text=config_string, + session_config_text=config_string) + self.config = Config(config_source=config_source) def exists(self, path: list): - return self.configtree.exists(path) + return self.config.exists(path) def value(self, path: list): - return self.configtree.return_value(path) + return self.config.return_value(path) def values(self, path: list): - return self.configtree.return_values(path) + return self.config.return_values(path) def list_nodes(self, path: list): - return self.configtree.list_nodes(path) + return self.config.list_nodes(path) def get_config_dict(self, path=[], effective=False, key_mangling=None, get_first_key=False, no_multi_convert=False, no_tag_node_value_mangle=False): - return self.configtree.get_config_dict(path, effective=effective, + return self.config.get_config_dict(path, effective=effective, key_mangling=key_mangling, get_first_key=get_first_key, no_multi_convert=no_multi_convert, no_tag_node_value_mangle=no_tag_node_value_mangle) @@ -110,7 +120,7 @@ class VbashOpRun(GenericOpRun): def run(self, path: list, **kwargs): cmd = ' '.join(path) - (out, err) = vyos.util.popen(f'. /opt/vyatta/share/vyatta-op/functions/interpreter/vyatta-op-run; _vyatta_op_run {cmd}', stderr=STDOUT, **kwargs) + (out, err) = popen(f'/opt/vyatta/bin/vyatta-op-cmd-wrapper {cmd}', stderr=STDOUT, **kwargs) if err: raise ConfigQueryError(out) return out diff --git a/python/vyos/configsource.py b/python/vyos/configsource.py index b0981d25e..510b5b65a 100644 --- a/python/vyos/configsource.py +++ b/python/vyos/configsource.py @@ -19,6 +19,7 @@ import re import subprocess from vyos.configtree import ConfigTree +from vyos.util import boot_configuration_complete class VyOSError(Exception): """ @@ -117,7 +118,7 @@ class ConfigSourceSession(ConfigSource): # Running config can be obtained either from op or conf mode, it always succeeds # once the config system is initialized during boot; # before initialization, set to empty string - if os.path.isfile('/tmp/vyos-config-status'): + if boot_configuration_complete(): try: running_config_text = self._run([self._cli_shell_api, '--show-active-only', '--show-show-defaults', '--show-ignore-edit', 'showConfig']) except VyOSError: @@ -161,7 +162,7 @@ class ConfigSourceSession(ConfigSource): if p.returncode != 0: raise VyOSError() else: - return out.decode('ascii', 'ignore') + return out.decode() def set_level(self, path): """ diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py index d8ffaca99..e9cdb69e4 100644 --- a/python/vyos/configtree.py +++ b/python/vyos/configtree.py @@ -17,6 +17,7 @@ import json from ctypes import cdll, c_char_p, c_void_p, c_int +LIBPATH = '/usr/lib/libvyosconfig.so.0' def escape_backslash(string: str) -> str: """Escape single backslashes in string that are not in escape sequence""" @@ -42,7 +43,9 @@ class ConfigTreeError(Exception): class ConfigTree(object): - def __init__(self, config_string, libpath='/usr/lib/libvyosconfig.so.0'): + def __init__(self, config_string=None, address=None, libpath=LIBPATH): + if config_string is None and address is None: + raise TypeError("ConfigTree() requires one of 'config_string' or 'address'") self.__config = None self.__lib = cdll.LoadLibrary(libpath) @@ -60,7 +63,7 @@ class ConfigTree(object): self.__to_string.restype = c_char_p self.__to_commands = self.__lib.to_commands - self.__to_commands.argtypes = [c_void_p] + self.__to_commands.argtypes = [c_void_p, c_char_p] self.__to_commands.restype = c_char_p self.__to_json = self.__lib.to_json @@ -123,18 +126,26 @@ class ConfigTree(object): self.__set_tag.argtypes = [c_void_p, c_char_p] self.__set_tag.restype = c_int + self.__get_subtree = self.__lib.get_subtree + self.__get_subtree.argtypes = [c_void_p, c_char_p] + self.__get_subtree.restype = c_void_p + self.__destroy = self.__lib.destroy self.__destroy.argtypes = [c_void_p] - config_section, version_section = extract_version(config_string) - config_section = escape_backslash(config_section) - config = self.__from_string(config_section.encode()) - if config is None: - msg = self.__get_error().decode() - raise ValueError("Failed to parse config: {0}".format(msg)) + if address is None: + config_section, version_section = extract_version(config_string) + config_section = escape_backslash(config_section) + config = self.__from_string(config_section.encode()) + if config is None: + msg = self.__get_error().decode() + raise ValueError("Failed to parse config: {0}".format(msg)) + else: + self.__config = config + self.__version = version_section else: - self.__config = config - self.__version = version_section + self.__config = address + self.__version = '' def __del__(self): if self.__config is not None: @@ -143,13 +154,16 @@ class ConfigTree(object): def __str__(self): return self.to_string() + def _get_config(self): + return self.__config + def to_string(self): config_string = self.__to_string(self.__config).decode() config_string = "{0}\n{1}".format(config_string, self.__version) return config_string - def to_commands(self): - return self.__to_commands(self.__config).decode() + def to_commands(self, op="set"): + return self.__to_commands(self.__config, op.encode()).decode() def to_json(self): return self.__to_json(self.__config).decode() @@ -281,3 +295,61 @@ class ConfigTree(object): else: raise ConfigTreeError("Path [{}] doesn't exist".format(path_str)) + def get_subtree(self, path, with_node=False): + check_path(path) + path_str = " ".join(map(str, path)).encode() + + res = self.__get_subtree(self.__config, path_str, with_node) + subt = ConfigTree(address=res) + return subt + +class DiffTree: + def __init__(self, left, right, path=[], libpath=LIBPATH): + if left is None: + left = ConfigTree(config_string='\n') + if right is None: + right = ConfigTree(config_string='\n') + if not (isinstance(left, ConfigTree) and isinstance(right, ConfigTree)): + raise TypeError("Arguments must be instances of ConfigTree") + if path: + if not left.exists(path): + raise ConfigTreeError(f"Path {path} doesn't exist in lhs tree") + if not right.exists(path): + raise ConfigTreeError(f"Path {path} doesn't exist in rhs tree") + + self.left = left + self.right = right + + self.__lib = cdll.LoadLibrary(libpath) + + self.__diff_tree = self.__lib.diff_tree + self.__diff_tree.argtypes = [c_char_p, c_void_p, c_void_p] + self.__diff_tree.restype = c_void_p + + self.__trim_tree = self.__lib.trim_tree + self.__trim_tree.argtypes = [c_void_p, c_void_p] + self.__trim_tree.restype = c_void_p + + check_path(path) + path_str = " ".join(map(str, path)).encode() + + res = self.__diff_tree(path_str, left._get_config(), right._get_config()) + + # full diff config_tree and python dict representation + self.full = ConfigTree(address=res) + self.dict = json.loads(self.full.to_json()) + + # config_tree sub-trees + self.add = self.full.get_subtree(['add']) + self.sub = self.full.get_subtree(['sub']) + self.inter = self.full.get_subtree(['inter']) + + # trim sub(-tract) tree to get delete tree for commands + ref = self.right.get_subtree(path, with_node=True) if path else self.right + res = self.__trim_tree(self.sub._get_config(), ref._get_config()) + self.delete = ConfigTree(address=res) + + def to_commands(self): + add = self.add.to_commands() + delete = self.delete.to_commands(op="delete") + return delete + "\n" + add diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index 365a28feb..438485d98 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -1,4 +1,4 @@ -# Copyright 2020-2021 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2020-2022 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 @@ -173,24 +173,43 @@ def verify_eapol(config): if ca_cert_name not in config['pki']['ca']: raise ConfigError('Invalid CA certificate specified for EAPoL') - ca_cert = config['pki']['ca'][cert_name] + ca_cert = config['pki']['ca'][ca_cert_name] if 'certificate' not in ca_cert: raise ConfigError('Invalid CA certificate specified for EAPoL') -def verify_mirror(config): +def verify_mirror_redirect(config): """ Common helper function used by interface implementations to perform - recurring validation of mirror interface configuration. + recurring validation of mirror and redirect interface configuration via tc(8) It makes no sense to mirror traffic back at yourself! """ + import os + if {'mirror', 'redirect'} <= set(config): + raise ConfigError('Mirror and redirect can not be enabled at the same time!') + if 'mirror' in config: for direction, mirror_interface in config['mirror'].items(): + if not os.path.exists(f'/sys/class/net/{mirror_interface}'): + raise ConfigError(f'Requested mirror interface "{mirror_interface}" '\ + 'does not exist!') + if mirror_interface == config['ifname']: - raise ConfigError(f'Can not mirror "{direction}" traffic back ' \ + raise ConfigError(f'Can not mirror "{direction}" traffic back '\ 'the originating interface!') + if 'redirect' in config: + redirect_ifname = config['redirect'] + if not os.path.exists(f'/sys/class/net/{redirect_ifname}'): + raise ConfigError(f'Requested redirect interface "{redirect_ifname}" '\ + 'does not exist!') + + if ('mirror' in config or 'redirect' in config) and dict_search('traffic_policy.in', config) is not None: + # XXX: support combination of limiting and redirect/mirror - this is an + # artificial limitation + raise ConfigError('Can not use ingress policy together with mirror or redirect!') + def verify_authentication(config): """ Common helper function used by interface implementations to perform @@ -224,9 +243,10 @@ def verify_bridge_delete(config): when interface also is part of a bridge. """ if 'is_bridge_member' in config: - raise ConfigError( - 'Interface "{ifname}" cannot be deleted as it is a ' - 'member of bridge "{is_bridge_member}"!'.format(**config)) + interface = config['ifname'] + for bridge in config['is_bridge_member']: + raise ConfigError(f'Interface "{interface}" cannot be deleted as it ' + f'is a member of bridge "{bridge}"!') def verify_interface_exists(ifname): """ @@ -308,27 +328,37 @@ def verify_vlan_config(config): if duplicate: raise ConfigError(f'Duplicate VLAN id "{duplicate[0]}" used for vif and vif-s interfaces!') + parent_ifname = config['ifname'] # 802.1q VLANs - for vlan in config.get('vif', {}): - vlan = config['vif'][vlan] + for vlan_id in config.get('vif', {}): + vlan = config['vif'][vlan_id] + vlan['ifname'] = f'{parent_ifname}.{vlan_id}' + verify_dhcpv6(vlan) verify_address(vlan) verify_vrf(vlan) + verify_mirror_redirect(vlan) verify_mtu_parent(vlan, config) # 802.1ad (Q-in-Q) VLANs - for s_vlan in config.get('vif_s', {}): - s_vlan = config['vif_s'][s_vlan] + for s_vlan_id in config.get('vif_s', {}): + s_vlan = config['vif_s'][s_vlan_id] + s_vlan['ifname'] = f'{parent_ifname}.{s_vlan_id}' + verify_dhcpv6(s_vlan) verify_address(s_vlan) verify_vrf(s_vlan) + verify_mirror_redirect(s_vlan) verify_mtu_parent(s_vlan, config) - for c_vlan in s_vlan.get('vif_c', {}): - c_vlan = s_vlan['vif_c'][c_vlan] + for c_vlan_id in s_vlan.get('vif_c', {}): + c_vlan = s_vlan['vif_c'][c_vlan_id] + c_vlan['ifname'] = f'{parent_ifname}.{s_vlan_id}.{c_vlan_id}' + verify_dhcpv6(c_vlan) verify_address(c_vlan) verify_vrf(c_vlan) + verify_mirror_redirect(c_vlan) verify_mtu_parent(c_vlan, config) verify_mtu_parent(c_vlan, s_vlan) diff --git a/python/vyos/cpu.py b/python/vyos/cpu.py new file mode 100644 index 000000000..a0ef864be --- /dev/null +++ b/python/vyos/cpu.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +# Copyright 2022 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# 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/>. + +""" +Retrieves (or at least attempts to retrieve) the total number of real CPU cores +installed in a Linux system. + +The issue of core count is complicated by existence of SMT, e.g. Intel's Hyper Threading. +GNU nproc returns the number of LOGICAL cores, +which is 2x of the real cores if SMT is enabled. + +The idea is to find all physical CPUs and add up their core counts. +It has special cases for x86_64 and MAY work correctly on other architectures, +but nothing is certain. +""" + +import re + + +def _read_cpuinfo(): + with open('/proc/cpuinfo', 'r') as f: + return f.readlines() + +def _split_line(l): + l = l.strip() + parts = re.split(r'\s*:\s*', l) + return (parts[0], ":".join(parts[1:])) + +def _find_cpus(cpuinfo_lines): + # Make a dict because it's more convenient to work with later, + # when we need to find physicall distinct CPUs there. + cpus = {} + + cpu_number = 0 + + for l in cpuinfo_lines: + key, value = _split_line(l) + if key == 'processor': + cpu_number = value + cpus[cpu_number] = {} + else: + cpus[cpu_number][key] = value + + return cpus + +def _find_physical_cpus(): + cpus = _find_cpus(_read_cpuinfo()) + + phys_cpus = {} + + for num in cpus: + if 'physical id' in cpus[num]: + # On at least some architectures, CPUs in different sockets + # have different 'physical id' field, e.g. on x86_64. + phys_id = cpus[num]['physical id'] + if phys_id not in phys_cpus: + phys_cpus[phys_id] = cpus[num] + else: + # On other architectures, e.g. on ARM, there's no such field. + # We just assume they are different CPUs, + # whether single core ones or cores of physical CPUs. + phys_cpus[num] = cpu[num] + + return phys_cpus + +def get_cpus(): + """ Returns a list of /proc/cpuinfo entries that belong to different CPUs. + """ + cpus_dict = _find_physical_cpus() + return list(cpus_dict.values()) + +def get_core_count(): + """ Returns the total number of physical CPU cores + (even if Hyper-Threading or another SMT is enabled and has inflated + the number of cores in /proc/cpuinfo) + """ + physical_cpus = _find_physical_cpus() + + core_count = 0 + + for num in physical_cpus: + # Some architectures, e.g. x86_64, include a field for core count. + # Since we found unique physical CPU entries, we can sum their core counts. + if 'cpu cores' in physical_cpus[num]: + core_count += int(physical_cpus[num]['cpu cores']) + else: + core_count += 1 + + return core_count diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py index 00b14a985..fcb6a7fbc 100644 --- a/python/vyos/defaults.py +++ b/python/vyos/defaults.py @@ -29,6 +29,8 @@ directories = { "vyos_udev_dir": "/run/udev/vyos" } +config_status = '/tmp/vyos-config-status' + cfg_group = 'vyattacfg' cfg_vintage = 'vyos' @@ -44,8 +46,10 @@ https_data = { api_data = { 'listen_address' : '127.0.0.1', 'port' : '8080', - 'strict' : 'false', - 'debug' : 'false', + 'socket' : False, + 'strict' : False, + 'gql' : False, + 'debug' : False, 'api_keys' : [ {"id": "testapp", "key": "qwerty"} ] } diff --git a/python/vyos/ethtool.py b/python/vyos/ethtool.py index e45b0f041..2b6012a73 100644 --- a/python/vyos/ethtool.py +++ b/python/vyos/ethtool.py @@ -1,4 +1,4 @@ -# Copyright 2021 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2021-2022 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 @@ -18,6 +18,11 @@ import re from vyos.util import popen +# These drivers do not support using ethtool to change the speed, duplex, or +# flow control settings +_drivers_without_speed_duplex_flow = ['vmxnet3', 'virtio_net', 'xen_netfront', + 'iavf', 'ice', 'i40e', 'hv_netvsc'] + class Ethtool: """ Class is used to retrive and cache information about an ethernet adapter @@ -41,7 +46,7 @@ class Ethtool: # '100' : {'full': '', 'half': ''}, # '1000': {'full': ''} # } - _speed_duplex = { } + _speed_duplex = {'auto': {'auto': ''}} _ring_buffers = { } _ring_buffers_max = { } _driver_name = None @@ -188,7 +193,7 @@ class Ethtool: if duplex not in ['auto', 'full', 'half']: raise ValueError(f'Value "{duplex}" for duplex is invalid!') - if self.get_driver_name() in ['vmxnet3', 'virtio_net', 'xen_netfront']: + if self.get_driver_name() in _drivers_without_speed_duplex_flow: return False if speed in self._speed_duplex: @@ -198,7 +203,7 @@ class Ethtool: def check_flow_control(self): """ Check if the NIC supports flow-control """ - if self.get_driver_name() in ['vmxnet3', 'virtio_net', 'xen_netfront']: + if self.get_driver_name() in _drivers_without_speed_duplex_flow: return False return self._flow_control diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py new file mode 100644 index 000000000..04fd44173 --- /dev/null +++ b/python/vyos/firewall.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 re + +from vyos.util import cmd +from vyos.util import dict_search_args + +def find_nftables_rule(table, chain, rule_matches=[]): + # Find rule in table/chain that matches all criteria and return the handle + results = cmd(f'sudo nft -a list chain {table} {chain}').split("\n") + for line in results: + if all(rule_match in line for rule_match in rule_matches): + handle_search = re.search('handle (\d+)', line) + if handle_search: + return handle_search[1] + return None + +def remove_nftables_rule(table, chain, handle): + cmd(f'sudo nft delete rule {table} {chain} handle {handle}') + +# Functions below used by template generation + +def nft_action(vyos_action): + if vyos_action == 'accept': + return 'return' + return vyos_action + +def parse_rule(rule_conf, fw_name, rule_id, ip_name): + output = [] + def_suffix = '6' if ip_name == 'ip6' else '' + + if 'state' in rule_conf and rule_conf['state']: + states = ",".join([s for s, v in rule_conf['state'].items() if v == 'enable']) + + if states: + output.append(f'ct state {{{states}}}') + + if 'connection_status' in rule_conf and rule_conf['connection_status']: + status = rule_conf['connection_status'] + if status['nat'] == 'destination': + nat_status = '{dnat}' + output.append(f'ct status {nat_status}') + if status['nat'] == 'source': + nat_status = '{snat}' + output.append(f'ct status {nat_status}') + + if 'protocol' in rule_conf and rule_conf['protocol'] != 'all': + proto = rule_conf['protocol'] + operator = '' + if proto[0] == '!': + operator = '!=' + proto = proto[1:] + if proto == 'tcp_udp': + proto = '{tcp, udp}' + output.append(f'meta l4proto {operator} {proto}') + + for side in ['destination', 'source']: + if side in rule_conf: + prefix = side[0] + side_conf = rule_conf[side] + + if 'address' in side_conf: + suffix = side_conf['address'] + if suffix[0] == '!': + suffix = f'!= {suffix[1:]}' + output.append(f'{ip_name} {prefix}addr {suffix}') + + if 'mac_address' in side_conf: + suffix = side_conf["mac_address"] + if suffix[0] == '!': + suffix = f'!= {suffix[1:]}' + output.append(f'ether {prefix}addr {suffix}') + + if 'port' in side_conf: + proto = rule_conf['protocol'] + port = side_conf['port'].split(',') + + ports = [] + negated_ports = [] + + for p in port: + if p[0] == '!': + negated_ports.append(p[1:]) + else: + ports.append(p) + + if proto == 'tcp_udp': + proto = 'th' + + if ports: + ports_str = ','.join(ports) + output.append(f'{proto} {prefix}port {{{ports_str}}}') + + if negated_ports: + negated_ports_str = ','.join(negated_ports) + output.append(f'{proto} {prefix}port != {{{negated_ports_str}}}') + + if 'group' in side_conf: + group = side_conf['group'] + if 'address_group' in group: + group_name = group['address_group'] + operator = '' + if group_name[0] == '!': + operator = '!=' + group_name = group_name[1:] + output.append(f'{ip_name} {prefix}addr {operator} $A{def_suffix}_{group_name}') + elif 'network_group' in group: + group_name = group['network_group'] + operator = '' + if group_name[0] == '!': + operator = '!=' + group_name = group_name[1:] + output.append(f'{ip_name} {prefix}addr {operator} $N{def_suffix}_{group_name}') + if 'mac_group' in group: + group_name = group['mac_group'] + operator = '' + if group_name[0] == '!': + operator = '!=' + group_name = group_name[1:] + output.append(f'ether {prefix}addr {operator} $M_{group_name}') + if 'port_group' in group: + proto = rule_conf['protocol'] + group_name = group['port_group'] + + if proto == 'tcp_udp': + proto = 'th' + + operator = '' + if group_name[0] == '!': + operator = '!=' + group_name = group_name[1:] + + output.append(f'{proto} {prefix}port {operator} $P_{group_name}') + + if 'log' in rule_conf and rule_conf['log'] == 'enable': + action = rule_conf['action'] if 'action' in rule_conf else 'accept' + output.append(f'log prefix "[{fw_name[:19]}-{rule_id}-{action[:1].upper()}] "') + + if 'hop_limit' in rule_conf: + operators = {'eq': '==', 'gt': '>', 'lt': '<'} + for op, operator in operators.items(): + if op in rule_conf['hop_limit']: + value = rule_conf['hop_limit'][op] + output.append(f'ip6 hoplimit {operator} {value}') + + for icmp in ['icmp', 'icmpv6']: + if icmp in rule_conf: + if 'type_name' in rule_conf[icmp]: + output.append(icmp + ' type ' + rule_conf[icmp]['type_name']) + else: + if 'code' in rule_conf[icmp]: + output.append(icmp + ' code ' + rule_conf[icmp]['code']) + if 'type' in rule_conf[icmp]: + output.append(icmp + ' type ' + rule_conf[icmp]['type']) + + if 'ipsec' in rule_conf: + if 'match_ipsec' in rule_conf['ipsec']: + output.append('meta ipsec == 1') + if 'match_non_ipsec' in rule_conf['ipsec']: + output.append('meta ipsec == 0') + + if 'fragment' in rule_conf: + # Checking for fragmentation after priority -400 is not possible, + # so we use a priority -450 hook to set a mark + if 'match_frag' in rule_conf['fragment']: + output.append('meta mark 0xffff1') + if 'match_non_frag' in rule_conf['fragment']: + output.append('meta mark != 0xffff1') + + if 'limit' in rule_conf: + if 'rate' in rule_conf['limit']: + output.append(f'limit rate {rule_conf["limit"]["rate"]}') + if 'burst' in rule_conf['limit']: + output.append(f'burst {rule_conf["limit"]["burst"]} packets') + + if 'recent' in rule_conf: + count = rule_conf['recent']['count'] + time = rule_conf['recent']['time'] + output.append(f'add @RECENT{def_suffix}_{fw_name}_{rule_id} {{ {ip_name} saddr limit rate over {count}/{time} burst {count} packets }}') + + if 'time' in rule_conf: + output.append(parse_time(rule_conf['time'])) + + tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags') + if tcp_flags: + output.append(parse_tcp_flags(tcp_flags)) + + output.append('counter') + + if 'set' in rule_conf: + output.append(parse_policy_set(rule_conf['set'], def_suffix)) + + if 'action' in rule_conf: + output.append(nft_action(rule_conf['action'])) + else: + output.append('return') + + output.append(f'comment "{fw_name}-{rule_id}"') + return " ".join(output) + +def parse_tcp_flags(flags): + include = [flag for flag in flags if flag != 'not'] + exclude = list(flags['not']) if 'not' in flags else [] + return f'tcp flags & ({"|".join(include + exclude)}) == {"|".join(include) if include else "0x0"}' + +def parse_time(time): + out = [] + if 'startdate' in time: + start = time['startdate'] + if 'T' not in start and 'starttime' in time: + start += f' {time["starttime"]}' + out.append(f'time >= "{start}"') + if 'starttime' in time and 'startdate' not in time: + out.append(f'hour >= "{time["starttime"]}"') + if 'stopdate' in time: + stop = time['stopdate'] + if 'T' not in stop and 'stoptime' in time: + stop += f' {time["stoptime"]}' + out.append(f'time < "{stop}"') + if 'stoptime' in time and 'stopdate' not in time: + out.append(f'hour < "{time["stoptime"]}"') + if 'weekdays' in time: + days = time['weekdays'].split(",") + out_days = [f'"{day}"' for day in days if day[0] != '!'] + out.append(f'day {{{",".join(out_days)}}}') + return " ".join(out) + +def parse_policy_set(set_conf, def_suffix): + out = [] + if 'dscp' in set_conf: + dscp = set_conf['dscp'] + out.append(f'ip{def_suffix} dscp set {dscp}') + if 'mark' in set_conf: + mark = set_conf['mark'] + out.append(f'meta mark set {mark}') + if 'table' in set_conf: + table = set_conf['table'] + if table == 'main': + table = '254' + mark = 0x7FFFFFFF - int(table) + out.append(f'meta mark set {mark}') + if 'tcp_mss' in set_conf: + mss = set_conf['tcp_mss'] + out.append(f'tcp option maxseg size set {mss}') + return " ".join(out) diff --git a/python/vyos/frr.py b/python/vyos/frr.py index df6849472..cbba19ab7 100644 --- a/python/vyos/frr.py +++ b/python/vyos/frr.py @@ -73,23 +73,25 @@ from vyos.util import cmd import logging from logging.handlers import SysLogHandler import os +import sys + LOG = logging.getLogger(__name__) +DEBUG = False -DEBUG = os.path.exists('/tmp/vyos.frr.debug') -if DEBUG: - LOG.setLevel(logging.DEBUG) - ch = SysLogHandler(address='/dev/log') - ch2 = logging.StreamHandler() - LOG.addHandler(ch) - LOG.addHandler(ch2) +ch = SysLogHandler(address='/dev/log') +ch2 = logging.StreamHandler(stream=sys.stdout) +LOG.addHandler(ch) +LOG.addHandler(ch2) _frr_daemons = ['zebra', 'bgpd', 'fabricd', 'isisd', 'ospf6d', 'ospfd', 'pbrd', - 'pimd', 'ripd', 'ripngd', 'sharpd', 'staticd', 'vrrpd', 'ldpd'] + 'pimd', 'ripd', 'ripngd', 'sharpd', 'staticd', 'vrrpd', 'ldpd', + 'bfdd'] path_vtysh = '/usr/bin/vtysh' path_frr_reload = '/usr/lib/frr/frr-reload.py' path_config = '/run/frr' +default_add_before = r'(ip prefix-list .*|route-map .*|line vty|end)' class FrrError(Exception): pass @@ -119,6 +121,12 @@ class ConfigSectionNotFound(FrrError): """ pass +def init_debugging(): + global DEBUG + + DEBUG = os.path.exists('/tmp/vyos.frr.debug') + if DEBUG: + LOG.setLevel(logging.DEBUG) def get_configuration(daemon=None, marked=False): """ Get current running FRR configuration @@ -214,13 +222,8 @@ def reload_configuration(config, daemon=None): def save_configuration(): - """Save FRR configuration to /run/frr/config/frr.conf - It save configuration on each commit. T3217 - """ - - cmd(f'{path_vtysh} -n -w') - - return + """ T3217: Save FRR configuration to /run/frr/config/frr.conf """ + return cmd(f'{path_vtysh} -n -w') def execute(command): @@ -427,6 +430,8 @@ class FRRConfig: Using this overwrites the current loaded config objects and replaces the original loaded config ''' + init_debugging() + self.imported_config = get_configuration(daemon=daemon) if daemon: LOG.debug(f'load_configuration: Configuration loaded from FRR daemon {daemon}') @@ -448,16 +453,37 @@ class FRRConfig: mark_configuration('\n'.join(self.config)) def commit_configuration(self, daemon=None): - '''Commit the current configuration to FRR - daemon: str with name of the FRR daemon to commit to or - None to use the consolidated config + ''' + Commit the current configuration to FRR daemon: str with name of the + FRR daemon to commit to or None to use the consolidated config. + + Configuration is automatically saved after apply ''' LOG.debug('commit_configuration: Commiting configuration') for i, e in enumerate(self.config): LOG.debug(f'commit_configuration: new_config {i:3} {e}') - reload_configuration('\n'.join(self.config), daemon=daemon) - def modify_section(self, start_pattern, replacement=[], stop_pattern=r'\S+', remove_stop_mark=False, count=0): + # https://github.com/FRRouting/frr/issues/10132 + # https://github.com/FRRouting/frr/issues/10133 + count = 0 + count_max = 5 + while count < count_max: + count += 1 + try: + reload_configuration('\n'.join(self.config), daemon=daemon) + break + except: + # we just need to re-try the commit of the configuration + # for the listed FRR issues above + pass + if count >= count_max: + raise ConfigurationNotValid(f'Config commit retry counter ({count_max}) exceeded') + + # Save configuration to /run/frr/config/frr.conf + save_configuration() + + + def modify_section(self, start_pattern, replacement='!', stop_pattern=r'\S+', remove_stop_mark=False, count=0): if isinstance(replacement, str): replacement = replacement.split('\n') elif not isinstance(replacement, list): diff --git a/python/vyos/hostsd_client.py b/python/vyos/hostsd_client.py index 303b6ea47..f31ef51cf 100644 --- a/python/vyos/hostsd_client.py +++ b/python/vyos/hostsd_client.py @@ -79,6 +79,18 @@ class Client(object): msg = {'type': 'forward_zones', 'op': 'get'} return self._communicate(msg) + def add_authoritative_zones(self, data): + msg = {'type': 'authoritative_zones', 'op': 'add', 'data': data} + self._communicate(msg) + + def delete_authoritative_zones(self, data): + msg = {'type': 'authoritative_zones', 'op': 'delete', 'data': data} + self._communicate(msg) + + def get_authoritative_zones(self): + msg = {'type': 'authoritative_zones', 'op': 'get'} + return self._communicate(msg) + def add_search_domains(self, data): msg = {'type': 'search_domains', 'op': 'add', 'data': data} self._communicate(msg) diff --git a/python/vyos/ifconfig/__init__.py b/python/vyos/ifconfig/__init__.py index 2d3e406ac..a37615c8f 100644 --- a/python/vyos/ifconfig/__init__.py +++ b/python/vyos/ifconfig/__init__.py @@ -26,6 +26,7 @@ from vyos.ifconfig.ethernet import EthernetIf from vyos.ifconfig.geneve import GeneveIf from vyos.ifconfig.loopback import LoopbackIf from vyos.ifconfig.macvlan import MACVLANIf +from vyos.ifconfig.input import InputIf from vyos.ifconfig.vxlan import VXLANIf from vyos.ifconfig.wireguard import WireGuardIf from vyos.ifconfig.vtun import VTunIf diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py index 27073b266..ffd9c590f 100644 --- a/python/vyos/ifconfig/bridge.py +++ b/python/vyos/ifconfig/bridge.py @@ -298,7 +298,6 @@ class BridgeIf(Interface): tmp = dict_search('member.interface', config) if tmp: - for interface, interface_config in tmp.items(): # if interface does yet not exist bail out early and # add it later @@ -316,10 +315,13 @@ class BridgeIf(Interface): # enslave interface port to bridge self.add_port(interface) - # always set private-vlan/port isolation - tmp = dict_search('isolated', interface_config) - value = 'on' if (tmp != None) else 'off' - lower.set_port_isolation(value) + if not interface.startswith('wlan'): + # always set private-vlan/port isolation - this can not be + # done when lower link is a wifi link, as it will trigger: + # RTNETLINK answers: Operation not supported + tmp = dict_search('isolated', interface_config) + value = 'on' if (tmp != None) else 'off' + lower.set_port_isolation(value) # set bridge port path cost if 'cost' in interface_config: diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 9d54dc78e..1280fc238 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -170,11 +170,18 @@ class EthernetIf(Interface): return cmd = f'ethtool --change {ifname}' - if speed == 'auto' or duplex == 'auto': - cmd += ' autoneg on' - else: - cmd += f' speed {speed} duplex {duplex} autoneg off' - return self._cmd(cmd) + try: + if speed == 'auto' or duplex == 'auto': + cmd += ' autoneg on' + else: + cmd += f' speed {speed} duplex {duplex} autoneg off' + return self._cmd(cmd) + except PermissionError: + # Some NICs do not tell that they don't suppport settings speed/duplex, + # but they do not actually support it either. + # In that case it's probably better to ignore the error + # than end up with a broken config. + print('Warning: could not set speed/duplex settings: operation not permitted!') def set_gro(self, state): """ diff --git a/python/vyos/ifconfig/geneve.py b/python/vyos/ifconfig/geneve.py index 7cb3968df..276c34cd7 100644 --- a/python/vyos/ifconfig/geneve.py +++ b/python/vyos/ifconfig/geneve.py @@ -42,7 +42,7 @@ class GeneveIf(Interface): # arguments used by iproute2. For more information please refer to: # - https://man7.org/linux/man-pages/man8/ip-link.8.html mapping = { - 'parameters.ip.dont_fragment': 'df set', + 'parameters.ip.df' : 'df', 'parameters.ip.tos' : 'tos', 'parameters.ip.ttl' : 'ttl', 'parameters.ipv6.flowlabel' : 'flowlabel', diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 58d130ef6..22441d1d2 100755 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1,4 +1,4 @@ -# Copyright 2019-2021 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2022 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 @@ -13,7 +13,6 @@ # 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/>. -from netifaces import interfaces import os import re import json @@ -37,6 +36,7 @@ from vyos.util import mac2eui64 from vyos.util import dict_search from vyos.util import read_file from vyos.util import get_interface_config +from vyos.util import get_interface_namespace from vyos.util import is_systemd_service_active from vyos.template import is_ipv4 from vyos.template import is_ipv6 @@ -135,6 +135,9 @@ class Interface(Control): 'validate': assert_mtu, 'shellcmd': 'ip link set dev {ifname} mtu {value}', }, + 'netns': { + 'shellcmd': 'ip link set dev {ifname} netns {value}', + }, 'vrf': { 'convert': lambda v: f'master {v}' if v else 'nomaster', 'shellcmd': 'ip link set dev {ifname} {value}', @@ -512,6 +515,35 @@ class Interface(Control): if prev_state == 'up': self.set_admin_state('up') + def del_netns(self, netns): + """ + Remove interface from given NETNS. + """ + + # If NETNS does not exist then there is nothing to delete + if not os.path.exists(f'/run/netns/{netns}'): + return None + + # As a PoC we only allow 'dummy' interfaces + if 'dum' not in self.ifname: + return None + + # Check if interface realy exists in namespace + if get_interface_namespace(self.ifname) != None: + self._cmd(f'ip netns exec {get_interface_namespace(self.ifname)} ip link del dev {self.ifname}') + return + + def set_netns(self, netns): + """ + Add interface from given NETNS. + + Example: + >>> from vyos.ifconfig import Interface + >>> Interface('dum0').set_netns('foo') + """ + + self.set_interface('netns', netns) + def set_vrf(self, vrf): """ Add/Remove interface from given VRF instance. @@ -544,6 +576,15 @@ class Interface(Control): return None return self.set_interface('arp_cache_tmo', tmo) + def _cleanup_mss_rules(self, table, ifname): + commands = [] + results = self._cmd(f'nft -a list chain {table} VYOS_TCP_MSS').split("\n") + for line in results: + if f'oifname "{ifname}"' in line: + handle_search = re.search('handle (\d+)', line) + if handle_search: + self._cmd(f'nft delete rule {table} VYOS_TCP_MSS handle {handle_search[1]}') + def set_tcp_ipv4_mss(self, mss): """ Set IPv4 TCP MSS value advertised when TCP SYN packets leave this @@ -555,22 +596,14 @@ class Interface(Control): >>> from vyos.ifconfig import Interface >>> Interface('eth0').set_tcp_ipv4_mss(1340) """ - iptables_bin = 'iptables' - base_options = f'-A FORWARD -o {self.ifname} -p tcp -m tcp --tcp-flags SYN,RST SYN' - out = self._cmd(f'{iptables_bin}-save -t mangle') - for line in out.splitlines(): - if line.startswith(base_options): - # remove OLD MSS mangling configuration - line = line.replace('-A FORWARD', '-D FORWARD') - self._cmd(f'{iptables_bin} -t mangle {line}') - - cmd_mss = f'{iptables_bin} -t mangle {base_options} --jump TCPMSS' + self._cleanup_mss_rules('raw', self.ifname) + nft_prefix = 'nft add rule raw VYOS_TCP_MSS' + base_cmd = f'oifname "{self.ifname}" tcp flags & (syn|rst) == syn' if mss == 'clamp-mss-to-pmtu': - self._cmd(f'{cmd_mss} --clamp-mss-to-pmtu') + self._cmd(f"{nft_prefix} '{base_cmd} tcp option maxseg size set rt mtu'") elif int(mss) > 0: - # probably add option to clamp only if bigger: low_mss = str(int(mss) + 1) - self._cmd(f'{cmd_mss} -m tcpmss --mss {low_mss}:65535 --set-mss {mss}') + self._cmd(f"{nft_prefix} '{base_cmd} tcp option maxseg size {low_mss}-65535 tcp option maxseg size set {mss}'") def set_tcp_ipv6_mss(self, mss): """ @@ -583,22 +616,14 @@ class Interface(Control): >>> from vyos.ifconfig import Interface >>> Interface('eth0').set_tcp_mss(1320) """ - iptables_bin = 'ip6tables' - base_options = f'-A FORWARD -o {self.ifname} -p tcp -m tcp --tcp-flags SYN,RST SYN' - out = self._cmd(f'{iptables_bin}-save -t mangle') - for line in out.splitlines(): - if line.startswith(base_options): - # remove OLD MSS mangling configuration - line = line.replace('-A FORWARD', '-D FORWARD') - self._cmd(f'{iptables_bin} -t mangle {line}') - - cmd_mss = f'{iptables_bin} -t mangle {base_options} --jump TCPMSS' + self._cleanup_mss_rules('ip6 raw', self.ifname) + nft_prefix = 'nft add rule ip6 raw VYOS_TCP_MSS' + base_cmd = f'oifname "{self.ifname}" tcp flags & (syn|rst) == syn' if mss == 'clamp-mss-to-pmtu': - self._cmd(f'{cmd_mss} --clamp-mss-to-pmtu') + self._cmd(f"{nft_prefix} '{base_cmd} tcp option maxseg size set rt mtu'") elif int(mss) > 0: - # probably add option to clamp only if bigger: low_mss = str(int(mss) + 1) - self._cmd(f'{cmd_mss} -m tcpmss --mss {low_mss}:65535 --set-mss {mss}') + self._cmd(f"{nft_prefix} '{base_cmd} tcp option maxseg size {low_mss}-65535 tcp option maxseg size set {mss}'") def set_arp_filter(self, arp_filter): """ @@ -711,8 +736,9 @@ class Interface(Control): if all_rp_filter == 1: global_setting = 'strict' elif all_rp_filter == 2: global_setting = 'loose' - print(f'WARNING: Global source-validation is set to "{global_setting}\n"' \ - 'this overrides per interface setting!') + from vyos.base import Warning + Warning(f'Global source-validation is set to "{global_setting} '\ + f'this overrides per interface setting!') tmp = self.get_interface('rp_filter') if int(tmp) == value: @@ -1054,16 +1080,17 @@ class Interface(Control): if addr in self._addr: return False - addr_is_v4 = is_ipv4(addr) - # add to interface if addr == 'dhcp': self.set_dhcp(True) elif addr == 'dhcpv6': self.set_dhcpv6(True) elif not is_intf_addr_assigned(self.ifname, addr): - self._cmd(f'ip addr add "{addr}" ' - f'{"brd + " if addr_is_v4 else ""}dev "{self.ifname}"') + tmp = f'ip addr add {addr} dev {self.ifname}' + # Add broadcast address for IPv4 + if is_ipv4(addr): tmp += ' brd +' + + self._cmd(tmp) else: return False @@ -1202,12 +1229,11 @@ class Interface(Control): options_file = f'{config_base}_{ifname}.options' pid_file = f'{config_base}_{ifname}.pid' lease_file = f'{config_base}_{ifname}.leases' - - # Stop client with old config files to get the right IF_METRIC. systemd_service = f'dhclient@{ifname}.service' - if is_systemd_service_active(systemd_service): - self._cmd(f'systemctl stop {systemd_service}') + # 'up' check is mandatory b/c even if the interface is A/D, as soon as + # the DHCP client is started the interface will be placed in u/u state. + # This is not what we intended to do when disabling an interface. if enable and 'disable' not in self._config: if dict_search('dhcp_options.host_name', self._config) == None: # read configured system hostname. @@ -1218,16 +1244,19 @@ class Interface(Control): tmp = {'dhcp_options' : { 'host_name' : hostname}} self._config = dict_merge(tmp, self._config) - render(options_file, 'dhcp-client/daemon-options.tmpl', - self._config) - render(config_file, 'dhcp-client/ipv4.tmpl', - self._config) + render(options_file, 'dhcp-client/daemon-options.j2', self._config) + render(config_file, 'dhcp-client/ipv4.j2', self._config) - # 'up' check is mandatory b/c even if the interface is A/D, as soon as - # the DHCP client is started the interface will be placed in u/u state. - # This is not what we intended to do when disabling an interface. - return self._cmd(f'systemctl restart {systemd_service}') + # When the DHCP client is restarted a brief outage will occur, as + # the old lease is released a new one is acquired (T4203). We will + # only restart DHCP client if it's option changed, or if it's not + # running, but it should be running (e.g. on system startup) + if 'dhcp_options_changed' in self._config or not is_systemd_service_active(systemd_service): + return self._cmd(f'systemctl restart {systemd_service}') + return None else: + if is_systemd_service_active(systemd_service): + self._cmd(f'systemctl stop {systemd_service}') # cleanup old config files for file in [config_file, options_file, pid_file, lease_file]: if os.path.isfile(file): @@ -1246,8 +1275,7 @@ class Interface(Control): systemd_service = f'dhcp6c@{ifname}.service' if enable and 'disable' not in self._config: - render(config_file, 'dhcp-client/ipv6.tmpl', - self._config) + render(config_file, 'dhcp-client/ipv6.j2', self._config) # We must ignore any return codes. This is required to enable # DHCPv6-PD for interfaces which are yet not up and running. @@ -1258,48 +1286,57 @@ class Interface(Control): if os.path.isfile(config_file): os.remove(config_file) - def set_mirror(self): + def set_mirror_redirect(self): # Please refer to the document for details # - https://man7.org/linux/man-pages/man8/tc.8.html # - https://man7.org/linux/man-pages/man8/tc-mirred.8.html # Depening if we are the source or the target interface of the port # mirror we need to setup some variables. source_if = self._config['ifname'] - config = self._config.get('mirror', None) + mirror_config = None + if 'mirror' in self._config: + mirror_config = self._config['mirror'] if 'is_mirror_intf' in self._config: source_if = next(iter(self._config['is_mirror_intf'])) - config = self._config['is_mirror_intf'][source_if].get('mirror', None) - - # Check configuration stored by old perl code before delete T3782 - if not 'redirect' in self._config: - # Please do not clear the 'set $? = 0 '. It's meant to force a return of 0 - # Remove existing mirroring rules - delete_tc_cmd = f'tc qdisc del dev {source_if} handle ffff: ingress 2> /dev/null;' - delete_tc_cmd += f'tc qdisc del dev {source_if} handle 1: root prio 2> /dev/null;' - delete_tc_cmd += 'set $?=0' - self._popen(delete_tc_cmd) - - # Bail out early if nothing needs to be configured - if not config: - return - - for direction, mirror_if in config.items(): - if mirror_if not in interfaces(): - continue - - if direction == 'ingress': - handle = 'ffff: ingress' - parent = 'ffff:' - elif direction == 'egress': - handle = '1: root prio' - parent = '1:' - - # Mirror egress traffic - mirror_cmd = f'tc qdisc add dev {source_if} handle {handle}; ' - # Export the mirrored traffic to the interface - mirror_cmd += f'tc filter add dev {source_if} parent {parent} protocol all prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress mirror dev {mirror_if}' - self._popen(mirror_cmd) + mirror_config = self._config['is_mirror_intf'][source_if].get('mirror', None) + + redirect_config = None + + # clear existing ingess - ignore errors (e.g. "Error: Cannot find specified + # qdisc on specified device") - we simply cleanup all stuff here + self._popen(f'tc qdisc del dev {source_if} parent ffff: 2>/dev/null'); + self._popen(f'tc qdisc del dev {source_if} parent 1: 2>/dev/null'); + + # Apply interface mirror policy + if mirror_config: + for direction, target_if in mirror_config.items(): + if direction == 'ingress': + handle = 'ffff: ingress' + parent = 'ffff:' + elif direction == 'egress': + handle = '1: root prio' + parent = '1:' + + # Mirror egress traffic + mirror_cmd = f'tc qdisc add dev {source_if} handle {handle}; ' + # Export the mirrored traffic to the interface + mirror_cmd += f'tc filter add dev {source_if} parent {parent} protocol '\ + f'all prio 10 u32 match u32 0 0 flowid 1:1 action mirred '\ + f'egress mirror dev {target_if}' + _, err = self._popen(mirror_cmd) + if err: print('tc qdisc(filter for mirror port failed') + + # Apply interface traffic redirection policy + elif 'redirect' in self._config: + _, err = self._popen(f'tc qdisc add dev {source_if} handle ffff: ingress') + if err: print(f'tc qdisc add for redirect failed!') + + target_if = self._config['redirect'] + _, err = self._popen(f'tc filter add dev {source_if} parent ffff: protocol '\ + f'all prio 10 u32 match u32 0 0 flowid 1:1 action mirred '\ + f'egress redirect dev {target_if}') + if err: print('tc filter add for redirect failed') def set_xdp(self, state): """ @@ -1353,6 +1390,16 @@ class Interface(Control): if mac: self.set_mac(mac) + # If interface is connected to NETNS we don't have to check all other + # settings like MTU/IPv6/sysctl values, etc. + # Since the interface is pushed onto a separate logical stack + # Configure NETNS + if dict_search('netns', config) != None: + self.set_netns(config.get('netns', '')) + return + else: + self.del_netns(config.get('netns', '')) + # Update interface description self.set_alias(config.get('description', '')) @@ -1388,9 +1435,6 @@ class Interface(Control): else: self.del_addr(addr) - for addr in new_addr: - self.add_addr(addr) - # start DHCPv6 client when only PD was configured if dhcpv6pd: self.set_dhcpv6(True) @@ -1405,16 +1449,15 @@ class Interface(Control): # checked before self.set_vrf(config.get('vrf', '')) + # Add this section after vrf T4331 + for addr in new_addr: + self.add_addr(addr) + # Configure MSS value for IPv4 TCP connections tmp = dict_search('ip.adjust_mss', config) value = tmp if (tmp != None) else '0' self.set_tcp_ipv4_mss(value) - # Configure MSS value for IPv6 TCP connections - tmp = dict_search('ipv6.adjust_mss', config) - value = tmp if (tmp != None) else '0' - self.set_tcp_ipv6_mss(value) - # Configure ARP cache timeout in milliseconds - has default value tmp = dict_search('ip.arp_cache_timeout', config) value = tmp if (tmp != None) else '30' @@ -1460,6 +1503,18 @@ class Interface(Control): value = tmp if (tmp != None) else '0' self.set_ipv4_source_validation(value) + # MTU - Maximum Transfer Unit has a default value. It must ALWAYS be set + # before mangling any IPv6 option. If MTU is less then 1280 IPv6 will be + # automatically disabled by the kernel. Also MTU must be increased before + # configuring any IPv6 address on the interface. + if 'mtu' in config: + self.set_mtu(config.get('mtu')) + + # Configure MSS value for IPv6 TCP connections + tmp = dict_search('ipv6.adjust_mss', config) + value = tmp if (tmp != None) else '0' + self.set_tcp_ipv6_mss(value) + # IPv6 forwarding tmp = dict_search('ipv6.disable_forwarding', config) value = '0' if (tmp != None) else '1' @@ -1482,10 +1537,6 @@ class Interface(Control): value = tmp if (tmp != None) else '1' self.set_ipv6_dad_messages(value) - # MTU - Maximum Transfer Unit - if 'mtu' in config: - self.set_mtu(config.get('mtu')) - # Delete old IPv6 EUI64 addresses before changing MAC for addr in (dict_search('ipv6.address.eui64_old', config) or []): self.del_ipv6_eui64_address(addr) @@ -1510,8 +1561,8 @@ class Interface(Control): # eXpress Data Path - highly experimental self.set_xdp('xdp' in config) - # configure port mirror - self.set_mirror() + # configure interface mirror or redirection target + self.set_mirror_redirect() # Enable/Disable of an interface must always be done at the end of the # derived class to make use of the ref-counting set_admin_state() @@ -1536,12 +1587,10 @@ class Interface(Control): tmp['source_interface'] = ifname tmp['vlan_id'] = vif_s_id - vif_s_ifname = f'{ifname}.{vif_s_id}' - vif_s_config['ifname'] = vif_s_ifname - # It is not possible to change the VLAN encapsulation protocol # "on-the-fly". For this "quirk" we need to actively delete and # re-create the VIF-S interface. + vif_s_ifname = f'{ifname}.{vif_s_id}' if self.exists(vif_s_ifname): cur_cfg = get_interface_config(vif_s_ifname) protocol = dict_search('linkinfo.info_data.protocol', cur_cfg).lower() @@ -1563,7 +1612,6 @@ class Interface(Control): tmp['vlan_id'] = vif_c_id vif_c_ifname = f'{vif_s_ifname}.{vif_c_id}' - vif_c_config['ifname'] = vif_c_ifname c_vlan = VLANIf(vif_c_ifname, **tmp) c_vlan.update(vif_c_config) @@ -1574,10 +1622,7 @@ class Interface(Control): # create/update 802.1q VLAN interfaces for vif_id, vif_config in config.get('vif', {}).items(): - vif_ifname = f'{ifname}.{vif_id}' - vif_config['ifname'] = vif_ifname - tmp = deepcopy(VLANIf.get_config()) tmp['source_interface'] = ifname tmp['vlan_id'] = vif_id @@ -1670,6 +1715,3 @@ class VLANIf(Interface): return None return super().set_admin_state(state) - - def set_mirror(self): - return diff --git a/python/vyos/ifconfig/loopback.py b/python/vyos/ifconfig/loopback.py index 192c12f5c..b3babfadc 100644 --- a/python/vyos/ifconfig/loopback.py +++ b/python/vyos/ifconfig/loopback.py @@ -1,4 +1,4 @@ -# Copyright 2019-2021 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2022 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 @@ -23,7 +23,6 @@ class LoopbackIf(Interface): """ _persistent_addresses = ['127.0.0.1/8', '::1/128'] iftype = 'loopback' - definition = { **Interface.definition, **{ @@ -32,6 +31,7 @@ class LoopbackIf(Interface): 'bridgeable': True, } } + def remove(self): """ Loopback interface can not be deleted from operating system. We can @@ -57,12 +57,14 @@ class LoopbackIf(Interface): interface setup code and provide a single point of entry when workin on any interface. """ - addr = config.get('address', []) + address = config.get('address', []) # We must ensure that the loopback addresses are never deleted from the system - addr += self._persistent_addresses + for tmp in self._persistent_addresses: + if tmp not in address: + address.append(tmp) # Update IP address entry in our dictionary - config.update({'address' : addr}) + config.update({'address' : address}) # call base class super().update(config) diff --git a/python/vyos/ifconfig/pppoe.py b/python/vyos/ifconfig/pppoe.py index 1d13264bf..63ffc8069 100644 --- a/python/vyos/ifconfig/pppoe.py +++ b/python/vyos/ifconfig/pppoe.py @@ -27,12 +27,13 @@ class PPPoEIf(Interface): }, } - def _remove_routes(self, vrf=''): + def _remove_routes(self, vrf=None): # Always delete default routes when interface is removed + vrf_cmd = '' if vrf: - vrf = f'-c "vrf {vrf}"' - self._cmd(f'vtysh -c "conf t" {vrf} -c "no ip route 0.0.0.0/0 {self.ifname} tag 210"') - self._cmd(f'vtysh -c "conf t" {vrf} -c "no ipv6 route ::/0 {self.ifname} tag 210"') + vrf_cmd = f'-c "vrf {vrf}"' + self._cmd(f'vtysh -c "conf t" {vrf_cmd} -c "no ip route 0.0.0.0/0 {self.ifname} tag 210"') + self._cmd(f'vtysh -c "conf t" {vrf_cmd} -c "no ipv6 route ::/0 {self.ifname} tag 210"') def remove(self): """ @@ -44,11 +45,11 @@ class PPPoEIf(Interface): >>> i = Interface('pppoe0') >>> i.remove() """ - + vrf = None tmp = get_interface_config(self.ifname) - vrf = '' if 'master' in tmp: - self._remove_routes(tmp['master']) + vrf = tmp['master'] + self._remove_routes(vrf) # remove bond master which places members in disabled state super().remove() @@ -84,10 +85,12 @@ class PPPoEIf(Interface): self._config = config # remove old routes from an e.g. old VRF assignment - vrf = '' - if 'vrf_old' in config: - vrf = config['vrf_old'] - self._remove_routes(vrf) + if 'shutdown_required': + vrf = None + tmp = get_interface_config(self.ifname) + if 'master' in tmp: + vrf = tmp['master'] + self._remove_routes(vrf) # DHCPv6 PD handling is a bit different on PPPoE interfaces, as we do # not require an 'address dhcpv6' CLI option as with other interfaces @@ -98,54 +101,15 @@ class PPPoEIf(Interface): super().update(config) - if 'default_route' not in config or config['default_route'] == 'none': - return - - # - # Set default routes pointing to pppoe interface - # - vrf = '' - sed_opt = '^ip route' - - install_v4 = True - install_v6 = True - # generate proper configuration string when VRFs are in use + vrf = '' if 'vrf' in config: tmp = config['vrf'] vrf = f'-c "vrf {tmp}"' - sed_opt = f'vrf {tmp}' - - if config['default_route'] == 'auto': - # only add route if there is no default route present - tmp = self._cmd(f'vtysh -c "show running-config staticd no-header" | sed -n "/{sed_opt}/,/!/p"') - for line in tmp.splitlines(): - line = line.lstrip() - if line.startswith('ip route 0.0.0.0/0'): - install_v4 = False - continue - - if 'ipv6' in config and line.startswith('ipv6 route ::/0'): - install_v6 = False - continue - - elif config['default_route'] == 'force': - # Force means that all static routes are replaced with the ones from this interface - tmp = self._cmd(f'vtysh -c "show running-config staticd no-header" | sed -n "/{sed_opt}/,/!/p"') - for line in tmp.splitlines(): - if self.ifname in line: - # It makes no sense to remove a route with our interface and the later re-add it. - # This will only make traffic disappear - which is a no-no! - continue - - line = line.lstrip() - if line.startswith('ip route 0.0.0.0/0'): - self._cmd(f'vtysh -c "conf t" {vrf} -c "no {line}"') - - if 'ipv6' in config and line.startswith('ipv6 route ::/0'): - self._cmd(f'vtysh -c "conf t" {vrf} -c "no {line}"') - - if install_v4: - self._cmd(f'vtysh -c "conf t" {vrf} -c "ip route 0.0.0.0/0 {self.ifname} tag 210"') - if install_v6 and 'ipv6' in config: - self._cmd(f'vtysh -c "conf t" {vrf} -c "ipv6 route ::/0 {self.ifname} tag 210"') + + if 'no_default_route' not in config: + # Set default route(s) pointing to PPPoE interface + distance = config['default_route_distance'] + self._cmd(f'vtysh -c "conf t" {vrf} -c "ip route 0.0.0.0/0 {self.ifname} tag 210 {distance}"') + if 'ipv6' in config: + self._cmd(f'vtysh -c "conf t" {vrf} -c "ipv6 route ::/0 {self.ifname} tag 210 {distance}"') diff --git a/python/vyos/ifconfig/section.py b/python/vyos/ifconfig/section.py index 0e4447b9e..91f667b65 100644 --- a/python/vyos/ifconfig/section.py +++ b/python/vyos/ifconfig/section.py @@ -52,12 +52,12 @@ class Section: name: name of the interface vlan: if vlan is True, do not stop at the vlan number """ - name = name.rstrip('0123456789') - name = name.rstrip('.') - if vlan: - name = name.rstrip('0123456789.') if vrrp: - name = name.rstrip('0123456789v') + name = re.sub(r'\d(\d|v|\.)*$', '', name) + elif vlan: + name = re.sub(r'\d(\d|\.)*$', '', name) + else: + name = re.sub(r'\d+$', '', name) return name @classmethod diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py index d73fb47b8..5baff10a9 100644 --- a/python/vyos/ifconfig/vxlan.py +++ b/python/vyos/ifconfig/vxlan.py @@ -1,4 +1,4 @@ -# Copyright 2019-2021 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019-2022 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 @@ -54,18 +54,31 @@ class VXLANIf(Interface): # arguments used by iproute2. For more information please refer to: # - https://man7.org/linux/man-pages/man8/ip-link.8.html mapping = { - 'source_address' : 'local', - 'source_interface' : 'dev', - 'remote' : 'remote', 'group' : 'group', - 'parameters.ip.dont_fragment': 'df set', + 'external' : 'external', + 'gpe' : 'gpe', + 'parameters.ip.df' : 'df', 'parameters.ip.tos' : 'tos', 'parameters.ip.ttl' : 'ttl', 'parameters.ipv6.flowlabel' : 'flowlabel', 'parameters.nolearning' : 'nolearning', + 'remote' : 'remote', + 'source_address' : 'local', + 'source_interface' : 'dev', + 'vni' : 'id', } - cmd = 'ip link add {ifname} type {type} id {vni} dstport {port}' + # IPv6 flowlabels can only be used on IPv6 tunnels, thus we need to + # ensure that at least the first remote IP address is passed to the + # tunnel creation command. Subsequent tunnel remote addresses can later + # be added to the FDB + remote_list = None + if 'remote' in self.config: + # skip first element as this is already configured as remote + remote_list = self.config['remote'][1:] + self.config['remote'] = self.config['remote'][0] + + cmd = 'ip link add {ifname} type {type} dstport {port}' for vyos_key, iproute2_key in mapping.items(): # dict_search will return an empty dict "{}" for valueless nodes like # "parameters.nolearning" - thus we need to test the nodes existence @@ -79,3 +92,10 @@ class VXLANIf(Interface): self._cmd(cmd.format(**self.config)) # interface is always A/D down. It needs to be enabled explicitly self.set_admin_state('down') + + # VXLAN tunnel is always recreated on any change - see interfaces-vxlan.py + if remote_list: + for remote in remote_list: + cmd = f'bridge fdb append to 00:00:00:00:00:00 dst {remote} ' \ + 'port {port} dev {ifname}' + self._cmd(cmd.format(**self.config)) diff --git a/python/vyos/ifconfig/wireless.py b/python/vyos/ifconfig/wireless.py index 748b6e02d..88eaa772b 100644 --- a/python/vyos/ifconfig/wireless.py +++ b/python/vyos/ifconfig/wireless.py @@ -49,10 +49,10 @@ class WiFiIf(Interface): on any interface. """ # We can not call add_to_bridge() until wpa_supplicant is running, thus - # we will remove the key from the config dict and react to this specal - # case in thie derived class. + # we will remove the key from the config dict and react to this special + # case in this derived class. # re-add ourselves to any bridge we might have fallen out of - bridge_member = '' + bridge_member = None if 'is_bridge_member' in config: bridge_member = config['is_bridge_member'] del config['is_bridge_member'] diff --git a/python/vyos/migrator.py b/python/vyos/migrator.py index 4574bb6d1..a2e0daabd 100644 --- a/python/vyos/migrator.py +++ b/python/vyos/migrator.py @@ -195,7 +195,7 @@ class Migrator(object): # This will force calling all migration scripts: cfg_versions = {} - sys_versions = systemversions.get_system_versions() + sys_versions = systemversions.get_system_component_version() # save system component versions in json file for easy reference self.save_json_record(sys_versions) diff --git a/python/vyos/pki.py b/python/vyos/pki.py index 68ad73bf2..0b916eaae 100644 --- a/python/vyos/pki.py +++ b/python/vyos/pki.py @@ -331,3 +331,29 @@ def verify_certificate(cert, ca_cert): return True except InvalidSignature: return False + +# Certificate chain + +def find_parent(cert, ca_certs): + for ca_cert in ca_certs: + if verify_certificate(cert, ca_cert): + return ca_cert + return None + +def find_chain(cert, ca_certs): + remaining = ca_certs.copy() + chain = [cert] + + while remaining: + parent = find_parent(chain[-1], remaining) + if parent is None: + # No parent in the list of remaining certificates or there's a circular dependency + break + elif parent == chain[-1]: + # Self-signed: must be root CA (end of chain) + break + else: + remaining.remove(parent) + chain.append(parent) + + return chain diff --git a/python/vyos/range_regex.py b/python/vyos/range_regex.py new file mode 100644 index 000000000..a8190d140 --- /dev/null +++ b/python/vyos/range_regex.py @@ -0,0 +1,142 @@ +'''Copyright (c) 2013, Dmitry Voronin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +''' +import math + +# coding=utf8 + +# Split range to ranges that has its unique pattern. +# Example for 12-345: +# +# 12- 19: 1[2-9] +# 20- 99: [2-9]\d +# 100-299: [1-2]\d{2} +# 300-339: 3[0-3]\d +# 340-345: 34[0-5] + +def range_to_regex(inpt_range): + if isinstance(inpt_range, str): + range_list = inpt_range.split('-') + # Check input arguments + if len(range_list) == 2: + # The first element in range must be higher then the second + if int(range_list[0]) < int(range_list[1]): + return regex_for_range(int(range_list[0]), int(range_list[1])) + + return None + +def bounded_regex_for_range(min_, max_): + return r'\b({})\b'.format(regex_for_range(min_, max_)) + +def regex_for_range(min_, max_): + """ + > regex_for_range(12, 345) + '1[2-9]|[2-9]\d|[1-2]\d{2}|3[0-3]\d|34[0-5]' + """ + positive_subpatterns = [] + negative_subpatterns = [] + + if min_ < 0: + min__ = 1 + if max_ < 0: + min__ = abs(max_) + max__ = abs(min_) + + negative_subpatterns = split_to_patterns(min__, max__) + min_ = 0 + + if max_ >= 0: + positive_subpatterns = split_to_patterns(min_, max_) + + negative_only_subpatterns = ['-' + val for val in negative_subpatterns if val not in positive_subpatterns] + positive_only_subpatterns = [val for val in positive_subpatterns if val not in negative_subpatterns] + intersected_subpatterns = ['-?' + val for val in negative_subpatterns if val in positive_subpatterns] + + subpatterns = negative_only_subpatterns + intersected_subpatterns + positive_only_subpatterns + return '|'.join(subpatterns) + + +def split_to_patterns(min_, max_): + subpatterns = [] + + start = min_ + for stop in split_to_ranges(min_, max_): + subpatterns.append(range_to_pattern(start, stop)) + start = stop + 1 + + return subpatterns + + +def split_to_ranges(min_, max_): + stops = {max_} + + nines_count = 1 + stop = fill_by_nines(min_, nines_count) + while min_ <= stop < max_: + stops.add(stop) + + nines_count += 1 + stop = fill_by_nines(min_, nines_count) + + zeros_count = 1 + stop = fill_by_zeros(max_ + 1, zeros_count) - 1 + while min_ < stop <= max_: + stops.add(stop) + + zeros_count += 1 + stop = fill_by_zeros(max_ + 1, zeros_count) - 1 + + stops = list(stops) + stops.sort() + + return stops + + +def fill_by_nines(integer, nines_count): + return int(str(integer)[:-nines_count] + '9' * nines_count) + + +def fill_by_zeros(integer, zeros_count): + return integer - integer % 10 ** zeros_count + + +def range_to_pattern(start, stop): + pattern = '' + any_digit_count = 0 + + for start_digit, stop_digit in zip(str(start), str(stop)): + if start_digit == stop_digit: + pattern += start_digit + elif start_digit != '0' or stop_digit != '9': + pattern += '[{}-{}]'.format(start_digit, stop_digit) + else: + any_digit_count += 1 + + if any_digit_count: + pattern += r'\d' + + if any_digit_count > 1: + pattern += '{{{}}}'.format(any_digit_count) + + return pattern
\ No newline at end of file diff --git a/python/vyos/remote.py b/python/vyos/remote.py index 2419f8873..66044fa52 100644 --- a/python/vyos/remote.py +++ b/python/vyos/remote.py @@ -74,20 +74,6 @@ class SourceAdapter(HTTPAdapter): num_pools=connections, maxsize=maxsize, block=block, source_address=self._source_pair) -class WrappedFile: - def __init__(self, obj, size=None, chunk_size=CHUNK_SIZE): - self._obj = obj - self._progress = size and make_incremental_progressbar(chunk_size / size) - def read(self, size=-1): - if self._progress: - next(self._progress) - self._obj.read(size) - def write(self, size=-1): - if self._progress: - next(self._progress) - self._obj.write(size) - def __getattr__(self, attr): - return getattr(self._obj, attr) def check_storage(path, size): """ @@ -97,8 +83,7 @@ def check_storage(path, size): directory = path if os.path.isdir(path) else (os.path.dirname(os.path.expanduser(path)) or os.getcwd()) # `size` can be None or 0 to indicate unknown size. if not size: - print_error('Warning: Cannot determine size of remote file.') - print_error('Bravely continuing regardless.') + print_error('Warning: Cannot determine size of remote file. Bravely continuing regardless.') return if size < 1024 * 1024: @@ -236,9 +221,13 @@ class HttpC: # Not only would it potentially mess up with the progress bar but # `shutil.copyfileobj(request.raw, file)` does not handle automatic decoding. s.headers.update({'Accept-Encoding': 'identity'}) - with s.head(self.urlstring) as r: + with s.head(self.urlstring, allow_redirects=True) as r: # Abort early if the destination is inaccessible. r.raise_for_status() + # If the request got redirected, keep the last URL we ended up with. + final_urlstring = r.url + if r.history and self.progressbar: + print_error('Redirecting to ' + final_urlstring) # Check for the prospective file size. try: size = int(r.headers['Content-Length']) @@ -247,7 +236,7 @@ class HttpC: size = None if self.check_space: check_storage(location, size) - with s.get(self.urlstring, stream=True) as r, open(location, 'wb') as f: + with s.get(final_urlstring, stream=True) as r, open(location, 'wb') as f: if self.progressbar and size: progress = make_incremental_progressbar(CHUNK_SIZE / size) next(progress) @@ -259,10 +248,9 @@ class HttpC: shutil.copyfileobj(r.raw, f) def upload(self, location: str): - size = os.path.getsize(location) if self.progressbar else None - # Keep in mind that `data` can be a file-like or iterable object. - with self._establish() as s, file(location, 'rb') as f: - s.post(self.urlstring, data=WrappedFile(f, size)) + # Does not yet support progressbars. + with self._establish() as s, open(location, 'rb') as f: + s.post(self.urlstring, data=f, allow_redirects=True) class TftpC: @@ -324,15 +312,16 @@ def friendly_download(local_path, urlstring, source_host='', source_port=0): print_error('Downloading...') download(local_path, urlstring, True, True, source_host, source_port) except KeyboardInterrupt: - print_error('Download aborted by user.') + print_error('\nDownload aborted by user.') sys.exit(1) except: import traceback + print_error(f'Failed to download {urlstring}.') # There are a myriad different reasons a download could fail. # SSH errors, FTP errors, I/O errors, HTTP errors (403, 404...) # We omit the scary stack trace but print the error nevertheless. - print_error(f'Failed to download {urlstring}.') - traceback.print_exception(*sys.exc_info()[:2], None) + exc_type, exc_value, exc_traceback = sys.exc_info() + traceback.print_exception(exc_type, exc_value, None, 0, None, False) sys.exit(1) else: print_error('Download complete.') diff --git a/python/vyos/systemversions.py b/python/vyos/systemversions.py index 9b3f4f413..f2da76d4f 100644 --- a/python/vyos/systemversions.py +++ b/python/vyos/systemversions.py @@ -17,7 +17,10 @@ import os import re import sys import vyos.defaults +from vyos.xml import component_version +# legacy version, reading from the file names in +# /opt/vyatta/etc/config-migrate/current def get_system_versions(): """ Get component versions from running system; critical failure if @@ -37,3 +40,7 @@ def get_system_versions(): system_versions[pair[0]] = int(pair[1]) return system_versions + +# read from xml cache +def get_system_component_version(): + return component_version() diff --git a/python/vyos/template.py b/python/vyos/template.py index b32cafe74..132f5ddde 100644 --- a/python/vyos/template.py +++ b/python/vyos/template.py @@ -18,14 +18,16 @@ import os from jinja2 import Environment from jinja2 import FileSystemLoader - +from jinja2 import ChainableUndefined from vyos.defaults import directories from vyos.util import chmod from vyos.util import chown +from vyos.util import dict_search_args from vyos.util import makedir # Holds template filters registered via register_filter() _FILTERS = {} +_TESTS = {} # reuse Environments with identical settings to improve performance @functools.lru_cache(maxsize=2) @@ -41,8 +43,10 @@ def _get_environment(location=None): cache_size=100, loader=loc_loader, trim_blocks=True, + undefined=ChainableUndefined, ) env.filters.update(_FILTERS) + env.tests.update(_TESTS) return env @@ -66,6 +70,26 @@ def register_filter(name, func=None): _FILTERS[name] = func return func +def register_test(name, func=None): + """Register a function to be available as test in templates under given name. + + It can also be used as a decorator, see below in this module for examples. + + :raise RuntimeError: + when trying to register a test after a template has been rendered already + :raise ValueError: when trying to register a name which was taken already + """ + if func is None: + return functools.partial(register_test, name) + if _get_environment.cache_info().currsize: + raise RuntimeError( + "Tests can only be registered before rendering the first template" + ) + if name in _TESTS: + raise ValueError(f"A test with name {name!r} was registered already") + _TESTS[name] = func + return func + def render_to_string(template, content, formater=None, location=None): """Render a template from the template directory, raise on any errors. @@ -126,6 +150,14 @@ def render( ################################## # Custom template filters follow # ################################## +@register_filter('force_to_list') +def force_to_list(value): + """ Convert scalars to single-item lists and leave lists untouched """ + if isinstance(value, list): + return value + else: + return [value] + @register_filter('ip_from_cidr') def ip_from_cidr(prefix): """ Take an IPv4/IPv6 CIDR host and strip cidr mask. @@ -151,6 +183,16 @@ def bracketize_ipv6(address): return f'[{address}]' return address +@register_filter('dot_colon_to_dash') +def dot_colon_to_dash(text): + """ Replace dot and colon to dash for string + Example: + 192.0.2.1 => 192-0-2-1, 2001:db8::1 => 2001-db8--1 + """ + text = text.replace(":", "-") + text = text.replace(".", "-") + return text + @register_filter('netmask_from_cidr') def netmask_from_cidr(prefix): """ Take CIDR prefix and convert the prefix length to a "subnet mask". @@ -479,3 +521,123 @@ def get_openvpn_ncp_ciphers(ciphers): else: out.append(cipher) return ':'.join(out).upper() + +@register_filter('snmp_auth_oid') +def snmp_auth_oid(type): + if type not in ['md5', 'sha', 'aes', 'des', 'none']: + raise ValueError() + + OIDs = { + 'md5' : '.1.3.6.1.6.3.10.1.1.2', + 'sha' : '.1.3.6.1.6.3.10.1.1.3', + 'aes' : '.1.3.6.1.6.3.10.1.2.4', + 'des' : '.1.3.6.1.6.3.10.1.2.2', + 'none': '.1.3.6.1.6.3.10.1.2.1' + } + return OIDs[type] + +@register_filter('nft_action') +def nft_action(vyos_action): + if vyos_action == 'accept': + return 'return' + return vyos_action + +@register_filter('nft_rule') +def nft_rule(rule_conf, fw_name, rule_id, ip_name='ip'): + from vyos.firewall import parse_rule + return parse_rule(rule_conf, fw_name, rule_id, ip_name) + +@register_filter('nft_default_rule') +def nft_default_rule(fw_conf, fw_name): + output = ['counter'] + default_action = fw_conf.get('default_action', 'accept') + + if 'enable_default_log' in fw_conf: + action_suffix = default_action[:1].upper() + output.append(f'log prefix "[{fw_name[:19]}-default-{action_suffix}] "') + + output.append(nft_action(default_action)) + output.append(f'comment "{fw_name} default-action {default_action}"') + return " ".join(output) + +@register_filter('nft_state_policy') +def nft_state_policy(conf, state, ipv6=False): + out = [f'ct state {state}'] + + if 'log' in conf and 'enable' in conf['log']: + out.append('log') + + out.append('counter') + + if 'action' in conf: + out.append(conf['action']) + + return " ".join(out) + +@register_filter('nft_intra_zone_action') +def nft_intra_zone_action(zone_conf, ipv6=False): + if 'intra_zone_filtering' in zone_conf: + intra_zone = zone_conf['intra_zone_filtering'] + fw_name = 'ipv6_name' if ipv6 else 'name' + name_prefix = 'NAME6_' if ipv6 else 'NAME_' + + if 'action' in intra_zone: + if intra_zone['action'] == 'accept': + return 'return' + return intra_zone['action'] + elif dict_search_args(intra_zone, 'firewall', fw_name): + name = dict_search_args(intra_zone, 'firewall', fw_name) + return f'jump {name_prefix}{name}' + return 'return' + +@register_test('vyos_defined') +def vyos_defined(value, test_value=None, var_type=None): + """ + Jinja2 plugin to test if a variable is defined and not none - vyos_defined + will test value if defined and is not none and return true or false. + + If test_value is supplied, the value must also pass == test_value to return true. + If var_type is supplied, the value must also be of the specified class/type + + Examples: + 1. Test if var is defined and not none: + {% if foo is vyos_defined %} + ... + {% endif %} + + 2. Test if variable is defined, not none and has value "something" + {% if bar is vyos_defined("something") %} + ... + {% endif %} + + Parameters + ---------- + value : any + Value to test from ansible + test_value : any, optional + Value to test in addition of defined and not none, by default None + var_type : ['float', 'int', 'str', 'list', 'dict', 'tuple', 'bool'], optional + Type or Class to test for + + Returns + ------- + boolean + True if variable matches criteria, False in other cases. + + Implementation inspired and re-used from https://github.com/aristanetworks/ansible-avd/ + """ + + from jinja2 import Undefined + + if isinstance(value, Undefined) or value is None: + # Invalid value - return false + return False + elif test_value is not None and value != test_value: + # Valid value but not matching the optional argument + return False + elif str(var_type).lower() in ['float', 'int', 'str', 'list', 'dict', 'tuple', 'bool'] and str(var_type).lower() != type(value).__name__: + # Invalid class - return false + return False + else: + # Valid value and is matching optional argument if provided - return true + return True diff --git a/python/vyos/util.py b/python/vyos/util.py index d8e83ab8d..de55e108b 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -774,6 +774,14 @@ def dict_search_recursive(dict_object, key): for x in dict_search_recursive(j, key): yield x +def get_bridge_fdb(interface): + """ Returns the forwarding database entries for a given interface """ + if not os.path.exists(f'/sys/class/net/{interface}'): + return None + from json import loads + tmp = loads(cmd(f'bridge -j fdb show dev {interface}')) + return tmp + def get_interface_config(interface): """ Returns the used encapsulation protocol for given interface. If interface does not exist, None is returned. @@ -794,6 +802,24 @@ def get_interface_address(interface): tmp = loads(cmd(f'ip -d -j addr show {interface}'))[0] return tmp +def get_interface_namespace(iface): + """ + Returns wich netns the interface belongs to + """ + from json import loads + # Check if netns exist + tmp = loads(cmd(f'ip --json netns ls')) + if len(tmp) == 0: + return None + + for ns in tmp: + namespace = f'{ns["name"]}' + # Search interface in each netns + data = loads(cmd(f'ip netns exec {namespace} ip -j link show')) + for compare in data: + if iface == compare["ifname"]: + return namespace + def get_all_vrfs(): """ Return a dictionary of all system wide known VRF instances """ from json import loads @@ -934,14 +960,23 @@ def install_into_config(conf, config_paths, override_prompt=True): return None count = 0 + failed = [] for path in config_paths: if override_prompt and conf.exists(path) and not conf.is_multi(path): if not ask_yes_no(f'Config node "{node}" already exists. Do you want to overwrite it?'): continue - cmd(f'/opt/vyatta/sbin/my_set {path}') - count += 1 + try: + cmd(f'/opt/vyatta/sbin/my_set {path}') + count += 1 + except: + failed.append(path) + + if failed: + print(f'Failed to install {len(failed)} value(s). Commands to manually install:') + for path in failed: + print(f'set {path}') if count > 0: print(f'{count} value(s) installed. Use "compare" to see the pending changes, and "commit" to apply.') @@ -954,6 +989,11 @@ def is_wwan_connected(interface): if not interface.startswith('wwan'): raise ValueError(f'Specified interface "{interface}" is not a WWAN interface') + # ModemManager is required for connection(s) - if service is not running, + # there won't be any connection at all! + if not is_systemd_service_active('ModemManager.service'): + return False + modem = interface.lstrip('wwan') tmp = cmd(f'mmcli --modem {modem} --output-json') @@ -961,3 +1001,26 @@ def is_wwan_connected(interface): # return True/False if interface is in connected state return dict_search('modem.generic.state', tmp) == 'connected' + +def boot_configuration_complete() -> bool: + """ Check if the boot config loader has completed + """ + from vyos.defaults import config_status + + if os.path.isfile(config_status): + return True + return False + +def sysctl_read(name): + """ Read and return current value of sysctl() option """ + tmp = cmd(f'sysctl {name}') + return tmp.split()[-1] + +def sysctl_write(name, value): + """ Change value via sysctl() - return True if changed, False otherwise """ + tmp = cmd(f'sysctl {name}') + # last list index contains the actual value - only write if value differs + if sysctl_read(name) != str(value): + call(f'sysctl -wq {name}={value}') + return True + return False diff --git a/python/vyos/validate.py b/python/vyos/validate.py index 0dad2a6cb..e005da0e4 100644 --- a/python/vyos/validate.py +++ b/python/vyos/validate.py @@ -43,19 +43,14 @@ def _are_same_ip(one, two): s_two = AF_INET if is_ipv4(two) else AF_INET6 return inet_pton(f_one, one) == inet_pton(f_one, two) -def is_intf_addr_assigned(intf, addr): - if '/' in addr: - ip,mask = addr.split('/') - return _is_intf_addr_assigned(intf, ip, mask) - return _is_intf_addr_assigned(intf, addr) - -def _is_intf_addr_assigned(intf, address, netmask=None): +def is_intf_addr_assigned(intf, address) -> bool: """ Verify if the given IPv4/IPv6 address is assigned to specific interface. It can check both a single IP address (e.g. 192.0.2.1 or a assigned CIDR address 192.0.2.1/24. """ from vyos.template import is_ipv4 + from netifaces import ifaddresses from netifaces import AF_INET from netifaces import AF_INET6 @@ -76,6 +71,9 @@ def _is_intf_addr_assigned(intf, address, netmask=None): addr_type = AF_INET if is_ipv4(address) else AF_INET6 # Check every IP address on this interface for a match + netmask = None + if '/' in address: + address, netmask = address.split('/') for ip in ifaces.get(addr_type,[]): # ip can have the interface name in the 'addr' field, we need to remove it # {'addr': 'fe80::a00:27ff:fec5:f821%eth2', 'netmask': 'ffff:ffff:ffff:ffff::'} @@ -99,14 +97,20 @@ def _is_intf_addr_assigned(intf, address, netmask=None): return False -def is_addr_assigned(addr): - """ - Verify if the given IPv4/IPv6 address is assigned to any interface - """ +def is_addr_assigned(ip_address, vrf=None) -> bool: + """ Verify if the given IPv4/IPv6 address is assigned to any interfac """ from netifaces import interfaces - for intf in interfaces(): - tmp = is_intf_addr_assigned(intf, addr) - if tmp == True: + from vyos.util import get_interface_config + from vyos.util import dict_search + for interface in interfaces(): + # Check if interface belongs to the requested VRF, if this is not the + # case there is no need to proceed with this data set - continue loop + # with next element + tmp = get_interface_config(interface) + if dict_search('master', tmp) != vrf: + continue + + if is_intf_addr_assigned(interface, ip_address): return True return False diff --git a/python/vyos/xml/__init__.py b/python/vyos/xml/__init__.py index e0eacb2d1..6db446a40 100644 --- a/python/vyos/xml/__init__.py +++ b/python/vyos/xml/__init__.py @@ -46,8 +46,8 @@ def is_tag(lpath): def is_leaf(lpath, flat=True): return load_configuration().is_leaf(lpath, flat) -def component_versions(): - return load_configuration().component_versions() +def component_version(): + return load_configuration().component_version() def defaults(lpath, flat=False): return load_configuration().defaults(lpath, flat) diff --git a/python/vyos/xml/definition.py b/python/vyos/xml/definition.py index 5e0d5282c..bc3892b42 100644 --- a/python/vyos/xml/definition.py +++ b/python/vyos/xml/definition.py @@ -249,10 +249,11 @@ class XML(dict): # @lru_cache(maxsize=100) # XXX: need to use cachetool instead - for later - def component_versions(self) -> dict: - sort_component = sorted(self[kw.component_version].items(), - key = lambda kv: kv[0]) - return dict(sort_component) + def component_version(self) -> dict: + d = {} + for k in sorted(self[kw.component_version]): + d[k] = int(self[kw.component_version][k]) + return d def defaults(self, lpath, flat): d = self[kw.default] diff --git a/scripts/build-command-templates b/scripts/build-command-templates index d8abb0a13..876f5877c 100755 --- a/scripts/build-command-templates +++ b/scripts/build-command-templates @@ -117,7 +117,7 @@ def collect_validators(ve): return regex_args + " " + validator_args -def get_properties(p): +def get_properties(p, default=None): props = {} if p is None: @@ -125,7 +125,12 @@ def get_properties(p): # Get the help string try: - props["help"] = p.find("help").text + help = p.find("help").text + if default != None: + # DNS forwarding for instance has multiple defaults - specified as whitespace separated list + tmp = ', '.join(default.text.split()) + help += f' (default: {tmp})' + props["help"] = help except: pass @@ -134,7 +139,11 @@ def get_properties(p): vhe = p.findall("valueHelp") vh = [] for v in vhe: - vh.append( (v.find("format").text, v.find("description").text) ) + format = v.find("format").text + description = v.find("description").text + if default != None and default.text == format: + description += f' (default)' + vh.append( (format, description) ) props["val_help"] = vh except: props["val_help"] = [] @@ -271,7 +280,7 @@ def process_node(n, tmpl_dir): print("Name of the node: {0}. Created directory: {1}\n".format(name, "/".join(my_tmpl_dir)), end="") os.makedirs(make_path(my_tmpl_dir), exist_ok=True) - props = get_properties(props_elem) + props = get_properties(props_elem, n.find("defaultValue")) if owner: props["owner"] = owner # Type should not be set for non-tag, non-leaf nodes diff --git a/smoketest/configs.no-load/firewall-big b/smoketest/configs.no-load/firewall-big new file mode 100644 index 000000000..94b0c6dd5 --- /dev/null +++ b/smoketest/configs.no-load/firewall-big @@ -0,0 +1,43440 @@ +firewall { + all-ping enable + broadcast-ping disable + config-trap disable + group { + address-group CENTREON_SERVERS { + address 109.228.63.82 + } + address-group CLUSTER_ADDRESSES { + address 10.255.255.4 + address 10.255.255.5 + address 77.68.76.16 + address 77.68.77.16 + address 172.16.255.254 + address 77.68.76.14 + address 77.68.77.14 + address 77.68.76.13 + address 77.68.77.13 + address 77.68.76.12 + address 77.68.77.12 + address 77.68.77.67 + address 77.68.77.103 + address 77.68.77.130 + address 77.68.76.245 + address 77.68.77.85 + address 77.68.76.45 + address 77.68.77.144 + address 77.68.77.105 + address 77.68.76.122 + address 77.68.76.104 + address 77.68.77.115 + address 77.68.77.178 + address 77.68.76.239 + address 77.68.76.30 + address 77.68.77.249 + address 77.68.76.59 + address 77.68.77.44 + address 77.68.77.200 + address 77.68.77.228 + address 77.68.76.191 + address 77.68.76.102 + address 77.68.77.26 + address 77.68.76.152 + address 77.68.77.212 + address 77.68.76.142 + address 77.68.76.60 + address 77.68.77.253 + address 77.68.76.54 + address 77.68.76.33 + address 77.68.77.114 + address 77.68.77.176 + address 77.68.77.219 + address 77.68.77.19 + address 77.68.77.22 + address 77.68.77.248 + address 77.68.76.161 + address 77.68.77.56 + address 77.68.77.129 + address 77.68.77.140 + address 77.68.76.177 + address 77.68.77.117 + address 77.68.77.108 + address 77.68.76.50 + address 77.68.76.217 + address 77.68.77.160 + address 77.68.77.30 + address 77.68.77.21 + address 77.68.76.29 + address 77.68.76.158 + address 77.68.76.203 + address 77.68.77.243 + address 77.68.77.54 + address 77.68.76.22 + address 77.68.76.25 + address 77.68.76.21 + address 77.68.77.221 + address 77.68.77.76 + address 77.68.76.127 + address 77.68.77.139 + address 77.68.77.240 + address 77.68.76.39 + address 77.68.76.149 + address 77.68.77.57 + address 77.68.77.185 + address 77.68.76.116 + address 77.68.76.160 + address 77.68.77.70 + address 77.68.77.149 + address 77.68.76.57 + address 77.68.76.115 + address 77.68.76.200 + address 77.68.76.23 + address 77.68.77.46 + address 77.68.76.198 + address 77.68.77.141 + address 77.68.77.50 + address 77.68.77.128 + address 77.68.77.88 + address 77.68.76.80 + address 77.68.76.35 + address 77.68.77.204 + address 77.68.77.201 + address 77.68.77.97 + address 77.68.76.195 + address 77.68.76.202 + address 77.68.76.157 + address 77.68.77.159 + address 77.68.76.118 + address 77.68.76.38 + address 77.68.77.203 + address 77.68.77.233 + address 77.68.77.163 + address 77.68.77.49 + address 77.68.76.58 + address 77.68.77.171 + address 77.68.77.150 + address 77.68.77.199 + address 77.68.76.220 + address 77.68.77.156 + address 77.68.76.248 + address 77.68.76.171 + address 77.68.76.212 + address 77.68.77.132 + address 77.68.77.81 + address 77.68.76.37 + address 77.68.76.197 + address 77.68.76.20 + address 77.68.76.99 + address 77.68.77.211 + address 77.68.77.236 + address 77.68.76.252 + address 77.68.77.32 + address 77.68.77.247 + address 77.68.76.209 + address 77.68.77.202 + address 77.68.76.247 + address 77.68.77.99 + address 77.68.76.169 + address 77.68.76.95 + address 77.68.76.187 + address 77.68.77.222 + address 77.68.77.53 + address 77.68.77.124 + address 77.68.76.61 + address 77.68.77.43 + address 77.68.76.94 + address 77.68.77.165 + address 77.68.77.152 + address 77.68.76.44 + address 77.68.76.47 + address 77.68.76.74 + address 77.68.76.55 + address 77.68.77.75 + address 77.68.77.239 + address 77.68.76.75 + address 77.68.77.71 + address 77.68.76.145 + address 77.68.77.145 + address 77.68.77.68 + address 77.68.76.126 + address 77.68.76.88 + address 77.68.77.181 + address 77.68.76.112 + address 77.68.77.33 + address 77.68.77.137 + address 77.68.77.92 + address 77.68.76.111 + address 77.68.76.185 + address 77.68.76.208 + address 77.68.76.150 + address 77.68.77.208 + address 77.68.76.42 + address 77.68.76.164 + address 77.68.77.207 + address 77.68.76.49 + address 77.68.77.227 + address 77.68.76.136 + address 77.68.76.77 + address 77.68.76.123 + address 77.68.76.31 + address 77.68.76.148 + address 77.68.77.120 + address 77.68.76.183 + address 77.68.77.107 + address 77.68.76.141 + address 77.68.76.105 + address 77.68.76.251 + address 77.68.76.249 + address 77.68.77.59 + address 77.68.77.37 + address 77.68.77.65 + address 77.68.76.231 + address 77.68.77.24 + address 77.68.77.63 + address 77.68.76.234 + address 77.68.76.93 + address 77.68.77.77 + address 77.68.77.151 + address 77.68.76.235 + address 77.68.77.95 + address 77.68.77.190 + address 77.68.76.91 + address 77.68.77.79 + address 77.68.77.100 + address 77.68.76.241 + address 77.68.77.209 + address 77.68.76.110 + address 77.68.76.40 + address 77.68.76.76 + address 77.68.76.124 + address 77.68.77.234 + address 77.68.76.219 + address 77.68.77.90 + address 77.68.76.107 + address 77.68.76.26 + address 77.68.76.211 + address 77.68.76.19 + address 77.68.77.231 + address 77.68.76.254 + address 77.68.77.251 + address 77.68.77.74 + address 77.68.77.192 + address 77.68.76.253 + address 77.68.77.214 + address 77.68.76.92 + address 77.68.76.250 + address 77.68.77.215 + address 77.68.76.165 + address 77.68.77.254 + address 77.68.76.120 + address 77.68.76.228 + address 77.68.77.157 + address 77.68.77.205 + address 77.68.76.138 + address 77.68.77.102 + address 77.68.76.181 + address 77.68.76.139 + address 77.68.76.243 + address 77.68.76.244 + address 77.68.76.114 + address 77.68.77.72 + address 77.68.77.161 + address 77.68.77.38 + address 77.68.77.62 + address 77.68.92.186 + address 77.68.91.195 + address 77.68.23.35 + address 77.68.84.155 + address 77.68.17.26 + address 77.68.76.96 + address 77.68.28.145 + address 77.68.76.48 + address 109.228.56.185 + address 77.68.84.147 + address 77.68.23.64 + address 77.68.26.166 + address 77.68.29.178 + address 77.68.12.195 + address 77.68.21.78 + address 77.68.5.166 + address 77.68.5.187 + address 77.68.4.111 + address 77.68.4.22 + address 77.68.7.227 + address 77.68.4.24 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.5.241 + address 77.68.7.222 + address 77.68.4.39 + address 77.68.4.25 + address 77.68.7.160 + address 77.68.27.211 + address 77.68.89.183 + address 77.68.24.59 + address 77.68.7.114 + address 77.68.75.113 + address 77.68.81.44 + address 77.68.90.106 + address 77.68.94.181 + address 77.68.30.164 + address 77.68.30.133 + address 77.68.7.67 + address 77.68.77.174 + address 77.68.27.54 + address 77.68.4.136 + address 77.68.72.202 + address 77.68.112.83 + address 77.68.85.172 + address 77.68.23.158 + address 77.68.112.75 + address 77.68.24.112 + address 77.68.112.213 + address 77.68.72.254 + address 77.68.20.161 + address 77.68.26.216 + address 77.68.112.184 + address 77.68.79.82 + address 77.68.27.57 + address 77.68.20.231 + address 77.68.118.17 + address 77.68.118.120 + address 77.68.117.51 + address 77.68.118.102 + address 77.68.116.119 + address 77.68.117.45 + address 77.68.116.220 + address 77.68.116.232 + address 77.68.117.222 + address 77.68.118.15 + address 77.68.116.221 + address 77.68.116.183 + address 77.68.119.14 + address 77.68.112.91 + address 77.68.117.202 + address 77.68.118.104 + address 77.68.7.172 + address 77.68.83.41 + address 77.68.15.95 + address 77.68.4.57 + address 77.68.85.27 + address 77.68.86.40 + address 77.68.88.164 + address 109.228.56.26 + address 77.68.7.123 + address 77.68.112.248 + address 109.228.60.215 + address 109.228.55.82 + address 77.68.7.186 + address 77.68.6.210 + address 77.68.77.238 + address 77.68.10.142 + address 77.68.31.144 + address 77.68.93.246 + address 77.68.121.127 + address 77.68.121.94 + address 77.68.120.241 + address 77.68.121.106 + address 77.68.122.195 + address 77.68.122.89 + address 77.68.120.146 + address 77.68.120.249 + address 77.68.122.241 + address 77.68.119.92 + address 77.68.120.26 + address 77.68.81.141 + address 77.68.79.206 + address 77.68.116.52 + address 77.68.88.100 + address 77.68.6.105 + address 77.68.78.229 + address 77.68.6.32 + address 77.68.10.170 + address 77.68.76.229 + address 77.68.95.42 + address 77.68.28.207 + address 77.68.17.186 + address 77.68.4.252 + address 77.68.24.220 + address 77.68.2.215 + address 77.68.91.128 + address 77.68.22.146 + address 77.68.23.112 + address 77.68.75.245 + address 77.68.125.218 + address 77.68.125.32 + address 77.68.12.250 + address 109.228.37.174 + address 77.68.127.151 + address 109.228.37.114 + address 109.228.36.229 + address 109.228.37.240 + address 109.228.61.31 + address 109.228.35.110 + address 109.228.39.157 + address 109.228.39.249 + address 109.228.38.171 + address 109.228.40.226 + address 109.228.40.207 + address 109.228.40.247 + address 77.68.126.51 + address 77.68.117.214 + address 77.68.113.117 + address 77.68.117.142 + address 77.68.17.200 + address 77.68.4.242 + address 77.68.86.148 + address 109.228.39.151 + address 109.228.40.194 + address 77.68.114.183 + address 77.68.90.132 + address 77.68.16.247 + address 77.68.6.110 + address 109.228.36.37 + address 77.68.127.172 + address 77.68.14.88 + address 77.68.120.229 + address 213.171.212.203 + address 213.171.213.41 + address 213.171.213.175 + address 213.171.213.97 + address 213.171.212.171 + address 213.171.212.89 + address 213.171.214.96 + address 213.171.212.172 + address 213.171.215.252 + address 213.171.213.242 + address 213.171.213.31 + address 213.171.212.71 + address 213.171.208.58 + address 77.68.25.130 + address 213.171.215.184 + address 77.68.13.76 + address 109.228.56.242 + address 77.68.25.146 + address 109.228.46.81 + address 77.68.77.69 + address 213.171.210.19 + address 77.68.120.45 + address 77.68.116.36 + address 213.171.211.128 + address 77.68.25.124 + address 109.228.48.249 + address 213.171.210.59 + address 213.171.215.43 + address 109.228.40.195 + address 109.228.52.186 + address 77.68.113.164 + address 77.68.114.93 + address 77.68.75.253 + address 109.228.53.243 + address 109.228.36.194 + address 77.68.28.147 + address 77.68.123.250 + address 185.132.36.24 + address 185.132.39.129 + address 185.132.36.142 + address 185.132.39.68 + address 185.132.36.17 + address 185.132.36.148 + address 185.132.37.101 + address 185.132.39.44 + address 185.132.39.37 + address 185.132.37.102 + address 185.132.38.142 + address 185.132.38.114 + address 185.132.38.95 + address 185.132.37.83 + address 185.132.36.7 + address 109.228.40.222 + address 77.68.119.188 + address 77.68.74.85 + address 77.68.91.22 + address 213.171.212.136 + address 185.132.38.216 + address 77.68.120.31 + address 77.68.95.212 + address 109.228.42.232 + address 77.68.13.137 + address 77.68.85.73 + address 77.68.85.115 + address 109.228.36.174 + address 77.68.9.186 + address 77.68.27.18 + address 77.68.27.27 + address 77.68.27.28 + address 77.68.3.80 + address 77.68.3.121 + address 77.68.3.144 + address 77.68.3.161 + address 77.68.3.194 + address 77.68.3.247 + address 77.68.28.139 + address 77.68.81.218 + address 77.68.93.125 + address 77.68.74.39 + address 77.68.78.73 + address 77.68.5.95 + address 77.68.74.152 + address 77.68.87.212 + address 77.68.3.52 + address 77.68.114.136 + address 77.68.125.60 + address 213.171.214.167 + address 77.68.114.234 + address 213.171.213.42 + address 109.228.59.247 + address 185.132.39.99 + address 185.132.39.145 + address 109.228.35.84 + address 185.132.36.60 + address 185.132.40.11 + address 185.132.39.219 + address 77.68.26.221 + address 185.132.40.56 + address 77.68.117.29 + address 185.132.40.90 + address 109.228.38.201 + address 185.132.40.244 + address 77.68.11.140 + address 213.171.210.155 + address 185.132.37.23 + address 213.171.214.234 + address 77.68.77.29 + address 77.68.20.217 + address 185.132.40.152 + address 77.68.9.75 + address 213.171.210.177 + address 185.132.41.72 + address 185.132.41.73 + address 77.68.5.155 + address 185.132.43.6 + address 77.68.75.45 + address 109.228.46.196 + address 185.132.43.28 + address 77.68.89.72 + address 185.132.43.98 + address 77.68.76.176 + address 185.132.43.164 + address 185.132.43.157 + address 77.68.6.119 + address 77.68.92.92 + address 77.68.10.152 + address 77.68.73.73 + address 77.68.32.43 + address 185.132.38.248 + address 77.68.120.218 + address 77.68.32.31 + address 77.68.32.254 + address 77.68.32.118 + address 77.68.82.157 + address 77.68.121.119 + address 77.68.74.209 + address 77.68.33.68 + address 77.68.24.172 + address 77.68.33.197 + address 77.68.33.48 + address 77.68.34.26 + address 77.68.34.28 + address 77.68.79.89 + address 77.68.76.137 + address 77.68.33.216 + address 77.68.32.83 + address 77.68.32.86 + address 77.68.32.89 + address 77.68.34.138 + address 77.68.34.139 + address 77.68.123.177 + address 77.68.35.116 + address 77.68.33.171 + address 213.171.208.40 + address 77.68.118.86 + address 77.68.48.81 + address 77.68.48.89 + address 77.68.48.105 + address 77.68.85.18 + address 77.68.26.228 + address 77.68.49.4 + address 77.68.80.26 + address 77.68.80.97 + address 77.68.126.101 + address 77.68.126.14 + address 77.68.49.12 + address 77.68.117.173 + address 77.68.8.144 + address 77.68.82.147 + address 77.68.24.134 + address 77.68.112.167 + address 77.68.49.126 + address 77.68.49.178 + address 77.68.50.91 + address 77.68.50.90 + address 77.68.24.63 + address 109.228.37.187 + address 77.68.50.193 + address 77.68.50.198 + address 77.68.50.142 + address 77.68.114.237 + address 77.68.115.17 + address 77.68.49.159 + address 77.68.49.160 + address 213.171.208.176 + address 77.68.116.84 + address 77.68.126.160 + address 185.132.36.56 + address 77.68.49.161 + address 77.68.34.50 + address 185.132.41.240 + address 77.68.51.214 + address 77.68.51.202 + address 185.132.37.133 + address 77.68.77.42 + address 77.68.100.132 + address 77.68.100.134 + address 77.68.100.150 + address 185.132.41.148 + address 77.68.101.64 + address 213.171.210.25 + address 77.68.101.124 + address 77.68.101.125 + address 77.68.89.247 + address 185.132.39.109 + address 77.68.100.167 + address 77.68.5.125 + address 77.68.4.80 + address 77.68.49.152 + address 77.68.12.45 + address 77.68.4.180 + address 213.171.214.102 + address 77.68.126.22 + address 77.68.114.205 + address 109.228.36.119 + address 213.171.212.90 + address 77.68.33.37 + address 185.132.43.71 + address 185.132.43.113 + address 77.68.48.202 + address 185.132.40.166 + address 77.68.112.90 + address 77.68.112.175 + address 77.68.103.19 + address 77.68.103.120 + address 77.68.33.24 + address 77.68.103.147 + address 109.228.47.223 + address 109.228.58.134 + address 109.228.56.97 + address 77.68.31.96 + address 77.68.103.227 + address 88.208.196.91 + address 88.208.196.92 + address 88.208.196.154 + address 88.208.197.10 + address 77.68.87.164 + address 77.68.93.164 + address 185.132.37.47 + address 77.68.75.64 + address 88.208.197.118 + address 88.208.197.135 + address 88.208.197.150 + address 88.208.197.155 + address 88.208.197.160 + address 88.208.197.60 + address 109.228.37.10 + address 88.208.215.61 + address 77.68.102.129 + address 88.208.196.123 + address 109.228.36.79 + address 185.132.38.182 + address 88.208.215.62 + address 88.208.215.157 + address 88.208.198.251 + address 88.208.215.19 + address 88.208.198.39 + address 109.228.38.117 + address 77.68.29.65 + address 88.208.215.121 + address 77.68.115.142 + address 77.68.76.108 + address 88.208.198.64 + address 88.208.198.66 + address 77.68.3.61 + address 88.208.198.92 + address 77.68.74.232 + address 77.68.118.88 + address 77.68.100.77 + address 77.68.48.14 + address 88.208.198.69 + address 88.208.197.23 + address 88.208.199.249 + address 213.171.212.114 + address 109.228.39.41 + address 88.208.199.141 + address 77.68.21.171 + address 88.208.199.233 + address 88.208.212.31 + address 77.68.102.5 + address 88.208.212.94 + address 109.228.61.37 + address 88.208.199.46 + address 77.68.78.113 + address 88.208.212.182 + address 88.208.212.188 + address 185.132.40.124 + address 213.171.209.217 + address 77.68.103.56 + address 88.208.197.208 + address 88.208.197.129 + } + address-group CMK_SATELLITES { + address 82.223.144.252 + address 109.228.63.67 + address 109.228.63.66 + address 82.223.200.61 + address 195.20.253.14 + address 217.72.206.27 + } + address-group DHCP_SERVERS { + address 10.255.241.13 + address 10.255.241.14 + address 10.255.242.13 + address 10.255.242.14 + address 10.255.243.13 + address 10.255.243.14 + address 10.255.244.13 + address 10.255.244.14 + address 10.255.245.13 + address 10.255.245.14 + address 10.255.246.13 + address 10.255.246.14 + address 10.255.247.13 + address 10.255.247.14 + address 10.255.248.13 + address 10.255.248.14 + address 10.255.249.13 + address 10.255.249.14 + address 77.68.76.14 + address 77.68.77.14 + address 77.68.76.13 + address 77.68.77.13 + } + address-group DNSCACHE_SERVERS { + address 10.255.255.4 + address 10.255.255.5 + address 77.68.76.12 + address 77.68.77.12 + } + address-group DT_BLOCKED { + address 172.16.255.254 + } + address-group DT_FW0A5C4_1 { + address 185.132.40.56 + } + address-group DT_FW0B352_1 { + address 77.68.77.238 + } + address-group DT_FW0BB22_1 { + address 77.68.16.247 + } + address-group DT_FW0BD92_3 { + address 109.228.36.79 + } + address-group DT_FW0C2E6_4 { + address 77.68.76.110 + } + address-group DT_FW0C8E1_1 { + address 77.68.77.103 + } + address-group DT_FW0C25B_1 { + address 77.68.86.148 + } + address-group DT_FW00D98_1 { + address 77.68.76.88 + } + address-group DT_FW0E2EE_1 { + address 213.171.211.128 + } + address-group DT_FW0E383_9 { + address 77.68.77.114 + } + address-group DT_FW0EA3F_1 { + address 77.68.49.159 + } + address-group DT_FW1ACD9_2 { + address 77.68.76.108 + } + address-group DT_FW1C8F2_1 { + address 185.132.37.83 + } + address-group DT_FW1CB16_1 { + address 77.68.29.178 + } + address-group DT_FW1CC15_2 { + address 77.68.77.248 + } + address-group DT_FW1D511_2 { + address 213.171.213.175 + } + address-group DT_FW1F3D0_6 { + address 77.68.76.250 + } + address-group DT_FW1F126_1 { + address 77.68.76.137 + } + address-group DT_FW1FA8E_1 { + address 185.132.37.101 + } + address-group DT_FW1FA9E_1 { + address 77.68.118.104 + } + address-group DT_FW2ACFF_1 { + address 77.68.24.220 + } + address-group DT_FW2B4BA_1 { + address 77.68.33.68 + } + address-group DT_FW2B279_4 { + address 77.68.77.204 + } + address-group DT_FW2BB8D_1 { + address 77.68.77.181 + } + address-group DT_FW2BF20_3 { + address 77.68.76.187 + } + address-group DT_FW2C5AE_1 { + address 77.68.76.228 + } + address-group DT_FW2E8D4_1 { + address 77.68.77.249 + } + address-group DT_FW2E060_1 { + address 77.68.77.215 + } + address-group DT_FW2ED4D_2 { + address 109.228.39.151 + } + address-group DT_FW2EF2C_1 { + address 77.68.11.140 + } + address-group DT_FW2F868_6 { + address 77.68.76.254 + } + address-group DT_FW2FB61_1 { + address 109.228.38.117 + } + address-group DT_FW3A12F_1 { + address 77.68.5.95 + } + address-group DT_FW3AD6F_1 { + address 77.68.120.241 + } + address-group DT_FW03B35_1 { + address 77.68.125.60 + } + address-group DT_FW3B068_2 { + address 77.68.77.63 + } + address-group DT_FW3CAAB_1 { + address 77.68.76.234 + } + address-group DT_FW3DBF8_9 { + address 77.68.76.198 + } + address-group DT_FW3EBC8_1 { + address 77.68.13.76 + } + address-group DT_FW03F2E_1 { + address 77.68.102.5 + } + address-group DT_FW3F465_1 { + address 109.228.36.119 + } + address-group DT_FW4AE7D_1 { + address 77.68.76.60 + } + address-group DT_FW4C136_1 { + address 77.68.76.50 + } + address-group DT_FW4D3E6_1 { + address 77.68.100.77 + } + address-group DT_FW4DB0A_1 { + address 77.68.49.161 + } + address-group DT_FW4E314_1 { + address 109.228.40.222 + } + address-group DT_FW4E399_1 { + address 213.171.214.96 + } + address-group DT_FW4F5EE_10 { + address 77.68.116.220 + } + address-group DT_FW4F81F_4 { + address 77.68.77.43 + } + address-group DT_FW5A5D7_3 { + address 77.68.77.205 + } + address-group DT_FW5A77C_16 { + address 77.68.76.202 + } + address-group DT_FW5A521_3 { + address 77.68.79.89 + } + address-group DT_FW05AD0_2 { + address 77.68.77.72 + } + address-group DT_FW5AE10_1 { + address 109.228.37.114 + } + address-group DT_FW5CBB2_1 { + address 77.68.77.150 + } + address-group DT_FW5D0FA_1 { + address 185.132.43.157 + } + address-group DT_FW6A684_1 { + address 77.68.116.119 + } + address-group DT_FW6B9B9_1 { + address 185.132.41.72 + } + address-group DT_FW6B39D_1 { + address 77.68.4.111 + address 77.68.77.174 + } + address-group DT_FW6C992_1 { + address 77.68.85.27 + } + address-group DT_FW6CD7E_2 { + address 77.68.76.148 + } + address-group DT_FW6D0CD_1 { + address 77.68.76.241 + } + address-group DT_FW6ECA4_1 { + address 77.68.117.51 + } + address-group DT_FW6EFD7_1 { + address 77.68.84.147 + } + address-group DT_FW6F539_1 { + address 77.68.76.217 + } + address-group DT_FW7A9B0_9 { + address 77.68.76.47 + } + address-group DT_FW7C4D9_14 { + address 109.228.36.37 + } + address-group DT_FW7DAE2_3 { + address 185.132.38.216 + } + address-group DT_FW7F28A_1 { + address 77.68.76.31 + } + address-group DT_FW8A3FC_3 { + address 77.68.77.132 + address 77.68.76.185 + address 77.68.77.90 + } + address-group DT_FW8A49A_1 { + address 77.68.77.85 + } + address-group DT_FW8A57A_1 { + address 77.68.77.222 + address 77.68.112.83 + } + address-group DT_FW8AFF1_7 { + address 77.68.76.118 + } + address-group DT_FW8B21D_1 { + address 77.68.23.64 + } + address-group DT_FW8C72E_1 { + address 77.68.27.54 + } + address-group DT_FW8C927_1 { + address 77.68.7.160 + } + address-group DT_FW8EA04_1 { + address 77.68.20.161 + } + address-group DT_FW8ECF4_1 { + address 77.68.2.215 + } + address-group DT_FW9B6FB_1 { + address 77.68.4.242 + } + address-group DT_FW9C682_3 { + address 213.171.212.203 + } + address-group DT_FW9D5C7_1 { + address 77.68.115.17 + } + address-group DT_FW9E550_1 { + address 213.171.212.71 + } + address-group DT_FW9EEDD_1 { + address 77.68.4.80 + address 77.68.49.152 + } + address-group DT_FW10C3D_19 { + address 77.68.25.124 + } + address-group DT_FW10FEE_1 { + address 77.68.122.89 + } + address-group DT_FW12C32_1 { + address 77.68.4.25 + address 77.68.7.114 + } + address-group DT_FW013EF_2 { + address 77.68.77.26 + } + address-group DT_FW15C99_6 { + address 77.68.114.237 + } + address-group DT_FW18E6E_3 { + address 77.68.76.112 + } + address-group DT_FW21A75_2 { + address 88.208.198.66 + } + address-group DT_FW24AB7_1 { + address 213.171.213.242 + } + address-group DT_FW26F0A_1 { + address 77.68.78.73 + } + address-group DT_FW27A8F_1 { + address 77.68.76.219 + } + address-group DT_FW028C0_2 { + address 77.68.26.221 + } + address-group DT_FW28EC8_1 { + address 77.68.76.93 + } + address-group DT_FW30D21_1 { + address 77.68.95.42 + } + address-group DT_FW32EFF_16 { + address 77.68.118.120 + } + address-group DT_FW32EFF_25 { + address 77.68.27.211 + } + address-group DT_FW32EFF_49 { + address 109.228.37.187 + } + address-group DT_FW34C91_3 { + address 77.68.76.142 + } + address-group DT_FW35F7B_1 { + address 77.68.30.164 + } + address-group DT_FW37E59_5 { + address 77.68.76.37 + } + address-group DT_FW40AE4_1 { + address 77.68.79.206 + } + address-group DT_FW42BC7_1 { + address 77.68.76.95 + } + address-group DT_FW44BF9_1 { + address 77.68.77.200 + } + address-group DT_FW45BEB_1 { + address 77.68.75.245 + } + address-group DT_FW45F3D_1 { + address 109.228.40.247 + } + address-group DT_FW45F87_1 { + address 77.68.77.207 + } + address-group DT_FW46F4A_1 { + address 88.208.197.135 + } + address-group DT_FW48A55_2 { + address 109.228.39.157 + } + address-group DT_FW49C3D_4 { + address 77.68.76.149 + } + address-group DT_FW49C3D_6 { + address 77.68.76.160 + } + address-group DT_FW050AC_1 { + address 77.68.77.214 + } + address-group DT_FW52F6F_1 { + address 77.68.82.147 + } + address-group DT_FW53C72_1 { + address 88.208.197.118 + } + address-group DT_FW58C69_4 { + address 77.68.76.141 + } + address-group DT_FW59F39_1 { + address 77.68.87.212 + } + address-group DT_FW60FD6_5 { + address 77.68.92.92 + } + address-group DT_FW69D6D_2 { + address 77.68.77.221 + } + address-group DT_FW72F37_1 { + address 77.68.77.100 + } + address-group DT_FW73A64_1 { + address 77.68.118.15 + } + address-group DT_FW75CA4_6 { + address 77.68.4.22 + } + address-group DT_FW85A7C_1 { + address 77.68.6.210 + } + address-group DT_FW85E02_11 { + address 77.68.77.233 + } + address-group DT_FW90AE3_1 { + address 77.68.88.100 + } + address-group DT_FW91B7A_1 { + address 77.68.76.40 + } + address-group DT_FW138F8_1 { + address 77.68.50.193 + } + address-group DT_FW0192C_1 { + address 185.132.39.68 + } + address-group DT_FW197DB_1 { + address 77.68.77.240 + } + address-group DT_FW210E2_8 { + address 77.68.94.181 + } + address-group DT_FW274FD_1 { + address 185.132.36.24 + } + address-group DT_FW310C6_3 { + address 88.208.198.39 + } + address-group DT_FW364CF_1 { + address 77.68.76.203 + address 77.68.77.97 + } + address-group DT_FW406AB_1 { + address 109.228.47.223 + } + address-group DT_FW444AF_1 { + address 185.132.37.102 + } + address-group DT_FW481D7_1 { + address 77.68.76.243 + } + address-group DT_FW539FB_1 { + address 77.68.21.171 + } + address-group DT_FW578BE_1 { + address 109.228.56.185 + } + address-group DT_FW597A6_1 { + address 77.68.5.125 + address 88.208.196.123 + address 88.208.212.31 + } + address-group DT_FW608FA_1 { + address 77.68.74.232 + } + address-group DT_FW633DD_1 { + address 77.68.121.119 + } + address-group DT_FW672AB_1 { + address 213.171.213.41 + } + address-group DT_FW0745F_5 { + address 77.68.117.222 + } + address-group DT_FW748B7_1 { + address 77.68.120.249 + } + address-group DT_FW825C8_19 { + address 77.68.76.111 + address 77.68.76.42 + } + address-group DT_FW825C8_24 { + address 77.68.77.120 + address 77.68.76.183 + } + address-group DT_FW826BA_3 { + address 77.68.77.152 + } + address-group DT_FW856FA_1 { + address 77.68.77.151 + } + address-group DT_FW883EB_1 { + address 77.68.76.152 + } + address-group DT_FW930F3_1 { + address 77.68.85.73 + } + address-group DT_FW930F3_3 { + address 77.68.114.234 + } + address-group DT_FW934AE_1 { + address 77.68.5.166 + } + address-group DT_FW0937A_1 { + address 77.68.6.119 + } + address-group DT_FW0952B_1 { + address 77.68.93.125 + } + address-group DT_FW996B4_2 { + address 77.68.76.157 + } + address-group DT_FW1208C_1 { + address 77.68.77.33 + } + address-group DT_FW1226C_3 { + address 77.68.117.45 + } + address-group DT_FW1271A_2 { + address 77.68.76.102 + } + address-group DT_FW2379F_14 { + address 213.171.212.89 + address 77.68.76.44 + address 77.68.77.239 + address 213.171.212.114 + address 77.68.103.56 + } + address-group DT_FW4293B_1 { + address 77.68.76.57 + } + address-group DT_FW4513E_1 { + address 77.68.77.75 + } + address-group DT_FW4735F_1 { + address 77.68.77.74 + } + address-group DT_FW05064_1 { + address 213.171.210.19 + } + address-group DT_FW05339_1 { + address 185.132.40.152 + } + address-group DT_FW5658C_1 { + address 77.68.77.185 + } + address-group DT_FW5858F_1 { + address 77.68.121.127 + } + address-group DT_FW06176_1 { + address 77.68.77.38 + } + address-group DT_FW6187E_1 { + address 77.68.103.147 + } + address-group DT_FW6863A_4 { + address 77.68.7.222 + } + address-group DT_FW6906B_1 { + address 185.132.43.28 + } + address-group DT_FW06940_3 { + address 77.68.33.216 + address 77.68.33.37 + address 77.68.50.90 + } + address-group DT_FW7648D_1 { + address 77.68.76.77 + } + address-group DT_FW08061_1 { + address 77.68.76.45 + } + address-group DT_FW8428B_1 { + address 77.68.33.24 + } + address-group DT_FW8871B_1 { + address 77.68.78.113 + } + address-group DT_FW11082_1 { + address 77.68.113.117 + } + address-group DT_FW16375_5 { + address 77.68.77.171 + } + address-group DT_FW19987_4 { + address 77.68.77.54 + } + address-group DT_FW20449_2 { + address 77.68.126.101 + } + address-group DT_FW25843_1 { + address 77.68.24.59 + } + address-group DT_FW26846_1 { + address 88.208.197.10 + } + address-group DT_FW27947_1 { + address 77.68.77.102 + } + address-group DT_FW27949_2 { + address 77.68.117.214 + } + address-group DT_FW28892_1 { + address 77.68.77.144 + } + address-group DT_FW31525_6 { + address 77.68.77.46 + } + address-group DT_FW36425_1 { + address 77.68.119.14 + } + address-group DT_FW40416_1 { + address 77.68.121.94 + } + address-group DT_FW42661_3 { + address 77.68.77.202 + } + address-group DT_FW44217_2 { + address 77.68.89.247 + } + address-group DT_FW45000_1 { + address 77.68.24.172 + } + address-group DT_FW48814_3 { + address 77.68.77.219 + } + address-group DT_FW49897_1 { + address 185.132.36.7 + } + address-group DT_FW56335_2 { + address 88.208.198.92 + } + address-group DT_FW56496_1 { + address 77.68.51.202 + address 77.68.101.64 + } + address-group DT_FW62858_12 { + address 77.68.77.145 + } + address-group DT_FW63230_1 { + address 77.68.76.220 + } + address-group DT_FW66347_1 { + address 77.68.92.186 + } + address-group DT_FW73215_1 { + address 213.171.209.217 + } + address-group DT_FW73573_1 { + address 77.68.76.249 + } + address-group DT_FW73573_2 { + address 77.68.77.62 + } + address-group DT_FW78137_1 { + address 77.68.34.50 + } + address-group DT_FW81138_1 { + address 77.68.77.59 + } + address-group DT_FW81286_1 { + address 77.68.77.243 + } + address-group DT_FW85040_1 { + address 77.68.5.187 + } + address-group DT_FW85619_1 { + address 77.68.127.172 + } + address-group DT_FW89619_1 { + address 77.68.76.253 + } + address-group DT_FW98818_1 { + address 88.208.197.129 + } + address-group DT_FWA0AA0_1 { + address 77.68.113.164 + } + address-group DT_FWA0B7F_1 { + address 185.132.39.44 + } + address-group DT_FWA2FF8_4 { + address 77.68.76.231 + } + address-group DT_FWA3EA3_1 { + address 77.68.77.42 + } + address-group DT_FWA4BC8_1 { + address 77.68.112.75 + } + address-group DT_FWA5D67_1 { + address 185.132.37.133 + } + address-group DT_FWA7A50_1 { + address 77.68.27.57 + address 77.68.118.102 + } + address-group DT_FWA69A0_1 { + address 213.171.212.90 + } + address-group DT_FWA076E_1 { + address 77.68.76.19 + } + address-group DT_FWA83DF_1 { + address 77.68.7.123 + } + address-group DT_FWA86A4_1 { + address 109.228.56.97 + } + address-group DT_FWA86ED_101 { + address 77.68.85.172 + address 109.228.38.171 + address 88.208.199.233 + } + address-group DT_FWA373F_1 { + address 77.68.76.171 + } + address-group DT_FWA0531_1 { + address 213.171.215.252 + } + address-group DT_FWA884B_5 { + address 88.208.199.249 + } + address-group DT_FWA7625_1 { + address 213.171.215.43 + } + address-group DT_FWAA38E_1 { + address 77.68.93.164 + } + address-group DT_FWAB44B_1 { + address 185.132.37.47 + } + address-group DT_FWAE88B_1 { + address 77.68.125.218 + } + address-group DT_FWAF6E8_1 { + address 77.68.76.115 + } + address-group DT_FWAFF0A_1 { + address 77.68.91.195 + } + address-group DT_FWB2CD2_1 { + address 77.68.72.254 + } + address-group DT_FWB28B6_5 { + address 77.68.77.209 + } + address-group DT_FWB36A0_1 { + address 77.68.77.108 + } + address-group DT_FWB118A_1 { + address 77.68.48.14 + } + address-group DT_FWB4438_2 { + address 88.208.215.61 + } + address-group DT_FWB6101_1 { + address 88.208.215.62 + } + address-group DT_FWB9699_7 { + address 77.68.76.123 + } + address-group DT_FWB9699_11 { + address 77.68.77.165 + } + address-group DT_FWBB718_1 { + address 77.68.77.71 + } + address-group DT_FWBC8A6_1 { + address 77.68.112.175 + } + address-group DT_FWBC280_1 { + address 77.68.100.167 + } + address-group DT_FWBD9D0_1 { + address 77.68.120.31 + } + address-group DT_FWBE878_1 { + address 213.171.212.172 + } + address-group DT_FWBED52_1 { + address 77.68.112.213 + } + address-group DT_FWBF494_1 { + address 77.68.76.209 + } + address-group DT_FWBFC02_1 { + address 77.68.112.90 + } + address-group DT_FWBFDED_1 { + address 77.68.76.30 + } + address-group DT_FWC0CE0_1 { + address 77.68.112.184 + } + address-group DT_FWC1ACD_1 { + address 77.68.85.18 + } + address-group DT_FWC2D30_1 { + address 77.68.76.48 + } + address-group DT_FWC2EF2_1 { + address 77.68.17.200 + } + address-group DT_FWC2EF2_2 { + address 77.68.17.200 + } + address-group DT_FWC7D36_1 { + address 77.68.76.126 + } + address-group DT_FWC8E8E_1 { + address 77.68.28.207 + } + address-group DT_FWC32BE_1 { + address 77.68.117.173 + } + address-group DT_FWC37B9_1 { + address 77.68.28.139 + } + address-group DT_FWC055A_1 { + address 77.68.77.30 + } + address-group DT_FWC72E5_1 { + address 77.68.103.227 + } + address-group DT_FWC96A1_1 { + address 77.68.75.253 + } + address-group DT_FWC1315_1 { + address 77.68.4.57 + } + address-group DT_FWC3921_1 { + address 77.68.76.164 + } + address-group DT_FWC6301_1 { + address 77.68.34.26 + } + address-group DT_FWCA628_1 { + address 185.132.39.99 + } + address-group DT_FWCB0CF_7 { + address 77.68.77.163 + } + address-group DT_FWCB29D_1 { + address 88.208.197.23 + } + address-group DT_FWCC18F_2 { + address 77.68.76.59 + } + address-group DT_FWCD7CE_1 { + address 77.68.77.56 + } + address-group DT_FWCDBC7_1 { + address 77.68.77.141 + } + address-group DT_FWCDD8B_1 { + address 185.132.37.23 + } + address-group DT_FWCE020_1 { + address 77.68.48.202 + } + address-group DT_FWD0E22_4 { + address 77.68.77.99 + } + address-group DT_FWD4A27_1 { + address 77.68.76.244 + } + address-group DT_FWD7EAB_1 { + address 77.68.7.67 + } + address-group DT_FWD8DD1_2 { + address 213.171.210.155 + } + address-group DT_FWD42CF_1 { + address 185.132.38.114 + } + address-group DT_FWD56A2_1 { + address 213.171.213.31 + } + address-group DT_FWD61BF_1 { + address 88.208.199.46 + } + address-group DT_FWD338A_1 { + address 77.68.77.69 + } + address-group DT_FWD498E_1 { + address 109.228.39.41 + } + address-group DT_FWD2082_1 { + address 77.68.76.94 + } + address-group DT_FWD2440_1 { + address 77.68.114.136 + } + address-group DT_FWD3431_2 { + address 77.68.77.105 + } + address-group DT_FWD7382_1 { + address 185.132.40.11 + } + address-group DT_FWDA443_6 { + address 77.68.34.28 + } + address-group DT_FWDAA4F_1 { + address 77.68.76.124 + } + address-group DT_FWDAF47_1 { + address 77.68.23.35 + } + address-group DT_FWDCA36_3 { + address 77.68.77.81 + } + address-group DT_FWDD089_5 { + address 77.68.77.21 + } + address-group DT_FWDEDB9_1 { + address 77.68.22.146 + } + address-group DT_FWE2AB5_8 { + address 77.68.26.166 + } + address-group DT_FWE3E77_1 { + address 77.68.76.49 + } + address-group DT_FWE6AB2_1 { + address 185.132.40.166 + } + address-group DT_FWE9F7D_1 { + address 77.68.32.118 + } + address-group DT_FWE012D_1 { + address 77.68.77.190 + } + address-group DT_FWE30A1_4 { + address 77.68.33.48 + } + address-group DT_FWE32F2_8 { + address 77.68.82.157 + } + address-group DT_FWE47DA_1 { + address 77.68.91.128 + } + address-group DT_FWE57AD_1 { + address 109.228.56.26 + } + address-group DT_FWE928F_1 { + address 77.68.77.129 + } + address-group DT_FWE7180_1 { + address 77.68.123.177 + } + address-group DT_FWEAE53_1 { + address 77.68.26.216 + } + address-group DT_FWEB321_1 { + address 77.68.4.74 + } + address-group DT_FWECBFB_14 { + address 77.68.77.44 + } + address-group DT_FWEE03C_1 { + address 77.68.116.232 + } + address-group DT_FWEEC75_1 { + address 77.68.76.29 + } + address-group DT_FWEF92E_5 { + address 77.68.77.57 + } + address-group DT_FWEF92E_6 { + address 77.68.77.70 + } + address-group DT_FWEF92E_7 { + address 77.68.77.149 + } + address-group DT_FWF3A1B_1 { + address 109.228.52.186 + } + address-group DT_FWF7B68_1 { + address 77.68.77.231 + } + address-group DT_FWF7BFA_1 { + address 77.68.120.45 + } + address-group DT_FWF8E67_1 { + address 77.68.85.115 + } + address-group DT_FWF8F85_1 { + address 109.228.36.229 + } + address-group DT_FWF9C28_2 { + address 77.68.84.155 + } + address-group DT_FWF9C28_4 { + address 77.68.28.145 + } + address-group DT_FWF19FB_2 { + address 77.68.76.212 + } + address-group DT_FWF30BD_1 { + address 77.68.14.88 + } + address-group DT_FWF48EB_1 { + address 77.68.76.21 + } + address-group DT_FWF0221_1 { + address 185.132.36.60 + address 185.132.40.244 + } + address-group DT_FWF323F_1 { + address 185.132.39.109 + } + address-group DT_FWF699D_4 { + address 185.132.40.90 + } + address-group DT_FWF791C_1 { + address 77.68.90.132 + } + address-group DT_FWF879C_1 { + address 77.68.76.169 + } + address-group DT_FWF3574_1 { + address 77.68.76.191 + } + address-group DT_FWF4063_1 { + address 77.68.32.254 + } + address-group DT_FWFD9AF_9 { + address 77.68.77.24 + } + address-group DT_FWFDCC7_1 { + address 109.228.59.247 + } + address-group DT_FWFDD94_15 { + address 77.68.76.161 + } + address-group DT_FWFDE34_1 { + address 185.132.38.182 + } + address-group DT_FWFEF05_1 { + address 88.208.197.150 + } + address-group DT_H71F96 { + address 77.68.23.112 + } + address-group DT_SMTP_BLOCKED { + address 172.16.255.254 + address 77.68.77.209 + address 77.68.76.148 + address 77.68.77.211 + address 77.68.21.78 + address 77.68.77.247 + address 77.68.77.203 + address 77.68.77.68 + address 77.68.77.43 + address 77.68.77.165 + address 77.68.76.145 + address 77.68.76.239 + address 77.68.77.67 + address 77.68.76.177 + address 77.68.77.117 + address 77.68.76.50 + address 77.68.76.158 + address 77.68.76.22 + address 77.68.76.123 + address 77.68.76.251 + address 77.68.77.63 + address 77.68.7.186 + address 77.68.93.246 + address 77.68.4.252 + address 77.68.76.30 + address 77.68.76.77 + address 77.68.76.31 + address 77.68.77.248 + address 77.68.3.52 + address 77.68.76.88 + address 213.171.214.234 + address 185.132.39.219 + address 77.68.5.155 + address 77.68.80.97 + address 77.68.101.124 + address 77.68.76.111 + address 77.68.76.42 + address 77.68.77.120 + address 77.68.76.183 + address 88.208.197.160 + address 88.208.197.10 + address 77.68.76.250 + address 77.68.77.219 + address 77.68.77.152 + address 77.68.76.60 + } + address-group DT_VPN-2661 { + address 185.132.40.90 + } + address-group DT_VPN-3575 { + address 77.68.77.202 + } + address-group DT_VPN-6103 { + address 77.68.77.21 + } + address-group DT_VPN-7030 { + address 77.68.77.44 + } + address-group DT_VPN-7902 { + address 77.68.77.43 + } + address-group DT_VPN-8159 { + address 77.68.77.163 + } + address-group DT_VPN-8203 { + address 77.68.77.202 + } + address-group DT_VPN-8625 { + address 77.68.94.181 + } + address-group DT_VPN-9415 { + address 77.68.76.114 + } + address-group DT_VPN-9484 { + address 77.68.77.76 + address 77.68.76.120 + } + address-group DT_VPN-9727 { + address 185.132.40.90 + } + address-group DT_VPN-9749 { + address 213.171.212.89 + address 77.68.76.44 + address 77.68.77.239 + address 213.171.212.114 + address 77.68.103.56 + } + address-group DT_VPN-9765 { + address 77.68.76.50 + } + address-group DT_VPN-10131 { + address 77.68.76.110 + } + address-group DT_VPN-11083 { + address 213.171.212.89 + address 77.68.76.44 + address 77.68.77.239 + address 213.171.212.114 + address 77.68.103.56 + } + address-group DT_VPN-11913 { + address 77.68.76.60 + } + address-group DT_VPN-12870 { + address 77.68.77.163 + } + address-group DT_VPN-12899 { + address 77.68.77.95 + } + address-group DT_VPN-13261 { + address 77.68.77.76 + address 77.68.76.120 + } + address-group DT_VPN-13983 { + address 77.68.3.52 + } + address-group DT_VPN-14649 { + address 77.68.76.161 + } + address-group DT_VPN-14657 { + address 77.68.76.161 + } + address-group DT_VPN-14658 { + address 77.68.76.161 + } + address-group DT_VPN-14673 { + address 77.68.76.161 + } + address-group DT_VPN-15625 { + address 77.68.77.44 + } + address-group DT_VPN-15950 { + address 77.68.101.124 + } + address-group DT_VPN-15951 { + address 77.68.118.120 + address 77.68.27.211 + address 109.228.37.187 + } + address-group DT_VPN-15960 { + address 77.68.101.124 + } + address-group DT_VPN-16402 { + address 109.228.39.151 + } + address-group DT_VPN-16450 { + address 77.68.77.163 + } + address-group DT_VPN-17207 { + address 77.68.77.163 + } + address-group DT_VPN-17558 { + address 77.68.77.163 + } + address-group DT_VPN-18646 { + address 77.68.77.163 + } + address-group DT_VPN-18647 { + address 77.68.77.163 + } + address-group DT_VPN-18830 { + address 77.68.118.120 + address 77.68.27.211 + address 109.228.37.187 + } + address-group DT_VPN-19135 { + address 109.228.39.151 + } + address-group DT_VPN-19474 { + address 77.68.118.120 + address 77.68.27.211 + address 109.228.37.187 + } + address-group DT_VPN-19807 { + address 77.68.76.198 + } + address-group DT_VPN-19992 { + address 77.68.25.124 + } + address-group DT_VPN-20306 { + address 77.68.77.248 + } + address-group DT_VPN-21673 { + address 77.68.15.95 + address 77.68.75.64 + } + address-group DT_VPN-21821 { + address 77.68.15.95 + address 77.68.75.64 + } + address-group DT_VPN-21822 { + address 77.68.15.95 + address 77.68.75.64 + } + address-group DT_VPN-21876 { + address 77.68.77.163 + } + address-group DT_VPN-21982 { + address 77.68.15.95 + address 77.68.75.64 + } + address-group DT_VPN-23209 { + address 77.68.77.24 + } + address-group DT_VPN-23729 { + address 77.68.118.120 + address 77.68.27.211 + address 109.228.37.187 + } + address-group DT_VPN-23733 { + address 77.68.118.120 + address 77.68.27.211 + address 109.228.37.187 + } + address-group DT_VPN-23734 { + address 77.68.118.120 + address 77.68.27.211 + address 109.228.37.187 + } + address-group DT_VPN-23738 { + address 77.68.118.120 + address 77.68.27.211 + address 109.228.37.187 + } + address-group DT_VPN-23946 { + address 77.68.77.44 + } + address-group DT_VPN-24398 { + address 77.68.76.118 + } + address-group DT_VPN-24589 { + address 77.68.76.118 + } + address-group DT_VPN-24591 { + address 77.68.76.118 + } + address-group DT_VPN-24592 { + address 77.68.76.118 + } + address-group DT_VPN-24593 { + address 77.68.76.118 + } + address-group DT_VPN-24594 { + address 77.68.76.118 + } + address-group DT_VPN-24595 { + address 77.68.76.118 + } + address-group DT_VPN-25822 { + address 77.68.15.95 + address 77.68.75.64 + } + address-group DT_VPN-26124 { + address 77.68.77.163 + } + address-group DT_VPN-26157 { + address 77.68.77.205 + } + address-group DT_VPN-26772 { + address 185.132.40.90 + } + address-group DT_VPN-28031 { + address 77.68.77.44 + } + address-group DT_VPN-28484 { + address 77.68.118.120 + address 77.68.27.211 + address 109.228.37.187 + } + address-group DT_VPN-28515 { + address 77.68.82.157 + } + address-group DT_VPN-29631 { + address 77.68.77.44 + } + address-group DT_VPN-30261 { + address 77.68.77.163 + } + address-group DT_VPN-30262 { + address 77.68.77.163 + } + address-group DT_VPN-30679 { + address 77.68.77.163 + } + address-group DT_VPN-30791 { + address 77.68.118.120 + address 77.68.27.211 + address 109.228.37.187 + } + address-group DT_VPN-31002 { + address 109.228.36.119 + } + address-group DT_VPN-31301 { + address 88.208.197.10 + } + address-group DT_VPN-32528 { + address 77.68.76.118 + } + address-group DT_VPN-33204 { + address 77.68.77.163 + } + address-group DT_VPN-34006 { + address 77.68.33.216 + address 77.68.33.37 + address 77.68.50.90 + } + address-group DT_VPN-34122 { + address 77.68.114.237 + } + address-group DT_VPN-34309 { + address 77.68.77.44 + } + address-group DT_VPN-34501 { + address 77.68.50.142 + } + address-group DT_VPN-34583 { + address 77.68.77.145 + } + address-group G-ALL_OPEN { + address 172.16.255.254 + address 77.68.76.208 + address 77.68.77.251 + address 109.228.36.174 + address 77.68.89.72 + address 77.68.77.29 + address 185.132.43.6 + address 109.228.46.196 + address 185.132.43.98 + address 185.132.41.148 + address 77.68.49.126 + address 77.68.49.178 + address 77.68.116.84 + address 185.132.36.56 + address 77.68.126.160 + address 213.171.208.176 + address 88.208.197.155 + address 88.208.198.69 + address 77.68.29.65 + } + address-group G-ICMP { + address 172.16.255.254 + address 77.68.76.141 + address 77.68.76.16 + address 77.68.76.22 + address 77.68.76.241 + address 77.68.77.128 + address 77.68.77.130 + address 77.68.77.16 + address 77.68.77.201 + address 77.68.77.22 + address 77.68.77.71 + address 77.68.76.254 + address 77.68.5.187 + address 77.68.94.181 + address 77.68.76.243 + address 77.68.92.186 + address 77.68.76.23 + address 77.68.26.216 + address 77.68.76.157 + address 77.68.76.102 + address 77.68.76.169 + address 77.68.76.30 + address 109.228.39.157 + address 77.68.76.77 + address 77.68.7.67 + address 109.228.55.82 + address 77.68.95.212 + address 77.68.85.73 + address 77.68.117.222 + address 77.68.125.60 + address 185.132.43.157 + address 77.68.114.136 + address 77.68.77.105 + address 77.68.33.197 + address 77.68.23.64 + address 77.68.112.184 + address 77.68.49.161 + address 77.68.76.191 + address 109.228.56.97 + address 185.132.37.101 + address 77.68.76.112 + address 77.68.117.173 + address 77.68.33.216 + address 77.68.33.37 + address 77.68.50.90 + address 77.68.16.247 + address 77.68.76.212 + address 77.68.77.185 + address 77.68.77.238 + } + address-group G-20-TCP { + address 172.16.255.254 + address 77.68.76.80 + address 77.68.77.253 + address 77.68.86.148 + address 77.68.77.248 + address 77.68.79.206 + address 109.228.40.222 + address 77.68.24.172 + address 77.68.77.144 + address 77.68.76.112 + } + address-group G-21-TCP { + address 172.16.255.254 + address 77.68.76.104 + address 77.68.76.127 + address 77.68.76.136 + address 77.68.76.141 + address 77.68.76.187 + address 77.68.76.195 + address 77.68.76.203 + address 77.68.76.209 + address 77.68.76.217 + address 77.68.76.22 + address 77.68.76.220 + address 77.68.76.235 + address 77.68.76.245 + address 77.68.76.38 + address 77.68.76.54 + address 77.68.76.75 + address 77.68.76.80 + address 77.68.76.91 + address 77.68.76.94 + address 77.68.77.107 + address 77.68.77.128 + address 77.68.77.137 + address 77.68.77.150 + address 77.68.77.151 + address 77.68.77.171 + address 77.68.77.200 + address 77.68.77.201 + address 77.68.77.207 + address 77.68.77.22 + address 77.68.77.236 + address 77.68.77.240 + address 77.68.77.253 + address 77.68.77.32 + address 77.68.77.49 + address 77.68.77.50 + address 77.68.77.56 + address 77.68.77.63 + address 77.68.77.71 + address 77.68.77.81 + address 77.68.77.85 + address 77.68.77.92 + address 77.68.77.97 + address 77.68.77.99 + address 77.68.77.190 + address 77.68.77.103 + address 77.68.76.26 + address 77.68.76.107 + address 77.68.76.148 + address 77.68.76.19 + address 77.68.77.192 + address 77.68.77.157 + address 77.68.91.195 + address 77.68.77.211 + address 109.228.56.185 + address 77.68.84.147 + address 77.68.77.74 + address 77.68.4.74 + address 77.68.30.133 + address 77.68.28.145 + address 77.68.26.216 + address 77.68.77.130 + address 77.68.116.119 + address 77.68.116.220 + address 109.228.56.26 + address 77.68.7.123 + address 77.68.84.155 + address 77.68.86.40 + address 77.68.120.241 + address 77.68.122.89 + address 77.68.10.142 + address 77.68.122.241 + address 77.68.6.105 + address 77.68.17.186 + address 77.68.95.42 + address 77.68.22.146 + address 77.68.4.252 + address 109.228.36.229 + address 109.228.40.207 + address 77.68.31.144 + address 109.228.37.174 + address 109.228.37.114 + address 77.68.112.75 + address 77.68.77.160 + address 77.68.76.152 + address 77.68.7.67 + address 77.68.113.117 + address 77.68.86.148 + address 77.68.23.35 + address 109.228.40.194 + address 77.68.90.132 + address 77.68.77.26 + address 77.68.76.95 + address 77.68.120.26 + address 109.228.61.31 + address 77.68.120.249 + address 77.68.6.210 + address 213.171.213.41 + address 77.68.77.248 + address 213.171.215.184 + address 77.68.25.146 + address 213.171.210.19 + address 213.171.213.242 + address 109.228.48.249 + address 109.228.40.195 + address 77.68.127.172 + address 77.68.79.206 + address 77.68.28.147 + address 185.132.36.148 + address 185.132.37.83 + address 77.68.117.51 + address 77.68.25.124 + address 77.68.13.137 + address 109.228.52.186 + address 185.132.36.24 + address 77.68.77.69 + address 109.228.40.222 + address 77.68.87.212 + address 185.132.39.99 + address 109.228.38.201 + address 185.132.39.219 + address 77.68.28.139 + address 77.68.81.218 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.117.222 + address 185.132.41.73 + address 77.68.76.45 + address 77.68.77.215 + address 77.68.77.214 + address 77.68.79.89 + address 77.68.76.21 + address 77.68.33.68 + address 77.68.80.97 + address 77.68.77.65 + address 185.132.41.148 + address 77.68.24.172 + address 77.68.5.95 + address 77.68.5.125 + address 213.171.208.40 + address 77.68.76.40 + address 77.68.113.164 + address 77.68.114.93 + address 185.132.36.60 + address 185.132.40.244 + address 213.171.214.102 + address 88.208.197.160 + address 88.208.196.123 + address 77.68.77.144 + address 77.68.126.14 + address 77.68.76.171 + address 88.208.198.69 + address 77.68.34.139 + address 88.208.212.31 + address 77.68.76.112 + address 77.68.76.228 + address 77.68.77.75 + address 88.208.198.66 + address 77.68.77.219 + address 77.68.77.204 + address 77.68.4.25 + address 77.68.7.114 + address 77.68.123.177 + address 77.68.114.237 + address 77.68.77.222 + address 77.68.112.83 + address 185.132.37.47 + address 77.68.77.238 + } + address-group G-22-TCP { + address 172.16.255.254 + address 77.68.76.104 + address 77.68.76.105 + address 77.68.76.115 + address 77.68.76.122 + address 77.68.76.126 + address 77.68.76.127 + address 77.68.76.136 + address 77.68.76.141 + address 77.68.76.145 + address 77.68.76.148 + address 77.68.76.158 + address 77.68.76.164 + address 77.68.76.177 + address 77.68.76.187 + address 77.68.76.195 + address 77.68.76.197 + address 77.68.76.20 + address 77.68.76.200 + address 77.68.76.209 + address 77.68.76.217 + address 77.68.76.22 + address 77.68.76.235 + address 77.68.76.239 + address 77.68.76.245 + address 77.68.76.247 + address 77.68.76.25 + address 77.68.76.251 + address 77.68.76.252 + address 77.68.76.33 + address 77.68.76.37 + address 77.68.76.38 + address 77.68.76.49 + address 77.68.76.54 + address 77.68.76.55 + address 77.68.76.57 + address 77.68.76.61 + address 77.68.76.74 + address 77.68.76.80 + address 77.68.76.99 + address 77.68.77.100 + address 77.68.77.103 + address 77.68.77.107 + address 77.68.77.108 + address 77.68.77.117 + address 77.68.77.124 + address 77.68.77.128 + address 77.68.77.129 + address 77.68.77.130 + address 77.68.77.137 + address 77.68.77.139 + address 77.68.77.140 + address 77.68.77.141 + address 77.68.77.150 + address 77.68.77.151 + address 77.68.77.159 + address 77.68.77.171 + address 77.68.77.176 + address 77.68.77.19 + address 77.68.77.190 + address 77.68.77.200 + address 77.68.77.201 + address 77.68.77.203 + address 77.68.77.207 + address 77.68.77.211 + address 77.68.77.212 + address 77.68.77.22 + address 77.68.77.221 + address 77.68.77.227 + address 77.68.77.240 + address 77.68.77.243 + address 77.68.77.247 + address 77.68.77.253 + address 77.68.77.32 + address 77.68.77.33 + address 77.68.77.37 + address 77.68.77.43 + address 77.68.77.49 + address 77.68.77.50 + address 77.68.77.53 + address 77.68.77.56 + address 77.68.77.67 + address 77.68.77.68 + address 77.68.77.77 + address 77.68.77.79 + address 77.68.77.81 + address 77.68.77.85 + address 77.68.77.88 + address 77.68.77.92 + address 77.68.77.99 + address 77.68.76.110 + address 77.68.76.76 + address 77.68.76.211 + address 77.68.76.19 + address 77.68.77.74 + address 77.68.76.165 + address 77.68.77.254 + address 77.68.77.157 + address 77.68.76.138 + address 77.68.76.139 + address 77.68.76.124 + address 77.68.76.243 + address 77.68.76.114 + address 77.68.76.244 + address 77.68.77.192 + address 77.68.77.161 + address 77.68.91.195 + address 77.68.17.26 + address 77.68.28.145 + address 77.68.84.147 + address 109.228.56.185 + address 77.68.26.166 + address 77.68.12.195 + address 77.68.29.178 + address 77.68.5.187 + address 77.68.7.227 + address 77.68.4.24 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.5.241 + address 77.68.4.39 + address 77.68.81.44 + address 77.68.90.106 + address 77.68.27.54 + address 77.68.30.133 + address 77.68.4.136 + address 77.68.24.112 + address 77.68.92.186 + address 77.68.20.161 + address 77.68.26.216 + address 77.68.20.231 + address 77.68.118.17 + address 77.68.116.119 + address 77.68.116.232 + address 77.68.7.172 + address 77.68.116.221 + address 77.68.89.183 + address 77.68.83.41 + address 77.68.86.40 + address 77.68.88.164 + address 109.228.56.26 + address 77.68.7.123 + address 77.68.112.248 + address 109.228.60.215 + address 77.68.7.186 + address 77.68.93.246 + address 77.68.120.241 + address 77.68.121.106 + address 77.68.122.195 + address 77.68.122.89 + address 77.68.122.241 + address 77.68.81.141 + address 77.68.116.52 + address 77.68.6.32 + address 77.68.76.229 + address 77.68.28.207 + address 77.68.4.252 + address 77.68.17.186 + address 77.68.24.220 + address 77.68.22.146 + address 77.68.23.112 + address 77.68.125.32 + address 77.68.72.202 + address 109.228.36.229 + address 77.68.31.144 + address 77.68.2.215 + address 77.68.117.142 + address 77.68.5.166 + address 77.68.76.102 + address 109.228.37.174 + address 109.228.37.114 + address 77.68.76.169 + address 109.228.37.240 + address 77.68.112.75 + address 77.68.77.160 + address 109.228.39.249 + address 77.68.76.77 + address 109.228.40.226 + address 77.68.7.67 + address 77.68.126.51 + address 77.68.75.113 + address 77.68.86.148 + address 77.68.23.35 + address 77.68.114.183 + address 109.228.40.194 + address 77.68.76.31 + address 77.68.90.132 + address 77.68.77.26 + address 77.68.76.96 + address 77.68.77.30 + address 77.68.76.95 + address 77.68.10.170 + address 77.68.120.26 + address 109.228.61.31 + address 77.68.76.59 + address 213.171.213.41 + address 77.68.77.248 + address 213.171.212.171 + address 77.68.4.22 + address 77.68.119.14 + address 213.171.215.184 + address 77.68.77.202 + address 77.68.25.146 + address 213.171.213.31 + address 77.68.78.229 + address 77.68.77.102 + address 213.171.210.19 + address 77.68.24.59 + address 213.171.213.97 + address 213.171.213.242 + address 109.228.48.249 + address 109.228.40.195 + address 77.68.120.229 + address 77.68.79.206 + address 77.68.123.250 + address 77.68.28.147 + address 185.132.36.142 + address 213.171.212.172 + address 185.132.36.148 + address 213.171.208.58 + address 77.68.25.130 + address 185.132.38.142 + address 109.228.56.242 + address 109.228.46.81 + address 185.132.38.95 + address 185.132.37.83 + address 77.68.117.51 + address 77.68.116.36 + address 77.68.120.45 + address 213.171.210.59 + address 213.171.215.43 + address 185.132.37.102 + address 109.228.42.232 + address 109.228.52.186 + address 77.68.9.186 + address 77.68.13.76 + address 109.228.36.194 + address 185.132.36.24 + address 77.68.77.69 + address 185.132.39.129 + address 185.132.36.17 + address 109.228.40.222 + address 77.68.74.39 + address 77.68.118.104 + address 213.171.212.136 + address 77.68.120.31 + address 77.68.74.152 + address 185.132.39.37 + address 77.68.87.212 + address 77.68.119.188 + address 77.68.74.85 + address 77.68.91.22 + address 77.68.76.88 + address 77.68.4.242 + address 77.68.76.181 + address 77.68.76.161 + address 109.228.35.84 + address 185.132.39.99 + address 77.68.95.212 + address 77.68.85.73 + address 77.68.76.219 + address 77.68.27.27 + address 77.68.3.194 + address 77.68.3.144 + address 77.68.3.80 + address 77.68.27.28 + address 77.68.3.247 + address 77.68.3.161 + address 77.68.27.18 + address 77.68.3.121 + address 213.171.214.234 + address 185.132.39.219 + address 77.68.28.139 + address 77.68.81.218 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.117.222 + address 213.171.211.128 + address 77.68.5.155 + address 185.132.41.73 + address 213.171.214.167 + address 185.132.43.28 + address 213.171.213.42 + address 77.68.76.45 + address 185.132.41.72 + address 185.132.43.157 + address 185.132.40.56 + address 185.132.37.23 + address 77.68.117.29 + address 77.68.75.253 + address 77.68.11.140 + address 77.68.77.215 + address 77.68.20.217 + address 77.68.76.198 + address 77.68.77.214 + address 213.171.210.177 + address 185.132.38.114 + address 77.68.33.48 + address 77.68.32.89 + address 77.68.32.86 + address 77.68.34.138 + address 77.68.32.83 + address 77.68.75.45 + address 77.68.76.176 + address 185.132.43.164 + address 77.68.76.137 + address 185.132.40.152 + address 77.68.33.68 + address 77.68.93.125 + address 77.68.24.134 + address 185.132.38.248 + address 77.68.32.43 + address 77.68.120.218 + address 77.68.112.167 + address 77.68.32.31 + address 77.68.32.254 + address 77.68.80.26 + address 77.68.80.97 + address 77.68.121.119 + address 77.68.74.209 + address 77.68.77.65 + address 185.132.43.6 + address 109.228.46.196 + address 185.132.43.98 + address 185.132.41.148 + address 77.68.24.172 + address 77.68.33.197 + address 213.171.210.25 + address 77.68.5.95 + address 77.68.23.64 + address 77.68.101.125 + address 77.68.5.125 + address 77.68.100.167 + address 109.228.59.247 + address 77.68.35.116 + address 77.68.33.171 + address 77.68.48.105 + address 77.68.48.81 + address 77.68.49.4 + address 109.228.36.119 + address 77.68.121.127 + address 77.68.82.147 + address 77.68.49.12 + address 77.68.8.144 + address 77.68.116.183 + address 77.68.103.19 + address 77.68.50.91 + address 77.68.24.63 + address 77.68.118.15 + address 77.68.50.198 + address 77.68.49.160 + address 77.68.49.161 + address 77.68.76.191 + address 77.68.76.40 + address 77.68.113.164 + address 77.68.77.42 + address 77.68.100.134 + address 77.68.100.132 + address 77.68.114.93 + address 185.132.36.60 + address 185.132.40.244 + address 77.68.85.18 + address 77.68.50.193 + address 77.68.89.247 + address 88.208.197.10 + address 77.68.102.129 + address 109.228.36.79 + address 185.132.38.182 + address 185.132.41.240 + address 77.68.51.214 + address 88.208.196.123 + address 77.68.126.22 + address 213.171.212.90 + address 77.68.114.205 + address 77.68.48.202 + address 77.68.112.175 + address 77.68.112.90 + address 185.132.40.166 + address 77.68.103.120 + address 77.68.103.147 + address 77.68.33.24 + address 109.228.58.134 + address 109.228.47.223 + address 109.228.56.97 + address 77.68.103.227 + address 88.208.196.92 + address 88.208.196.154 + address 185.132.39.44 + address 77.68.76.248 + address 88.208.198.92 + address 77.68.77.144 + address 77.68.126.14 + address 88.208.196.91 + address 77.68.100.77 + address 185.132.37.101 + address 77.68.87.164 + address 77.68.76.120 + address 77.68.93.164 + address 77.68.76.171 + address 88.208.197.135 + address 88.208.197.118 + address 88.208.197.150 + address 77.68.34.139 + address 213.171.213.175 + address 77.68.21.171 + address 88.208.197.60 + address 109.228.37.10 + address 88.208.215.61 + address 88.208.212.31 + address 109.228.53.243 + address 77.68.48.89 + address 88.208.212.188 + address 88.208.198.251 + address 88.208.215.19 + address 77.68.76.228 + address 109.228.39.41 + address 77.68.115.142 + address 77.68.78.73 + address 213.171.214.96 + address 88.208.198.66 + address 77.68.3.61 + address 77.68.77.219 + address 77.68.26.228 + address 77.68.4.25 + address 77.68.7.114 + address 77.68.123.177 + address 77.68.77.222 + address 77.68.112.83 + address 77.68.117.214 + address 88.208.199.141 + address 185.132.39.109 + address 185.132.37.47 + address 77.68.102.5 + address 77.68.16.247 + address 88.208.212.94 + address 77.68.72.254 + address 109.228.61.37 + address 77.68.50.142 + address 77.68.78.113 + address 88.208.212.182 + address 185.132.40.124 + address 88.208.197.208 + address 88.208.197.129 + address 77.68.77.238 + address 77.68.79.82 + address 185.132.38.216 + } + address-group G-25-TCP { + address 172.16.255.254 + address 77.68.76.115 + address 77.68.76.141 + address 77.68.76.187 + address 77.68.76.195 + address 77.68.76.197 + address 77.68.76.203 + address 77.68.76.209 + address 77.68.76.55 + address 77.68.76.57 + address 77.68.76.75 + address 77.68.76.91 + address 77.68.76.99 + address 77.68.77.107 + address 77.68.77.129 + address 77.68.77.130 + address 77.68.77.141 + address 77.68.77.150 + address 77.68.77.159 + address 77.68.77.171 + address 77.68.77.176 + address 77.68.77.207 + address 77.68.77.22 + address 77.68.77.236 + address 77.68.77.240 + address 77.68.77.243 + address 77.68.77.32 + address 77.68.77.33 + address 77.68.77.49 + address 77.68.77.50 + address 77.68.77.56 + address 77.68.77.63 + address 77.68.77.81 + address 77.68.77.85 + address 77.68.77.92 + address 77.68.77.97 + address 77.68.77.99 + address 77.68.77.77 + address 77.68.76.19 + address 77.68.77.192 + address 77.68.77.254 + address 77.68.76.139 + address 77.68.84.147 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.81.44 + address 77.68.30.133 + address 77.68.77.74 + address 77.68.77.100 + address 77.68.92.186 + address 77.68.76.114 + address 77.68.116.119 + address 77.68.116.221 + address 77.68.116.220 + address 109.228.56.26 + address 77.68.7.123 + address 77.68.120.241 + address 109.228.60.215 + address 77.68.7.172 + address 77.68.116.52 + address 77.68.91.128 + address 77.68.24.112 + address 77.68.76.94 + address 109.228.37.114 + address 77.68.112.75 + address 77.68.77.160 + address 77.68.7.67 + address 77.68.113.117 + address 77.68.126.51 + address 77.68.86.148 + address 77.68.23.35 + address 77.68.77.30 + address 77.68.76.95 + address 77.68.10.170 + address 213.171.213.41 + address 213.171.215.184 + address 77.68.25.146 + address 213.171.213.31 + address 77.68.78.229 + address 213.171.210.19 + address 77.68.79.206 + address 213.171.215.252 + address 109.228.52.186 + address 77.68.77.69 + address 109.228.40.222 + address 77.68.87.212 + address 185.132.39.99 + address 77.68.85.73 + address 77.68.28.139 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.117.222 + address 185.132.43.28 + address 185.132.37.23 + address 77.68.77.215 + address 77.68.77.214 + address 185.132.38.114 + address 77.68.33.48 + address 77.68.79.89 + address 77.68.76.21 + address 77.68.76.137 + address 77.68.80.26 + address 77.68.5.95 + address 77.68.100.167 + address 77.68.4.80 + address 77.68.49.152 + address 213.171.208.40 + address 77.68.112.184 + address 77.68.115.17 + address 77.68.82.147 + address 77.68.118.15 + address 77.68.76.191 + address 77.68.50.193 + address 77.68.102.129 + address 77.68.76.118 + address 88.208.198.69 + address 77.68.34.139 + address 88.208.197.60 + address 88.208.212.188 + address 77.68.76.112 + address 77.68.77.75 + address 213.171.214.96 + address 88.208.198.66 + address 77.68.77.219 + address 77.68.77.204 + address 77.68.76.202 + address 77.68.123.177 + address 77.68.77.222 + address 77.68.112.83 + address 185.132.37.47 + address 77.68.77.152 + address 77.68.77.181 + address 77.68.77.185 + address 77.68.77.238 + address 77.68.79.82 + } + address-group G-53-TCP { + address 172.16.255.254 + address 77.68.94.181 + address 77.68.28.145 + address 77.68.84.155 + address 77.68.78.229 + address 185.132.39.99 + address 185.132.43.28 + address 77.68.77.215 + address 185.132.40.152 + address 77.68.49.161 + address 77.68.76.118 + } + address-group G-53-UDP { + address 172.16.255.254 + address 77.68.76.235 + address 77.68.76.93 + address 77.68.77.107 + address 77.68.77.151 + address 77.68.77.37 + address 77.68.76.139 + address 77.68.81.44 + address 77.68.94.181 + address 77.68.28.145 + address 77.68.81.141 + address 77.68.4.252 + address 77.68.125.32 + address 77.68.86.148 + address 77.68.78.229 + address 185.132.43.28 + address 77.68.75.45 + address 185.132.40.152 + address 77.68.4.80 + address 77.68.49.152 + address 77.68.49.161 + address 77.68.34.50 + } + address-group G-80-TCP { + address 172.16.255.254 + address 77.68.76.104 + address 77.68.76.105 + address 77.68.76.115 + address 77.68.76.116 + address 77.68.76.122 + address 77.68.76.126 + address 77.68.76.127 + address 77.68.76.136 + address 77.68.76.141 + address 77.68.76.145 + address 77.68.76.148 + address 77.68.76.150 + address 77.68.76.158 + address 77.68.76.164 + address 77.68.76.177 + address 77.68.76.187 + address 77.68.76.195 + address 77.68.76.197 + address 77.68.76.20 + address 77.68.76.200 + address 77.68.76.203 + address 77.68.76.209 + address 77.68.76.217 + address 77.68.76.22 + address 77.68.76.220 + address 77.68.76.23 + address 77.68.76.231 + address 77.68.76.235 + address 77.68.76.239 + address 77.68.76.241 + address 77.68.76.245 + address 77.68.76.247 + address 77.68.76.25 + address 77.68.76.251 + address 77.68.76.252 + address 77.68.76.33 + address 77.68.76.35 + address 77.68.76.37 + address 77.68.76.38 + address 77.68.76.39 + address 77.68.76.49 + address 77.68.76.50 + address 77.68.76.54 + address 77.68.76.55 + address 77.68.76.57 + address 77.68.76.58 + address 77.68.76.61 + address 77.68.76.74 + address 77.68.76.75 + address 77.68.76.80 + address 77.68.76.91 + address 77.68.76.93 + address 77.68.76.94 + address 77.68.76.99 + address 77.68.77.100 + address 77.68.77.103 + address 77.68.77.107 + address 77.68.77.108 + address 77.68.77.115 + address 77.68.77.117 + address 77.68.77.124 + address 77.68.77.128 + address 77.68.77.129 + address 77.68.77.130 + address 77.68.77.137 + address 77.68.77.139 + address 77.68.77.140 + address 77.68.77.141 + address 77.68.77.150 + address 77.68.77.151 + address 77.68.77.156 + address 77.68.77.159 + address 77.68.77.171 + address 77.68.77.176 + address 77.68.77.178 + address 77.68.77.19 + address 77.68.77.190 + address 77.68.77.199 + address 77.68.77.200 + address 77.68.77.201 + address 77.68.77.203 + address 77.68.77.207 + address 77.68.77.211 + address 77.68.77.212 + address 77.68.77.22 + address 77.68.77.227 + address 77.68.77.228 + address 77.68.77.236 + address 77.68.77.240 + address 77.68.77.243 + address 77.68.77.247 + address 77.68.77.253 + address 77.68.77.32 + address 77.68.77.33 + address 77.68.77.37 + address 77.68.77.49 + address 77.68.77.50 + address 77.68.77.53 + address 77.68.77.56 + address 77.68.77.63 + address 77.68.77.67 + address 77.68.77.68 + address 77.68.77.71 + address 77.68.77.77 + address 77.68.77.79 + address 77.68.77.81 + address 77.68.77.85 + address 77.68.77.88 + address 77.68.77.92 + address 77.68.77.97 + address 77.68.77.99 + address 77.68.76.76 + address 77.68.76.124 + address 77.68.76.211 + address 77.68.76.19 + address 77.68.77.74 + address 77.68.77.192 + address 77.68.76.92 + address 77.68.76.165 + address 77.68.77.254 + address 77.68.77.157 + address 77.68.76.138 + address 77.68.76.139 + address 77.68.76.114 + address 77.68.76.244 + address 77.68.77.161 + address 77.68.77.62 + address 77.68.77.38 + address 77.68.91.195 + address 77.68.17.26 + address 77.68.28.145 + address 109.228.56.185 + address 77.68.84.147 + address 77.68.12.195 + address 77.68.21.78 + address 77.68.5.187 + address 77.68.7.227 + address 77.68.4.24 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.5.241 + address 77.68.4.39 + address 77.68.81.44 + address 77.68.90.106 + address 77.68.94.181 + address 77.68.30.164 + address 77.68.30.133 + address 77.68.4.136 + address 77.68.23.158 + address 77.68.92.186 + address 77.68.24.112 + address 77.68.112.213 + address 77.68.20.161 + address 77.68.26.216 + address 77.68.20.231 + address 77.68.118.17 + address 77.68.116.119 + address 77.68.116.220 + address 77.68.116.232 + address 77.68.76.142 + address 77.68.117.202 + address 77.68.7.172 + address 77.68.116.221 + address 77.68.89.183 + address 77.68.83.41 + address 77.68.86.40 + address 77.68.88.164 + address 109.228.56.26 + address 77.68.7.123 + address 77.68.112.248 + address 109.228.60.215 + address 77.68.7.186 + address 77.68.93.246 + address 77.68.84.155 + address 77.68.120.241 + address 77.68.121.106 + address 77.68.122.195 + address 77.68.122.89 + address 77.68.120.146 + address 77.68.122.241 + address 77.68.119.92 + address 77.68.81.141 + address 77.68.10.142 + address 77.68.116.52 + address 77.68.6.105 + address 77.68.76.229 + address 77.68.95.42 + address 77.68.28.207 + address 77.68.4.252 + address 77.68.17.186 + address 77.68.91.128 + address 77.68.22.146 + address 77.68.23.112 + address 77.68.24.220 + address 77.68.125.32 + address 77.68.76.243 + address 77.68.12.250 + address 77.68.72.202 + address 109.228.36.229 + address 109.228.40.207 + address 77.68.31.144 + address 77.68.2.215 + address 77.68.117.142 + address 77.68.5.166 + address 109.228.37.174 + address 109.228.37.114 + address 77.68.76.169 + address 109.228.37.240 + address 77.68.112.75 + address 77.68.76.30 + address 109.228.35.110 + address 77.68.77.160 + address 77.68.77.208 + address 77.68.76.152 + address 109.228.39.249 + address 77.68.76.77 + address 109.228.40.226 + address 77.68.7.67 + address 77.68.113.117 + address 77.68.126.51 + address 77.68.75.113 + address 77.68.86.148 + address 77.68.23.35 + address 77.68.114.183 + address 109.228.40.194 + address 77.68.76.31 + address 77.68.77.72 + address 77.68.90.132 + address 77.68.6.110 + address 77.68.76.96 + address 77.68.77.30 + address 77.68.76.95 + address 77.68.10.170 + address 77.68.120.26 + address 109.228.61.31 + address 77.68.76.59 + address 77.68.120.249 + address 77.68.6.210 + address 213.171.213.41 + address 77.68.77.248 + address 213.171.212.171 + address 77.68.4.22 + address 77.68.119.14 + address 213.171.215.184 + address 77.68.77.202 + address 77.68.25.146 + address 213.171.213.31 + address 77.68.78.229 + address 77.68.77.102 + address 213.171.210.19 + address 77.68.24.59 + address 213.171.213.97 + address 213.171.213.242 + address 77.68.77.205 + address 109.228.48.249 + address 109.228.40.195 + address 77.68.120.229 + address 77.68.127.172 + address 77.68.79.206 + address 77.68.123.250 + address 77.68.28.147 + address 213.171.212.172 + address 185.132.36.148 + address 213.171.208.58 + address 77.68.25.130 + address 109.228.56.242 + address 109.228.46.81 + address 185.132.38.95 + address 185.132.37.83 + address 77.68.117.51 + address 77.68.116.36 + address 77.68.120.45 + address 77.68.25.124 + address 213.171.210.59 + address 213.171.215.43 + address 213.171.215.252 + address 185.132.37.102 + address 109.228.42.232 + address 109.228.52.186 + address 77.68.9.186 + address 77.68.13.76 + address 109.228.36.194 + address 185.132.36.7 + address 185.132.36.24 + address 77.68.77.69 + address 185.132.39.129 + address 185.132.36.17 + address 109.228.40.222 + address 77.68.118.104 + address 77.68.120.31 + address 77.68.74.152 + address 185.132.39.37 + address 77.68.3.52 + address 77.68.87.212 + address 77.68.76.29 + address 77.68.119.188 + address 77.68.74.85 + address 77.68.91.22 + address 77.68.76.88 + address 77.68.4.242 + address 77.68.76.181 + address 77.68.76.161 + address 185.132.39.99 + address 77.68.95.212 + address 77.68.85.73 + address 77.68.76.219 + address 77.68.27.27 + address 77.68.3.194 + address 77.68.3.144 + address 77.68.3.80 + address 77.68.27.28 + address 77.68.3.247 + address 77.68.3.161 + address 77.68.27.18 + address 77.68.3.121 + address 213.171.214.234 + address 109.228.38.201 + address 185.132.39.219 + address 77.68.28.139 + address 77.68.81.218 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.117.222 + address 213.171.211.128 + address 77.68.5.155 + address 185.132.41.73 + address 77.68.77.231 + address 213.171.214.167 + address 185.132.43.28 + address 213.171.213.42 + address 77.68.76.45 + address 185.132.41.72 + address 77.68.92.92 + address 185.132.40.56 + address 185.132.37.23 + address 77.68.117.29 + address 77.68.75.253 + address 77.68.11.140 + address 77.68.77.215 + address 77.68.20.217 + address 77.68.10.152 + address 77.68.73.73 + address 77.68.76.198 + address 77.68.77.214 + address 77.68.9.75 + address 213.171.210.177 + address 77.68.76.160 + address 185.132.38.114 + address 77.68.33.48 + address 185.132.40.90 + address 77.68.79.89 + address 77.68.34.28 + address 77.68.76.21 + address 77.68.75.45 + address 77.68.76.176 + address 77.68.77.95 + address 185.132.39.68 + address 185.132.43.164 + address 77.68.76.137 + address 185.132.40.152 + address 77.68.77.249 + address 77.68.33.68 + address 77.68.24.134 + address 185.132.38.248 + address 77.68.32.43 + address 77.68.120.218 + address 77.68.112.167 + address 77.68.32.31 + address 77.68.32.118 + address 77.68.32.254 + address 77.68.80.26 + address 77.68.17.200 + address 77.68.80.97 + address 77.68.121.119 + address 77.68.74.209 + address 77.68.77.65 + address 185.132.43.6 + address 109.228.46.196 + address 185.132.43.98 + address 77.68.100.150 + address 185.132.41.148 + address 77.68.24.172 + address 77.68.33.197 + address 77.68.5.95 + address 77.68.23.64 + address 77.68.101.124 + address 77.68.5.125 + address 77.68.100.167 + address 77.68.4.80 + address 77.68.49.152 + address 109.228.59.247 + address 213.171.208.40 + address 77.68.112.184 + address 77.68.35.116 + address 77.68.33.171 + address 77.68.76.111 + address 77.68.76.42 + address 77.68.77.120 + address 77.68.76.183 + address 77.68.118.86 + address 77.68.48.105 + address 77.68.48.81 + address 77.68.49.4 + address 109.228.36.119 + address 77.68.34.26 + address 77.68.115.17 + address 77.68.121.127 + address 77.68.82.147 + address 77.68.49.12 + address 77.68.8.144 + address 77.68.116.183 + address 213.171.212.89 + address 77.68.76.44 + address 77.68.77.239 + address 77.68.51.202 + address 77.68.101.64 + address 77.68.103.19 + address 77.68.50.91 + address 77.68.24.63 + address 77.68.118.15 + address 77.68.50.198 + address 77.68.77.59 + address 77.68.49.160 + address 77.68.76.191 + address 77.68.126.101 + address 77.68.113.164 + address 77.68.77.42 + address 77.68.100.134 + address 77.68.100.132 + address 77.68.114.93 + address 185.132.36.60 + address 185.132.40.244 + address 77.68.85.18 + address 213.171.214.102 + address 77.68.50.193 + address 88.208.197.160 + address 88.208.197.10 + address 77.68.102.129 + address 109.228.36.79 + address 185.132.38.182 + address 185.132.41.240 + address 77.68.51.214 + address 88.208.196.123 + address 88.208.215.157 + address 77.68.126.22 + address 77.68.4.180 + address 213.171.212.90 + address 77.68.114.205 + address 185.132.43.71 + address 77.68.77.114 + address 77.68.48.202 + address 77.68.112.175 + address 77.68.112.90 + address 185.132.40.166 + address 77.68.76.118 + address 77.68.103.120 + address 77.68.33.24 + address 109.228.58.134 + address 109.228.47.223 + address 77.68.31.96 + address 77.68.103.227 + address 77.68.76.250 + address 213.171.212.203 + address 88.208.196.92 + address 88.208.196.154 + address 185.132.39.44 + address 77.68.76.248 + address 88.208.198.92 + address 109.228.36.37 + address 77.68.77.144 + address 77.68.126.14 + address 88.208.196.91 + address 77.68.100.77 + address 185.132.37.101 + address 77.68.87.164 + address 77.68.77.76 + address 77.68.76.120 + address 77.68.82.157 + address 77.68.93.164 + address 77.68.76.171 + address 88.208.197.135 + address 88.208.197.118 + address 88.208.197.150 + address 213.171.212.114 + address 88.208.198.69 + address 77.68.34.139 + address 77.68.21.171 + address 88.208.197.60 + address 77.68.85.27 + address 109.228.37.10 + address 88.208.215.61 + address 88.208.199.249 + address 88.208.212.31 + address 109.228.53.243 + address 77.68.48.89 + address 88.208.212.188 + address 88.208.198.251 + address 77.68.76.112 + address 77.68.48.14 + address 88.208.215.19 + address 77.68.103.56 + address 77.68.76.228 + address 77.68.77.75 + address 77.68.117.173 + address 88.208.215.121 + address 109.228.39.41 + address 77.68.88.100 + address 77.68.76.108 + address 77.68.115.142 + address 213.171.214.96 + address 88.208.198.66 + address 88.208.198.64 + address 77.68.3.61 + address 77.68.77.219 + address 77.68.77.204 + address 77.68.26.228 + address 77.68.74.232 + address 77.68.118.88 + address 77.68.76.48 + address 77.68.76.202 + address 77.68.4.25 + address 77.68.7.114 + address 77.68.123.177 + address 88.208.197.23 + address 77.68.114.237 + address 77.68.77.222 + address 77.68.112.83 + address 88.208.199.141 + address 77.68.77.163 + address 185.132.39.109 + address 77.68.77.44 + address 185.132.37.47 + address 77.68.102.5 + address 77.68.16.247 + address 88.208.212.94 + address 77.68.72.254 + address 77.68.77.152 + address 77.68.50.142 + address 88.208.199.46 + address 77.68.78.113 + address 88.208.212.182 + address 77.68.77.181 + address 77.68.15.95 + address 77.68.75.64 + address 213.171.212.71 + address 185.132.40.124 + address 88.208.197.208 + address 88.208.197.129 + address 77.68.76.60 + address 77.68.6.119 + address 77.68.77.185 + address 77.68.77.238 + address 77.68.79.82 + address 109.228.39.151 + } + address-group G-110-TCP { + address 172.16.255.254 + address 77.68.76.187 + address 77.68.77.107 + address 77.68.77.128 + address 77.68.77.129 + address 77.68.77.171 + address 77.68.77.176 + address 77.68.77.190 + address 77.68.77.207 + address 77.68.77.22 + address 77.68.77.33 + address 77.68.77.49 + address 77.68.77.92 + address 77.68.77.77 + address 77.68.76.19 + address 77.68.77.192 + address 77.68.84.147 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.116.119 + address 77.68.116.221 + address 77.68.120.241 + address 109.228.60.215 + address 77.68.116.52 + address 77.68.126.51 + address 77.68.23.35 + address 77.68.76.95 + address 213.171.215.184 + address 77.68.25.146 + address 77.68.79.206 + address 213.171.215.252 + address 109.228.52.186 + address 109.228.40.222 + address 185.132.39.99 + address 77.68.77.214 + address 185.132.38.114 + address 77.68.79.89 + address 77.68.5.95 + address 77.68.100.167 + address 77.68.4.80 + address 77.68.49.152 + address 213.171.208.40 + address 77.68.50.193 + address 77.68.102.129 + address 88.208.198.69 + address 88.208.212.188 + address 88.208.198.66 + address 77.68.4.25 + address 77.68.7.114 + address 77.68.123.177 + address 77.68.77.185 + address 77.68.77.238 + } + address-group G-143-TCP { + address 172.16.255.254 + address 77.68.76.115 + address 77.68.76.123 + address 77.68.76.187 + address 77.68.77.129 + address 77.68.77.130 + address 77.68.77.141 + address 77.68.77.171 + address 77.68.77.176 + address 77.68.77.207 + address 77.68.77.22 + address 77.68.77.33 + address 77.68.77.49 + address 77.68.77.50 + address 77.68.77.92 + address 77.68.77.77 + address 77.68.77.192 + address 77.68.84.147 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.81.44 + address 77.68.92.186 + address 77.68.116.119 + address 77.68.116.221 + address 109.228.60.215 + address 77.68.7.172 + address 77.68.116.52 + address 77.68.24.112 + address 77.68.77.107 + address 77.68.112.75 + address 77.68.7.67 + address 77.68.126.51 + address 77.68.23.35 + address 77.68.76.95 + address 213.171.215.184 + address 77.68.25.146 + address 213.171.213.31 + address 213.171.210.19 + address 77.68.79.206 + address 77.68.77.69 + address 109.228.40.222 + address 185.132.39.99 + address 77.68.117.222 + address 77.68.33.48 + address 77.68.79.89 + address 77.68.5.95 + address 77.68.100.167 + address 77.68.4.80 + address 77.68.49.152 + address 213.171.208.40 + address 77.68.115.17 + address 77.68.102.129 + address 88.208.198.69 + address 77.68.34.139 + address 88.208.212.188 + address 88.208.198.66 + address 77.68.77.204 + address 77.68.4.25 + address 77.68.7.114 + address 77.68.123.177 + address 77.68.77.222 + address 77.68.112.83 + } + address-group G-443-TCP { + address 172.16.255.254 + address 77.68.76.104 + address 77.68.76.105 + address 77.68.76.115 + address 77.68.76.116 + address 77.68.76.122 + address 77.68.76.126 + address 77.68.76.127 + address 77.68.76.136 + address 77.68.76.141 + address 77.68.76.145 + address 77.68.76.148 + address 77.68.76.150 + address 77.68.76.158 + address 77.68.76.164 + address 77.68.76.177 + address 77.68.76.187 + address 77.68.76.195 + address 77.68.76.197 + address 77.68.76.20 + address 77.68.76.200 + address 77.68.76.203 + address 77.68.76.209 + address 77.68.76.217 + address 77.68.76.22 + address 77.68.76.220 + address 77.68.76.23 + address 77.68.76.231 + address 77.68.76.235 + address 77.68.76.239 + address 77.68.76.241 + address 77.68.76.245 + address 77.68.76.25 + address 77.68.76.252 + address 77.68.76.33 + address 77.68.76.35 + address 77.68.76.37 + address 77.68.76.38 + address 77.68.76.39 + address 77.68.76.49 + address 77.68.76.50 + address 77.68.76.54 + address 77.68.76.55 + address 77.68.76.57 + address 77.68.76.58 + address 77.68.76.61 + address 77.68.76.74 + address 77.68.76.75 + address 77.68.76.80 + address 77.68.76.91 + address 77.68.76.93 + address 77.68.76.94 + address 77.68.76.99 + address 77.68.77.100 + address 77.68.77.103 + address 77.68.77.107 + address 77.68.77.108 + address 77.68.77.117 + address 77.68.77.124 + address 77.68.77.128 + address 77.68.77.129 + address 77.68.77.130 + address 77.68.77.137 + address 77.68.77.139 + address 77.68.77.140 + address 77.68.77.141 + address 77.68.77.150 + address 77.68.77.151 + address 77.68.77.156 + address 77.68.77.159 + address 77.68.77.171 + address 77.68.77.176 + address 77.68.77.178 + address 77.68.77.19 + address 77.68.77.190 + address 77.68.77.199 + address 77.68.77.200 + address 77.68.77.201 + address 77.68.77.203 + address 77.68.77.207 + address 77.68.77.211 + address 77.68.77.212 + address 77.68.77.22 + address 77.68.77.221 + address 77.68.77.227 + address 77.68.77.228 + address 77.68.77.236 + address 77.68.77.240 + address 77.68.77.243 + address 77.68.77.247 + address 77.68.77.253 + address 77.68.77.32 + address 77.68.77.33 + address 77.68.77.37 + address 77.68.77.49 + address 77.68.77.50 + address 77.68.77.53 + address 77.68.77.56 + address 77.68.77.63 + address 77.68.77.67 + address 77.68.77.68 + address 77.68.77.71 + address 77.68.77.77 + address 77.68.77.79 + address 77.68.77.81 + address 77.68.77.85 + address 77.68.77.88 + address 77.68.77.92 + address 77.68.77.97 + address 77.68.77.99 + address 77.68.76.76 + address 77.68.76.124 + address 77.68.76.211 + address 77.68.76.19 + address 77.68.76.110 + address 77.68.77.74 + address 77.68.77.192 + address 77.68.76.92 + address 77.68.76.165 + address 77.68.77.254 + address 77.68.77.157 + address 77.68.76.138 + address 77.68.76.139 + address 77.68.76.114 + address 77.68.76.244 + address 77.68.77.161 + address 77.68.77.38 + address 77.68.91.195 + address 77.68.17.26 + address 77.68.28.145 + address 109.228.56.185 + address 77.68.84.147 + address 77.68.12.195 + address 77.68.21.78 + address 77.68.5.187 + address 77.68.7.227 + address 77.68.4.24 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.5.241 + address 77.68.4.39 + address 77.68.81.44 + address 77.68.90.106 + address 77.68.94.181 + address 77.68.30.164 + address 77.68.30.133 + address 77.68.4.136 + address 77.68.23.158 + address 77.68.24.112 + address 77.68.92.186 + address 77.68.20.161 + address 77.68.112.213 + address 77.68.26.216 + address 77.68.20.231 + address 77.68.118.17 + address 77.68.116.119 + address 77.68.116.220 + address 77.68.116.232 + address 77.68.76.142 + address 77.68.117.202 + address 77.68.7.172 + address 77.68.116.221 + address 77.68.89.183 + address 77.68.83.41 + address 77.68.86.40 + address 77.68.88.164 + address 109.228.56.26 + address 77.68.7.123 + address 77.68.112.248 + address 109.228.60.215 + address 77.68.7.186 + address 77.68.93.246 + address 77.68.84.155 + address 77.68.120.241 + address 77.68.121.106 + address 77.68.122.195 + address 77.68.122.89 + address 77.68.120.146 + address 77.68.122.241 + address 77.68.81.141 + address 77.68.116.52 + address 77.68.6.105 + address 77.68.76.229 + address 77.68.95.42 + address 77.68.28.207 + address 77.68.4.252 + address 77.68.17.186 + address 77.68.91.128 + address 77.68.22.146 + address 77.68.23.112 + address 77.68.24.220 + address 77.68.125.32 + address 77.68.12.250 + address 77.68.76.243 + address 77.68.72.202 + address 109.228.36.229 + address 109.228.40.207 + address 77.68.31.144 + address 77.68.2.215 + address 77.68.117.142 + address 77.68.5.166 + address 77.68.76.102 + address 109.228.37.174 + address 109.228.37.114 + address 109.228.37.240 + address 77.68.112.75 + address 77.68.76.30 + address 109.228.35.110 + address 77.68.77.160 + address 77.68.77.208 + address 77.68.76.152 + address 109.228.39.249 + address 77.68.76.77 + address 77.68.7.160 + address 109.228.40.226 + address 77.68.7.67 + address 77.68.113.117 + address 77.68.126.51 + address 77.68.75.113 + address 77.68.86.148 + address 77.68.114.183 + address 109.228.40.194 + address 77.68.76.31 + address 77.68.77.72 + address 77.68.90.132 + address 77.68.6.110 + address 77.68.77.26 + address 77.68.76.96 + address 77.68.77.30 + address 77.68.76.95 + address 77.68.10.170 + address 77.68.76.234 + address 77.68.120.26 + address 109.228.61.31 + address 77.68.76.59 + address 77.68.120.249 + address 77.68.6.210 + address 213.171.213.41 + address 77.68.77.248 + address 213.171.212.171 + address 77.68.4.22 + address 77.68.119.14 + address 213.171.215.184 + address 77.68.77.202 + address 77.68.25.146 + address 213.171.213.31 + address 77.68.78.229 + address 77.68.77.102 + address 213.171.210.19 + address 77.68.24.59 + address 213.171.213.97 + address 213.171.213.242 + address 77.68.77.205 + address 109.228.48.249 + address 109.228.40.195 + address 77.68.120.229 + address 77.68.127.172 + address 77.68.79.206 + address 77.68.123.250 + address 77.68.28.147 + address 213.171.212.172 + address 185.132.36.148 + address 213.171.208.58 + address 77.68.25.130 + address 109.228.56.242 + address 109.228.46.81 + address 185.132.38.95 + address 185.132.37.83 + address 77.68.117.51 + address 77.68.116.36 + address 77.68.120.45 + address 77.68.25.124 + address 213.171.210.59 + address 213.171.215.43 + address 213.171.215.252 + address 185.132.37.102 + address 109.228.42.232 + address 109.228.52.186 + address 77.68.9.186 + address 77.68.13.76 + address 109.228.36.194 + address 185.132.36.7 + address 185.132.36.24 + address 77.68.77.69 + address 185.132.39.129 + address 185.132.36.17 + address 109.228.40.222 + address 77.68.118.104 + address 77.68.120.31 + address 77.68.74.152 + address 185.132.39.37 + address 77.68.3.52 + address 77.68.87.212 + address 77.68.76.29 + address 77.68.119.188 + address 77.68.74.85 + address 77.68.91.22 + address 77.68.76.88 + address 77.68.4.242 + address 77.68.76.181 + address 77.68.76.161 + address 185.132.39.99 + address 77.68.95.212 + address 77.68.76.219 + address 77.68.27.27 + address 77.68.3.194 + address 77.68.3.144 + address 77.68.3.80 + address 77.68.27.28 + address 77.68.3.247 + address 77.68.3.161 + address 77.68.27.18 + address 77.68.3.121 + address 213.171.214.234 + address 109.228.38.201 + address 185.132.39.219 + address 77.68.28.139 + address 77.68.81.218 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.117.222 + address 213.171.211.128 + address 77.68.5.155 + address 77.68.77.231 + address 213.171.214.167 + address 185.132.43.28 + address 213.171.213.42 + address 77.68.76.45 + address 77.68.92.92 + address 77.68.77.233 + address 185.132.40.56 + address 185.132.37.23 + address 77.68.117.29 + address 77.68.75.253 + address 77.68.11.140 + address 77.68.77.215 + address 77.68.20.217 + address 77.68.10.152 + address 77.68.73.73 + address 77.68.76.198 + address 77.68.77.214 + address 77.68.9.75 + address 213.171.210.177 + address 77.68.77.70 + address 77.68.77.149 + address 77.68.76.160 + address 185.132.38.114 + address 77.68.33.48 + address 185.132.40.90 + address 77.68.79.89 + address 77.68.34.28 + address 77.68.76.21 + address 77.68.75.45 + address 77.68.76.176 + address 77.68.77.95 + address 185.132.39.68 + address 185.132.43.164 + address 77.68.76.137 + address 185.132.40.152 + address 77.68.77.249 + address 77.68.24.134 + address 185.132.38.248 + address 77.68.32.43 + address 77.68.120.218 + address 77.68.112.167 + address 77.68.32.31 + address 77.68.32.118 + address 77.68.32.254 + address 77.68.80.26 + address 77.68.17.200 + address 77.68.80.97 + address 77.68.121.119 + address 77.68.74.209 + address 77.68.77.65 + address 185.132.43.6 + address 109.228.46.196 + address 185.132.43.98 + address 77.68.100.150 + address 185.132.41.148 + address 77.68.24.172 + address 77.68.33.197 + address 77.68.5.95 + address 77.68.23.64 + address 77.68.101.124 + address 77.68.5.125 + address 77.68.100.167 + address 77.68.4.80 + address 77.68.49.152 + address 109.228.59.247 + address 213.171.208.40 + address 77.68.112.184 + address 77.68.35.116 + address 185.132.40.11 + address 77.68.33.171 + address 77.68.76.111 + address 77.68.76.42 + address 77.68.77.120 + address 77.68.76.183 + address 77.68.118.86 + address 77.68.48.105 + address 77.68.48.81 + address 77.68.49.4 + address 109.228.36.119 + address 77.68.34.26 + address 77.68.115.17 + address 77.68.82.147 + address 77.68.49.12 + address 77.68.8.144 + address 77.68.51.202 + address 77.68.101.64 + address 77.68.103.19 + address 77.68.50.91 + address 77.68.24.63 + address 77.68.118.15 + address 77.68.50.198 + address 77.68.77.59 + address 77.68.49.160 + address 77.68.76.191 + address 77.68.126.101 + address 77.68.76.40 + address 77.68.77.42 + address 77.68.100.134 + address 77.68.100.132 + address 77.68.114.93 + address 185.132.36.60 + address 185.132.40.244 + address 77.68.85.18 + address 213.171.214.102 + address 77.68.50.193 + address 88.208.197.160 + address 88.208.197.10 + address 77.68.102.129 + address 109.228.36.79 + address 185.132.38.182 + address 185.132.41.240 + address 77.68.51.214 + address 88.208.196.123 + address 88.208.215.157 + address 77.68.126.22 + address 77.68.4.180 + address 213.171.212.90 + address 77.68.114.205 + address 185.132.43.71 + address 88.208.215.62 + address 77.68.77.114 + address 77.68.48.202 + address 77.68.112.175 + address 77.68.112.90 + address 185.132.40.166 + address 77.68.76.118 + address 77.68.103.120 + address 77.68.33.24 + address 109.228.58.134 + address 109.228.47.223 + address 77.68.31.96 + address 77.68.103.227 + address 213.171.212.203 + address 88.208.196.92 + address 88.208.196.154 + address 185.132.39.44 + address 77.68.76.248 + address 88.208.198.92 + address 109.228.36.37 + address 77.68.77.144 + address 77.68.126.14 + address 88.208.196.91 + address 77.68.100.77 + address 185.132.37.101 + address 77.68.87.164 + address 77.68.77.76 + address 77.68.76.120 + address 77.68.82.157 + address 77.68.93.164 + address 77.68.76.171 + address 88.208.197.135 + address 88.208.197.118 + address 88.208.197.150 + address 88.208.198.69 + address 77.68.34.139 + address 77.68.21.171 + address 88.208.197.60 + address 77.68.85.27 + address 109.228.37.10 + address 88.208.215.61 + address 88.208.199.249 + address 88.208.212.31 + address 109.228.53.243 + address 77.68.48.89 + address 88.208.212.188 + address 88.208.198.251 + address 77.68.76.112 + address 77.68.48.14 + address 88.208.215.19 + address 77.68.77.75 + address 77.68.117.173 + address 88.208.215.121 + address 109.228.39.41 + address 77.68.88.100 + address 77.68.76.108 + address 77.68.115.142 + address 77.68.33.216 + address 77.68.33.37 + address 77.68.50.90 + address 213.171.214.96 + address 88.208.198.66 + address 88.208.198.64 + address 77.68.3.61 + address 77.68.77.219 + address 77.68.77.204 + address 77.68.26.228 + address 77.68.74.232 + address 77.68.118.88 + address 77.68.77.46 + address 77.68.76.48 + address 77.68.76.202 + address 77.68.4.25 + address 77.68.7.114 + address 88.208.197.23 + address 77.68.114.237 + address 77.68.77.222 + address 77.68.112.83 + address 77.68.117.214 + address 88.208.199.141 + address 77.68.77.163 + address 185.132.39.109 + address 77.68.77.44 + address 185.132.37.47 + address 77.68.102.5 + address 77.68.16.247 + address 88.208.212.94 + address 77.68.72.254 + address 77.68.76.212 + address 77.68.77.152 + address 77.68.50.142 + address 88.208.199.46 + address 77.68.78.113 + address 88.208.212.182 + address 77.68.77.181 + address 77.68.15.95 + address 77.68.75.64 + address 213.171.212.71 + address 185.132.40.124 + address 88.208.197.208 + address 88.208.197.129 + address 77.68.76.60 + address 77.68.6.119 + address 77.68.77.185 + address 77.68.77.238 + address 77.68.27.57 + address 77.68.118.102 + address 77.68.79.82 + address 109.228.39.151 + } + address-group G-465-TCP { + address 172.16.255.254 + address 77.68.76.115 + address 77.68.76.141 + address 77.68.76.187 + address 77.68.76.197 + address 77.68.76.209 + address 77.68.76.99 + address 77.68.77.107 + address 77.68.77.129 + address 77.68.77.130 + address 77.68.77.141 + address 77.68.77.150 + address 77.68.77.171 + address 77.68.77.176 + address 77.68.77.190 + address 77.68.77.207 + address 77.68.77.22 + address 77.68.77.32 + address 77.68.77.33 + address 77.68.77.63 + address 77.68.77.92 + address 77.68.77.99 + address 77.68.77.77 + address 77.68.77.192 + address 77.68.84.147 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.77.74 + address 77.68.77.100 + address 77.68.116.221 + address 109.228.60.215 + address 77.68.116.52 + address 77.68.7.172 + address 77.68.95.42 + address 77.68.91.128 + address 77.68.24.112 + address 109.228.37.114 + address 77.68.112.75 + address 77.68.7.67 + address 77.68.113.117 + address 77.68.126.51 + address 77.68.23.35 + address 77.68.10.170 + address 77.68.76.234 + address 213.171.213.31 + address 77.68.78.229 + address 213.171.210.19 + address 109.228.52.186 + address 77.68.77.69 + address 109.228.40.222 + address 77.68.87.212 + address 77.68.28.139 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.117.222 + address 185.132.43.28 + address 77.68.77.214 + address 185.132.38.114 + address 77.68.33.48 + address 77.68.79.89 + address 77.68.76.21 + address 77.68.80.26 + address 77.68.5.95 + address 77.68.100.167 + address 77.68.4.80 + address 77.68.49.152 + address 77.68.112.184 + address 77.68.115.17 + address 77.68.82.147 + address 77.68.50.193 + address 88.208.215.61 + address 213.171.214.96 + address 88.208.198.66 + address 77.68.77.204 + address 77.68.123.177 + address 77.68.77.222 + address 77.68.112.83 + address 77.68.77.185 + address 77.68.79.82 + } + address-group G-587-TCP { + address 172.16.255.254 + address 77.68.76.141 + address 77.68.76.187 + address 77.68.76.197 + address 77.68.76.209 + address 77.68.77.128 + address 77.68.77.129 + address 77.68.77.141 + address 77.68.77.171 + address 77.68.77.190 + address 77.68.77.207 + address 77.68.77.32 + address 77.68.77.33 + address 77.68.77.63 + address 77.68.77.85 + address 77.68.77.92 + address 77.68.77.99 + address 77.68.77.77 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.81.44 + address 77.68.77.100 + address 77.68.92.186 + address 77.68.116.119 + address 77.68.116.221 + address 77.68.120.241 + address 109.228.60.215 + address 77.68.122.241 + address 77.68.116.52 + address 77.68.91.128 + address 77.68.24.112 + address 77.68.77.107 + address 109.228.37.114 + address 77.68.112.75 + address 77.68.77.160 + address 77.68.113.117 + address 77.68.126.51 + address 77.68.23.35 + address 77.68.76.95 + address 77.68.10.170 + address 77.68.76.234 + address 213.171.213.41 + address 213.171.213.31 + address 77.68.78.229 + address 213.171.210.19 + address 109.228.52.186 + address 109.228.40.222 + address 77.68.87.212 + address 185.132.39.219 + address 77.68.28.139 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.117.222 + address 185.132.43.28 + address 77.68.77.215 + address 77.68.77.214 + address 185.132.38.114 + address 77.68.33.48 + address 77.68.76.21 + address 77.68.100.167 + address 77.68.4.80 + address 77.68.49.152 + address 77.68.112.184 + address 77.68.115.17 + address 77.68.82.147 + address 77.68.76.191 + address 77.68.50.193 + address 77.68.77.114 + address 88.208.215.61 + address 77.68.76.112 + address 77.68.33.216 + address 77.68.33.37 + address 77.68.50.90 + address 88.208.198.66 + address 77.68.77.219 + address 77.68.123.177 + address 77.68.77.222 + address 77.68.112.83 + address 77.68.77.152 + address 77.68.79.82 + } + address-group G-993-TCP { + address 172.16.255.254 + address 77.68.76.115 + address 77.68.77.129 + address 77.68.77.130 + address 77.68.77.141 + address 77.68.77.150 + address 77.68.77.171 + address 77.68.77.176 + address 77.68.77.190 + address 77.68.77.207 + address 77.68.77.22 + address 77.68.77.33 + address 77.68.77.49 + address 77.68.77.56 + address 77.68.77.77 + address 77.68.77.192 + address 77.68.84.147 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.81.44 + address 77.68.77.74 + address 77.68.77.100 + address 77.68.92.186 + address 77.68.116.119 + address 77.68.116.221 + address 77.68.120.241 + address 77.68.7.172 + address 77.68.91.128 + address 77.68.23.112 + address 77.68.24.112 + address 77.68.77.107 + address 109.228.37.114 + address 77.68.112.75 + address 77.68.7.67 + address 77.68.113.117 + address 77.68.126.51 + address 77.68.86.148 + address 77.68.23.35 + address 77.68.76.95 + address 213.171.215.184 + address 77.68.25.146 + address 213.171.213.31 + address 213.171.210.19 + address 77.68.79.206 + address 77.68.123.250 + address 77.68.77.69 + address 109.228.40.222 + address 77.68.87.212 + address 77.68.91.22 + address 185.132.39.99 + address 77.68.28.139 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.117.222 + address 77.68.5.155 + address 185.132.43.28 + address 77.68.77.215 + address 77.68.10.152 + address 77.68.73.73 + address 77.68.77.214 + address 185.132.38.114 + address 77.68.33.48 + address 77.68.79.89 + address 77.68.5.95 + address 77.68.4.80 + address 77.68.49.152 + address 213.171.208.40 + address 77.68.115.17 + address 77.68.103.19 + address 185.132.36.60 + address 185.132.40.244 + address 88.208.197.10 + address 77.68.102.129 + address 88.208.215.157 + address 88.208.198.69 + address 88.208.212.188 + address 213.171.214.96 + address 88.208.198.66 + address 77.68.77.204 + address 77.68.74.232 + address 77.68.4.25 + address 77.68.7.114 + address 77.68.123.177 + address 77.68.77.222 + address 77.68.112.83 + address 77.68.79.82 + } + address-group G-995-TCP { + address 172.16.255.254 + address 77.68.76.115 + address 77.68.77.129 + address 77.68.77.171 + address 77.68.77.176 + address 77.68.77.190 + address 77.68.77.22 + address 77.68.77.33 + address 77.68.77.92 + address 77.68.77.77 + address 77.68.84.147 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.77.74 + address 77.68.77.100 + address 77.68.116.221 + address 77.68.120.241 + address 77.68.7.172 + address 77.68.95.42 + address 77.68.91.128 + address 77.68.23.112 + address 77.68.24.112 + address 77.68.77.107 + address 109.228.37.114 + address 77.68.7.67 + address 77.68.126.51 + address 77.68.79.206 + address 77.68.123.250 + address 109.228.52.186 + address 109.228.40.222 + address 77.68.91.22 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.5.155 + address 185.132.43.28 + address 77.68.77.214 + address 185.132.38.114 + address 77.68.79.89 + address 77.68.80.26 + address 77.68.4.80 + address 77.68.49.152 + address 77.68.103.19 + address 77.68.50.193 + address 88.208.197.10 + address 213.171.214.96 + address 88.208.198.66 + address 77.68.74.232 + address 77.68.4.25 + address 77.68.7.114 + address 77.68.77.185 + } + address-group G-1433-TCP { + address 172.16.255.254 + address 77.68.76.94 + address 77.68.30.164 + address 77.68.10.142 + address 77.68.77.95 + address 77.68.126.101 + address 77.68.76.118 + address 77.68.77.75 + } + address-group G-3306-TCP { + address 172.16.255.254 + address 77.68.76.127 + address 77.68.76.187 + address 77.68.76.252 + address 77.68.76.55 + address 77.68.76.80 + address 77.68.77.21 + address 77.68.77.63 + address 77.68.77.81 + address 77.68.77.85 + address 77.68.77.92 + address 77.68.76.241 + address 109.228.56.185 + address 77.68.28.145 + address 77.68.76.114 + address 77.68.17.26 + address 77.68.120.241 + address 77.68.6.32 + address 77.68.91.128 + address 109.228.37.114 + address 77.68.76.169 + address 77.68.76.77 + address 77.68.113.117 + address 77.68.86.148 + address 77.68.76.234 + address 77.68.76.59 + address 77.68.77.202 + address 77.68.28.147 + address 109.228.52.186 + address 77.68.117.222 + address 213.171.213.42 + address 77.68.75.253 + address 77.68.77.215 + address 77.68.79.89 + address 77.68.118.15 + address 109.228.36.79 + address 77.68.33.216 + address 77.68.33.37 + address 77.68.50.90 + address 77.68.76.48 + address 77.68.77.222 + address 77.68.112.83 + address 77.68.77.44 + address 88.208.212.94 + } + address-group G-3389-TCP { + address 172.16.255.254 + address 77.68.76.116 + address 77.68.76.150 + address 77.68.76.203 + address 77.68.76.220 + address 77.68.76.23 + address 77.68.76.241 + address 77.68.76.35 + address 77.68.76.39 + address 77.68.76.47 + address 77.68.76.49 + address 77.68.76.50 + address 77.68.76.58 + address 77.68.76.75 + address 77.68.76.91 + address 77.68.76.93 + address 77.68.76.94 + address 77.68.76.99 + address 77.68.77.115 + address 77.68.77.156 + address 77.68.77.178 + address 77.68.77.199 + address 77.68.77.236 + address 77.68.77.63 + address 77.68.77.71 + address 77.68.77.97 + address 77.68.77.99 + address 77.68.76.107 + address 77.68.76.26 + address 77.68.76.92 + address 77.68.77.38 + address 77.68.21.78 + address 77.68.94.181 + address 77.68.30.164 + address 77.68.23.158 + address 77.68.27.54 + address 77.68.76.142 + address 77.68.117.202 + address 77.68.116.220 + address 77.68.84.155 + address 77.68.120.146 + address 77.68.119.92 + address 77.68.10.142 + address 77.68.6.105 + address 77.68.4.252 + address 77.68.127.151 + address 77.68.77.228 + address 109.228.40.207 + address 77.68.77.24 + address 109.228.35.110 + address 77.68.76.152 + address 77.68.76.77 + address 77.68.113.117 + address 77.68.6.110 + address 77.68.76.96 + address 77.68.127.172 + address 185.132.37.83 + address 77.68.25.124 + address 77.68.3.52 + address 77.68.114.234 + address 77.68.85.73 + address 109.228.38.201 + address 77.68.26.221 + address 77.68.10.152 + address 77.68.73.73 + address 77.68.76.198 + address 77.68.9.75 + address 77.68.79.89 + address 77.68.77.95 + address 77.68.77.65 + address 77.68.100.150 + address 77.68.101.125 + address 77.68.101.124 + address 213.171.208.40 + address 77.68.12.45 + address 77.68.118.86 + address 77.68.77.59 + address 77.68.126.101 + address 213.171.214.102 + address 88.208.197.160 + address 88.208.215.157 + address 77.68.4.180 + address 185.132.43.71 + address 77.68.31.96 + address 109.228.36.37 + address 77.68.77.76 + address 77.68.82.157 + address 109.228.37.10 + address 77.68.77.75 + address 77.68.117.173 + address 88.208.215.121 + address 77.68.115.142 + address 77.68.33.216 + address 77.68.33.37 + address 77.68.50.90 + address 88.208.198.64 + address 77.68.118.88 + address 77.68.114.237 + address 77.68.50.142 + address 77.68.15.95 + address 77.68.75.64 + address 77.68.77.238 + } + address-group G-8080-TCP { + address 172.16.255.254 + address 77.68.76.57 + address 77.68.76.243 + address 77.68.28.145 + address 77.68.76.114 + address 77.68.76.157 + address 77.68.77.248 + address 77.68.77.202 + address 77.68.24.59 + address 77.68.81.218 + address 77.68.77.105 + address 185.132.40.152 + address 109.228.36.119 + address 77.68.121.127 + address 77.68.116.183 + address 77.68.34.139 + address 77.68.88.100 + address 77.68.77.222 + address 77.68.112.83 + address 77.68.77.163 + address 88.208.212.94 + address 77.68.78.113 + address 77.68.15.95 + address 213.171.212.71 + } + address-group G-8443-TCP { + address 172.16.255.254 + address 77.68.76.104 + address 77.68.76.105 + address 77.68.76.127 + address 77.68.76.136 + address 77.68.76.141 + address 77.68.76.148 + address 77.68.76.150 + address 77.68.76.158 + address 77.68.76.187 + address 77.68.76.195 + address 77.68.76.197 + address 77.68.76.20 + address 77.68.76.200 + address 77.68.76.209 + address 77.68.76.217 + address 77.68.76.22 + address 77.68.76.231 + address 77.68.76.235 + address 77.68.76.239 + address 77.68.76.245 + address 77.68.76.247 + address 77.68.76.249 + address 77.68.76.25 + address 77.68.76.251 + address 77.68.76.252 + address 77.68.76.33 + address 77.68.76.37 + address 77.68.76.57 + address 77.68.76.61 + address 77.68.76.74 + address 77.68.76.80 + address 77.68.76.93 + address 77.68.77.100 + address 77.68.77.103 + address 77.68.77.107 + address 77.68.77.108 + address 77.68.77.115 + address 77.68.77.117 + address 77.68.77.128 + address 77.68.77.130 + address 77.68.77.137 + address 77.68.77.139 + address 77.68.77.140 + address 77.68.77.141 + address 77.68.77.151 + address 77.68.77.159 + address 77.68.77.176 + address 77.68.77.190 + address 77.68.77.200 + address 77.68.77.201 + address 77.68.77.207 + address 77.68.77.211 + address 77.68.77.22 + address 77.68.77.227 + address 77.68.77.240 + address 77.68.77.247 + address 77.68.77.253 + address 77.68.77.32 + address 77.68.77.37 + address 77.68.77.49 + address 77.68.77.50 + address 77.68.77.56 + address 77.68.77.68 + address 77.68.77.81 + address 77.68.77.85 + address 77.68.77.88 + address 77.68.77.92 + address 77.68.77.99 + address 77.68.76.211 + address 77.68.76.19 + address 77.68.77.192 + address 77.68.77.254 + address 77.68.77.157 + address 77.68.76.138 + address 77.68.76.139 + address 77.68.76.243 + address 77.68.77.38 + address 77.68.77.62 + address 77.68.91.195 + address 77.68.17.26 + address 77.68.84.147 + address 109.228.56.185 + address 77.68.5.187 + address 77.68.4.24 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.5.241 + address 77.68.77.74 + address 77.68.76.115 + address 77.68.81.44 + address 77.68.90.106 + address 77.68.94.181 + address 77.68.30.133 + address 77.68.4.136 + address 77.68.28.145 + address 77.68.24.112 + address 77.68.92.186 + address 77.68.26.216 + address 77.68.20.231 + address 77.68.118.17 + address 77.68.116.119 + address 77.68.76.142 + address 77.68.7.172 + address 77.68.116.221 + address 77.68.89.183 + address 77.68.83.41 + address 77.68.86.40 + address 77.68.88.164 + address 109.228.56.26 + address 77.68.7.123 + address 77.68.116.220 + address 109.228.60.215 + address 77.68.7.186 + address 77.68.93.246 + address 77.68.120.241 + address 77.68.122.195 + address 77.68.122.89 + address 77.68.81.141 + address 77.68.116.52 + address 77.68.6.105 + address 77.68.76.229 + address 77.68.4.252 + address 77.68.17.186 + address 77.68.91.128 + address 77.68.22.146 + address 77.68.125.32 + address 109.228.36.229 + address 77.68.31.144 + address 77.68.117.142 + address 109.228.37.174 + address 109.228.37.114 + address 77.68.76.169 + address 77.68.112.75 + address 77.68.77.160 + address 109.228.39.249 + address 77.68.7.67 + address 77.68.113.117 + address 77.68.126.51 + address 77.68.86.148 + address 77.68.114.183 + address 109.228.40.194 + address 77.68.90.132 + address 77.68.77.26 + address 77.68.76.96 + address 77.68.77.30 + address 77.68.76.95 + address 77.68.10.170 + address 77.68.120.26 + address 109.228.61.31 + address 77.68.76.59 + address 77.68.120.249 + address 213.171.213.41 + address 77.68.119.14 + address 213.171.215.184 + address 77.68.77.202 + address 77.68.25.146 + address 213.171.213.31 + address 77.68.77.102 + address 213.171.210.19 + address 213.171.213.97 + address 109.228.48.249 + address 109.228.40.195 + address 77.68.127.172 + address 77.68.79.206 + address 109.228.56.242 + address 109.228.46.81 + address 185.132.38.95 + address 77.68.116.36 + address 77.68.120.45 + address 185.132.37.102 + address 77.68.13.137 + address 109.228.36.194 + address 185.132.36.7 + address 185.132.36.24 + address 77.68.77.69 + address 185.132.39.129 + address 77.68.87.212 + address 77.68.76.29 + address 77.68.76.88 + address 77.68.76.181 + address 77.68.76.161 + address 77.68.85.73 + address 77.68.76.219 + address 109.228.38.201 + address 185.132.39.219 + address 77.68.28.139 + address 77.68.81.218 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.117.222 + address 77.68.76.45 + address 185.132.40.56 + address 77.68.75.253 + address 77.68.10.152 + address 77.68.73.73 + address 77.68.77.214 + address 185.132.38.114 + address 185.132.40.90 + address 77.68.79.89 + address 77.68.76.21 + address 77.68.75.45 + address 77.68.24.134 + address 77.68.32.43 + address 77.68.80.26 + address 77.68.17.200 + address 77.68.80.97 + address 77.68.74.209 + address 77.68.77.65 + address 77.68.33.197 + address 77.68.5.95 + address 77.68.23.64 + address 77.68.5.125 + address 77.68.100.167 + address 77.68.4.80 + address 77.68.49.152 + address 77.68.48.105 + address 77.68.48.81 + address 77.68.49.12 + address 213.171.212.89 + address 77.68.76.44 + address 77.68.77.239 + address 77.68.77.59 + address 77.68.126.101 + address 77.68.76.40 + address 77.68.114.93 + address 77.68.50.193 + address 88.208.197.160 + address 109.228.36.79 + address 185.132.38.182 + address 88.208.196.123 + address 88.208.215.157 + address 77.68.76.118 + address 77.68.103.227 + address 88.208.196.92 + address 185.132.39.44 + address 88.208.198.92 + address 77.68.126.14 + address 88.208.196.91 + address 77.68.100.77 + address 185.132.37.101 + address 77.68.76.120 + address 213.171.212.114 + address 77.68.34.139 + address 88.208.215.61 + address 88.208.212.31 + address 109.228.53.243 + address 77.68.103.56 + address 213.171.214.96 + address 88.208.198.66 + address 77.68.77.219 + address 77.68.4.25 + address 77.68.7.114 + address 77.68.77.222 + address 77.68.112.83 + address 77.68.77.44 + address 77.68.72.254 + address 77.68.78.113 + address 213.171.212.71 + address 185.132.40.124 + address 88.208.197.208 + address 77.68.77.238 + address 77.68.79.82 + } + address-group G-8447-TCP { + address 172.16.255.254 + address 77.68.76.104 + address 77.68.76.105 + address 77.68.76.127 + address 77.68.76.136 + address 77.68.76.141 + address 77.68.76.148 + address 77.68.76.150 + address 77.68.76.158 + address 77.68.76.187 + address 77.68.76.195 + address 77.68.76.197 + address 77.68.76.20 + address 77.68.76.209 + address 77.68.76.22 + address 77.68.76.231 + address 77.68.76.235 + address 77.68.76.239 + address 77.68.76.245 + address 77.68.76.25 + address 77.68.76.252 + address 77.68.76.33 + address 77.68.76.37 + address 77.68.76.57 + address 77.68.76.61 + address 77.68.76.74 + address 77.68.76.93 + address 77.68.77.100 + address 77.68.77.103 + address 77.68.77.107 + address 77.68.77.108 + address 77.68.77.117 + address 77.68.77.128 + address 77.68.77.130 + address 77.68.77.137 + address 77.68.77.139 + address 77.68.77.141 + address 77.68.77.151 + address 77.68.77.159 + address 77.68.77.176 + address 77.68.77.190 + address 77.68.77.200 + address 77.68.77.201 + address 77.68.77.207 + address 77.68.77.211 + address 77.68.77.22 + address 77.68.77.227 + address 77.68.77.240 + address 77.68.77.247 + address 77.68.77.253 + address 77.68.77.32 + address 77.68.77.37 + address 77.68.77.49 + address 77.68.77.50 + address 77.68.77.56 + address 77.68.77.68 + address 77.68.77.81 + address 77.68.77.85 + address 77.68.77.88 + address 77.68.77.92 + address 77.68.77.99 + address 77.68.76.211 + address 77.68.76.19 + address 77.68.77.192 + address 77.68.77.254 + address 77.68.77.157 + address 77.68.76.138 + address 77.68.76.139 + address 77.68.91.195 + address 77.68.17.26 + address 109.228.56.185 + address 77.68.84.147 + address 77.68.5.187 + address 77.68.4.24 + address 77.68.4.74 + address 77.68.6.202 + address 77.68.5.241 + address 77.68.77.74 + address 77.68.81.44 + address 77.68.90.106 + address 77.68.94.181 + address 77.68.4.136 + address 77.68.28.145 + address 77.68.24.112 + address 77.68.92.186 + address 77.68.26.216 + address 77.68.20.231 + address 77.68.118.17 + address 77.68.116.119 + address 77.68.76.142 + address 77.68.7.172 + address 77.68.83.41 + address 77.68.116.221 + address 77.68.86.40 + address 77.68.88.164 + address 109.228.56.26 + address 77.68.7.123 + address 77.68.116.220 + address 109.228.60.215 + address 77.68.7.186 + address 77.68.93.246 + address 77.68.120.241 + address 77.68.122.195 + address 77.68.122.89 + address 77.68.81.141 + address 77.68.116.52 + address 77.68.6.105 + address 77.68.76.229 + address 77.68.4.252 + address 77.68.17.186 + address 77.68.91.128 + address 77.68.22.146 + address 77.68.125.32 + address 109.228.36.229 + address 77.68.31.144 + address 77.68.117.142 + address 109.228.37.174 + address 109.228.37.114 + address 77.68.112.75 + address 77.68.77.160 + address 109.228.39.249 + address 77.68.7.67 + address 77.68.113.117 + address 77.68.126.51 + address 77.68.86.148 + address 77.68.114.183 + address 109.228.40.194 + address 77.68.90.132 + address 77.68.76.96 + address 77.68.77.30 + address 77.68.76.95 + address 77.68.10.170 + address 109.228.61.31 + address 77.68.76.59 + address 77.68.120.249 + address 213.171.213.41 + address 213.171.215.184 + address 77.68.25.146 + address 213.171.213.31 + address 77.68.77.102 + address 213.171.210.19 + address 213.171.213.97 + address 109.228.48.249 + address 77.68.127.172 + address 77.68.79.206 + address 109.228.56.242 + address 109.228.46.81 + address 185.132.38.95 + address 77.68.116.36 + address 109.228.36.194 + address 185.132.36.7 + address 185.132.36.24 + address 77.68.77.69 + address 185.132.39.129 + address 77.68.87.212 + address 77.68.76.88 + address 77.68.76.181 + address 77.68.76.219 + address 185.132.39.219 + address 77.68.28.139 + address 77.68.4.111 + address 77.68.77.174 + address 77.68.117.222 + address 77.68.77.231 + address 77.68.76.45 + address 185.132.40.56 + address 77.68.10.152 + address 77.68.73.73 + address 77.68.77.214 + address 185.132.38.114 + address 185.132.40.90 + address 77.68.79.89 + address 77.68.76.21 + address 77.68.75.45 + address 77.68.24.134 + address 77.68.32.43 + address 77.68.80.26 + address 77.68.17.200 + address 77.68.80.97 + address 77.68.74.209 + address 77.68.33.197 + address 77.68.5.95 + address 77.68.5.125 + address 77.68.100.167 + address 77.68.4.80 + address 77.68.49.152 + address 77.68.48.105 + address 77.68.48.81 + address 77.68.49.12 + address 213.171.212.89 + address 77.68.76.44 + address 77.68.77.239 + address 77.68.77.59 + address 77.68.126.101 + address 77.68.114.93 + address 77.68.50.193 + address 88.208.197.160 + address 109.228.36.79 + address 185.132.38.182 + address 88.208.196.123 + address 88.208.215.157 + address 77.68.76.118 + address 77.68.103.227 + address 88.208.196.92 + address 185.132.39.44 + address 88.208.198.92 + address 77.68.126.14 + address 88.208.196.91 + address 77.68.100.77 + address 185.132.37.101 + address 77.68.76.120 + address 213.171.212.114 + address 77.68.34.139 + address 88.208.215.61 + address 88.208.212.31 + address 109.228.53.243 + address 77.68.103.56 + address 213.171.214.96 + address 88.208.198.66 + address 77.68.77.219 + address 77.68.77.204 + address 77.68.76.48 + address 77.68.4.25 + address 77.68.7.114 + address 77.68.77.222 + address 77.68.112.83 + address 77.68.72.254 + address 77.68.78.113 + address 213.171.212.71 + address 185.132.40.124 + address 88.208.197.208 + address 77.68.79.82 + } + address-group G-10000-TCP { + address 172.16.255.254 + address 77.68.76.177 + address 77.68.76.54 + address 77.68.30.133 + address 77.68.76.114 + address 77.68.11.140 + address 77.68.76.112 + address 77.68.78.113 + } + address-group LAN_ADDRESSES { + address 10.255.255.2 + address 10.255.255.3 + } + address-group MANAGEMENT_ADDRESSES { + address 82.223.200.175 + address 82.223.200.177 + } + address-group NAGIOS_PROBES { + address 77.68.76.16 + address 77.68.77.16 + } + address-group NAS_ARRAYS { + address 10.7.197.251 + address 10.7.197.252 + address 10.7.197.253 + address 10.7.197.254 + } + address-group NAS_DOMAIN_CONTROLLERS { + address 10.7.197.16 + address 10.7.197.17 + } + address-group NLB_ADDRESSES { + address 109.228.63.15 + address 109.228.63.16 + address 109.228.63.132 + address 109.228.63.133 + } + network-group NAS_NETWORKS { + network 10.7.197.0/24 + } + network-group RFC1918 { + network 10.0.0.0/8 + network 172.16.0.0/12 + network 192.168.0.0/16 + } + network-group TRANSFER_NETS { + network 109.228.63.128/25 + } + } + ipv6-receive-redirects disable + ipv6-src-route disable + ip-src-route disable + log-martians enable + name LAN-INBOUND { + default-action drop + rule 10 { + action drop + description "Anti-spoofing non-cluster addresses" + source { + group { + address-group !CLUSTER_ADDRESSES + } + } + } + rule 20 { + action drop + description "Drop traffic to datacenter transfer net" + destination { + group { + network-group TRANSFER_NETS + } + } + source { + group { + address-group CLUSTER_ADDRESSES + } + } + } + rule 400 { + action drop + description Anti-spoofing_10.255.255.2 + source { + address 10.255.255.2 + mac-address !00:50:56:af:61:20 + } + } + rule 401 { + action drop + description Anti-spoofing_77.68.126.51 + source { + address 77.68.126.51 + mac-address !00:50:56:03:df:06 + } + } + rule 402 { + action drop + description Anti-spoofing_109.228.36.37 + source { + address 109.228.36.37 + mac-address !00:50:56:38:c4:2c + } + } + rule 403 { + action drop + description Anti-spoofing_77.68.117.214 + source { + address 77.68.117.214 + mac-address !00:50:56:00:28:c3 + } + } + rule 404 { + action drop + description Anti-spoofing_77.68.127.172 + source { + address 77.68.127.172 + mac-address !00:50:56:08:ce:ec + } + } + rule 405 { + action drop + description Anti-spoofing_77.68.117.142 + source { + address 77.68.117.142 + mac-address !00:50:56:1a:02:40 + } + } + rule 406 { + action drop + description Anti-spoofing_77.68.14.88 + source { + address 77.68.14.88 + mac-address !00:50:56:3c:79:85 + } + } + rule 407 { + action drop + description Anti-spoofing_77.68.17.200 + source { + address 77.68.17.200 + mac-address !00:50:56:0c:1b:57 + } + } + rule 408 { + action drop + description Anti-spoofing_77.68.120.229 + source { + address 77.68.120.229 + mac-address !00:50:56:18:af:65 + } + } + rule 410 { + action drop + description Anti-spoofing_10.255.255.3 + source { + address 10.255.255.3 + mac-address !00:50:56:af:cd:42 + } + } + rule 411 { + action drop + description Anti-spoofing_77.68.4.242 + source { + address 77.68.4.242 + mac-address !00:50:56:25:d9:34 + } + } + rule 412 { + action drop + description Anti-spoofing_77.68.113.117 + source { + address 77.68.113.117 + mac-address !00:50:56:36:ea:1d + } + } + rule 413 { + action drop + description Anti-spoofing_213.171.213.242 + source { + address 213.171.213.242 + mac-address !00:50:56:29:dd:5c + } + } + rule 414 { + action drop + description Anti-spoofing_77.68.86.148 + source { + address 77.68.86.148 + mac-address !00:50:56:01:91:19 + } + } + rule 418 { + action drop + description Anti-spoofing_213.171.212.203 + source { + address 213.171.212.203 + mac-address !00:50:56:01:c3:39 + } + } + rule 419 { + action drop + description Anti-spoofing_77.68.114.234 + source { + address 77.68.114.234 + mac-address !00:50:56:1b:72:cd + } + } + rule 420 { + action drop + description Anti-spoofing_10.255.255.4 + source { + address 10.255.255.4 + mac-address !00:50:56:af:09:7d + } + } + rule 421 { + action drop + description Anti-spoofing_213.171.212.171 + source { + address 213.171.212.171 + mac-address !00:50:56:12:54:58 + } + } + rule 422 { + action drop + description Anti-spoofing_77.68.114.183 + source { + address 77.68.114.183 + mac-address !00:50:56:3d:9b:eb + } + } + rule 423 { + action drop + description Anti-spoofing_213.171.213.41 + source { + address 213.171.213.41 + mac-address !00:50:56:2a:ef:a2 + } + } + rule 424 { + action drop + description Anti-spoofing_77.68.90.132 + source { + address 77.68.90.132 + mac-address !00:50:56:28:04:1e + } + } + rule 425 { + action drop + description Anti-spoofing_10.255.255.5 + source { + address 10.255.255.5 + mac-address !00:50:56:af:3b:bb + } + } + rule 426 { + action drop + description Anti-spoofing_213.171.213.175 + source { + address 213.171.213.175 + mac-address !00:50:56:0d:d4:b1 + } + } + rule 427 { + action drop + description Anti-spoofing_109.228.39.151 + source { + address 109.228.39.151 + mac-address !00:50:56:39:67:8d + } + } + rule 428 { + action drop + description Anti-spoofing_77.68.112.167 + source { + address 77.68.112.167 + mac-address !00:50:56:32:24:c9 + } + } + rule 429 { + action drop + description Anti-spoofing_109.228.40.194 + source { + address 109.228.40.194 + mac-address !00:50:56:19:49:71 + } + } + rule 430 { + action drop + description Anti-spoofing_77.68.76.12 + source { + address 77.68.76.12 + mac-address !00:50:56:af:09:7d + } + } + rule 431 { + action drop + description Anti-spoofing_213.171.213.97 + source { + address 213.171.213.97 + mac-address !00:50:56:15:d9:89 + } + } + rule 432 { + action drop + description Anti-spoofing_77.68.16.247 + source { + address 77.68.16.247 + mac-address !00:50:56:01:49:07 + } + } + rule 433 { + action drop + description Anti-spoofing_77.68.33.48 + source { + address 77.68.33.48 + mac-address !00:50:56:11:0e:07 + } + } + rule 434 { + action drop + description Anti-spoofing_77.68.6.110 + source { + address 77.68.6.110 + mac-address !00:50:56:31:76:8a + } + } + rule 435 { + action drop + description Anti-spoofing_77.68.77.12 + source { + address 77.68.77.12 + mac-address !00:50:56:af:3b:bb + } + } + rule 436 { + action drop + description Anti-spoofing_213.171.215.252 + source { + address 213.171.215.252 + mac-address !00:50:56:11:88:0a + } + } + rule 437 { + action drop + description Anti-spoofing_88.208.197.208 + source { + address 88.208.197.208 + mac-address !00:50:56:1d:97:93 + } + } + rule 438 { + action drop + description Anti-spoofing_213.171.212.89 + source { + address 213.171.212.89 + mac-address !00:50:56:36:8d:bf + } + } + rule 439 { + action drop + description Anti-spoofing_77.68.93.125 + source { + address 77.68.93.125 + mac-address !00:50:56:19:f1:6f + } + } + rule 440 { + action drop + description Anti-spoofing_probe_77.68.76.16 + source { + address 77.68.76.16 + mac-address !00:50:56:aa:48:d4 + } + } + rule 441 { + action drop + description Anti-spoofing_213.171.214.96 + source { + address 213.171.214.96 + mac-address !00:50:56:0c:45:b5 + } + } + rule 442 { + action drop + description Anti-spoofing_77.68.76.176 + source { + address 77.68.76.176 + mac-address !00:50:56:2b:e6:f7 + } + } + rule 444 { + action drop + description Anti-spoofing_213.171.212.172 + source { + address 213.171.212.172 + mac-address !00:50:56:35:ab:43 + } + } + rule 446 { + action drop + description Anti-spoofing_185.132.38.95 + source { + address 185.132.38.95 + mac-address !00:50:56:07:a6:f7 + } + } + rule 447 { + action drop + description Anti-spoofing_185.132.38.248 + source { + address 185.132.38.248 + mac-address !00:50:56:19:e5:16 + } + } + rule 448 { + action drop + description Anti-spoofing_109.228.52.186 + source { + address 109.228.52.186 + mac-address !00:50:56:20:80:4f + } + } + rule 449 { + action drop + description Anti-spoofing_213.171.213.31 + source { + address 213.171.213.31 + mac-address !00:50:56:34:e3:61 + } + } + rule 450 { + action drop + description Anti-spoofing_probe_77.68.77.16 + source { + address 77.68.77.16 + mac-address !00:50:56:aa:4a:32 + } + } + rule 451 { + action drop + description Anti-spoofing_213.171.210.59 + source { + address 213.171.210.59 + mac-address !00:50:56:10:74:b6 + } + } + rule 452 { + action drop + description Anti-spoofing_185.132.36.7 + source { + address 185.132.36.7 + mac-address !00:50:56:17:24:16 + } + } + rule 453 { + action drop + description Anti-spoofing_213.171.212.71 + source { + address 213.171.212.71 + mac-address !00:50:56:1d:50:e0 + } + } + rule 454 { + action drop + description Anti-spoofing_213.171.208.58 + source { + address 213.171.208.58 + mac-address !00:50:56:05:1c:70 + } + } + rule 455 { + action drop + description Anti-spoofing_77.68.77.69 + source { + address 77.68.77.69 + mac-address !00:50:56:17:f9:d1 + } + } + rule 456 { + action drop + description Anti-spoofing_77.68.25.130 + source { + address 77.68.25.130 + mac-address !00:50:56:3c:92:ff + } + } + rule 457 { + action drop + description Anti-spoofing_213.171.215.184 + source { + address 213.171.215.184 + mac-address !00:50:56:18:84:ff + } + } + rule 458 { + action drop + description Anti-spoofing_77.68.74.39 + source { + address 77.68.74.39 + mac-address !00:50:56:0a:41:ee + } + } + rule 459 { + action drop + description Anti-spoofing_109.228.56.242 + source { + address 109.228.56.242 + mac-address !00:50:56:28:8c:ff + } + } + rule 460 { + action drop + description Anti-spoofing_77.68.76.13 + source { + address 77.68.76.13 + mac-address !00:50:56:8f:62:1e + } + } + rule 461 { + action drop + description Anti-spoofing_77.68.13.76 + source { + address 77.68.13.76 + mac-address !00:50:56:2c:c7:38 + } + } + rule 462 { + action drop + description Anti-spoofing_77.68.119.188 + source { + address 77.68.119.188 + mac-address !00:50:56:02:1c:16 + } + } + rule 463 { + action drop + description Anti-spoofing_109.228.46.81 + source { + address 109.228.46.81 + mac-address !00:50:56:31:1f:8a + } + } + rule 464 { + action drop + description Anti-spoofing_77.68.25.146 + source { + address 77.68.25.146 + mac-address !00:50:56:07:cc:76 + } + } + rule 465 { + action drop + description Anti-spoofing_77.68.76.14 + source { + address 77.68.76.14 + mac-address !00:50:56:8f:6a:24 + } + } + rule 466 { + action drop + description Anti-spoofing_77.68.116.36 + source { + address 77.68.116.36 + mac-address !00:50:56:1c:c9:83 + } + } + rule 467 { + action drop + description Anti-spoofing_185.132.43.113 + source { + address 185.132.43.113 + mac-address !00:50:56:22:79:ac + } + } + rule 468 { + action drop + description Anti-spoofing_213.171.210.19 + source { + address 213.171.210.19 + mac-address !00:50:56:32:6c:19 + } + } + rule 469 { + action drop + description Anti-spoofing_77.68.113.164 + source { + address 77.68.113.164 + mac-address !00:50:56:07:28:41 + } + } + rule 470 { + action drop + description Anti-spoofing_77.68.77.13 + source { + address 77.68.77.13 + mac-address !00:50:56:8f:62:1e + } + } + rule 471 { + action drop + description Anti-spoofing_213.171.211.128 + source { + address 213.171.211.128 + mac-address !00:50:56:37:b2:85 + } + } + rule 472 { + action drop + description Anti-spoofing_77.68.120.45 + source { + address 77.68.120.45 + mac-address !00:50:56:13:5e:ca + } + } + rule 473 { + action drop + description Anti-spoofing_77.68.25.124 + source { + address 77.68.25.124 + mac-address !00:50:56:2f:27:08 + } + } + rule 474 { + action drop + description Anti-spoofing_77.68.33.68 + source { + address 77.68.33.68 + mac-address !00:50:56:1c:96:48 + } + } + rule 475 { + action drop + description Anti-spoofing_77.68.77.14 + source { + address 77.68.77.14 + mac-address !00:50:56:8f:6a:24 + } + } + rule 476 { + action drop + description Anti-spoofing_109.228.48.249 + source { + address 109.228.48.249 + mac-address !00:50:56:06:32:ac + } + } + rule 477 { + action drop + description Anti-spoofing_109.228.40.195 + source { + address 109.228.40.195 + mac-address !00:50:56:21:46:3e + } + } + rule 478 { + action drop + description Anti-spoofing_213.171.215.43 + source { + address 213.171.215.43 + mac-address !00:50:56:24:c0:53 + } + } + rule 479 { + action drop + description Anti-spoofing_185.132.37.101 + source { + address 185.132.37.101 + mac-address !00:50:56:2c:08:73 + } + } + rule 480 { + action drop + description Anti-spoofing_109.228.53.243 + source { + address 109.228.53.243 + mac-address !00:50:56:31:d1:1a + } + } + rule 481 { + action drop + description Anti-spoofing_77.68.81.218 + source { + address 77.68.81.218 + mac-address !00:50:56:03:e1:62 + } + } + rule 482 { + action drop + description Anti-spoofing_77.68.102.5 + source { + address 77.68.102.5 + mac-address !00:50:56:12:a3:05 + } + } + rule 483 { + action drop + description Anti-spoofing_77.68.114.93 + source { + address 77.68.114.93 + mac-address !00:50:56:3c:d8:18 + } + } + rule 485 { + action drop + description Anti-spoofing_77.68.76.137 + source { + address 77.68.76.137 + mac-address !00:50:56:25:38:78 + } + } + rule 486 { + action drop + description Anti-spoofing_77.68.75.253 + source { + address 77.68.75.253 + mac-address !00:50:56:32:f9:d7 + } + } + rule 487 { + action drop + description Anti-spoofing_77.68.6.119 + source { + address 77.68.6.119 + mac-address !00:50:56:2a:06:e0 + } + } + rule 488 { + action drop + description Anti-spoofing_185.132.39.68 + source { + address 185.132.39.68 + mac-address !00:50:56:22:2e:b5 + } + } + rule 489 { + action drop + description Anti-spoofing_77.68.5.95 + source { + address 77.68.5.95 + mac-address !00:50:56:34:d6:94 + } + } + rule 490 { + action drop + description Anti-spoofing_109.228.36.194 + source { + address 109.228.36.194 + mac-address !00:50:56:02:d4:bb + } + } + rule 491 { + action drop + description Anti-spoofing_77.68.34.50 + source { + address 77.68.34.50 + mac-address !00:50:56:07:df:24 + } + } + rule 492 { + action drop + description Anti-spoofing_77.68.27.18 + source { + address 77.68.27.18 + mac-address !00:50:56:1c:9d:9e + } + } + rule 493 { + action drop + description Anti-spoofing_77.68.28.147 + source { + address 77.68.28.147 + mac-address !00:50:56:29:e0:70 + } + } + rule 494 { + action drop + description Anti-spoofing_77.68.123.250 + source { + address 77.68.123.250 + mac-address !00:50:56:0d:49:c0 + } + } + rule 495 { + action drop + description Anti-spoofing_185.132.39.129 + source { + address 185.132.39.129 + mac-address !00:50:56:29:5a:4c + } + } + rule 496 { + action drop + description Anti-spoofing_185.132.36.24 + source { + address 185.132.36.24 + mac-address !00:50:56:12:df:2d + } + } + rule 497 { + action drop + description Anti-spoofing_185.132.38.114 + source { + address 185.132.38.114 + mac-address !00:50:56:1d:ce:df + } + } + rule 498 { + action drop + description Anti-spoofing_185.132.36.148 + source { + address 185.132.36.148 + mac-address !00:50:56:04:d1:7e + } + } + rule 499 { + action drop + description Anti-spoofing_185.132.36.142 + source { + address 185.132.36.142 + mac-address !00:50:56:13:22:d1 + } + } + rule 500 { + action drop + description Anti-spoofing_77.68.77.67 + source { + address 77.68.77.67 + mac-address !00:50:56:26:3e:0a + } + } + rule 501 { + action drop + description Anti-spoofing_185.132.39.44 + source { + address 185.132.39.44 + mac-address !00:50:56:32:a0:22 + } + } + rule 502 { + action drop + description Anti-spoofing_77.68.76.114 + source { + address 77.68.76.114 + mac-address !00:50:56:32:42:42 + } + } + rule 503 { + action drop + description Anti-spoofing_77.68.77.103 + source { + address 77.68.77.103 + mac-address !00:50:56:1e:6d:9b + } + } + rule 504 { + action drop + description Anti-spoofing_77.68.77.130 + source { + address 77.68.77.130 + mac-address !00:50:56:24:79:76 + } + } + rule 505 { + action drop + description Anti-spoofing_77.68.76.245 + source { + address 77.68.76.245 + mac-address !00:50:56:1d:0f:83 + } + } + rule 506 { + action drop + description Anti-spoofing_77.68.118.17 + source { + address 77.68.118.17 + mac-address !00:50:56:18:d3:d1 + } + } + rule 507 { + action drop + description Anti-spoofing_77.68.79.82 + source { + address 77.68.79.82 + mac-address !00:50:56:22:e9:9e + } + } + rule 509 { + action drop + description Anti-spoofing_77.68.77.85 + source { + address 77.68.77.85 + mac-address !00:50:56:1d:40:33 + } + } + rule 510 { + action drop + description Anti-spoofing_77.68.76.45 + source { + address 77.68.76.45 + mac-address !00:50:56:18:dc:fe + } + } + rule 511 { + action drop + description Anti-spoofing_77.68.77.144 + source { + address 77.68.77.144 + mac-address !00:50:56:3c:9a:1a + } + } + rule 512 { + action drop + description Anti-spoofing_77.68.77.105 + source { + address 77.68.77.105 + mac-address !00:50:56:1f:f9:c9 + } + } + rule 513 { + action drop + description Anti-spoofing_77.68.12.250 + source { + address 77.68.12.250 + mac-address !00:50:56:3e:06:ca + } + } + rule 514 { + action drop + description Anti-spoofing_77.68.76.76 + source { + address 77.68.76.76 + mac-address !00:50:56:03:1f:db + } + } + rule 515 { + action drop + description Anti-spoofing_185.132.36.17 + source { + address 185.132.36.17 + mac-address !00:50:56:36:7a:94 + } + } + rule 516 { + action drop + description Anti-spoofing_77.68.76.122 + source { + address 77.68.76.122 + mac-address !00:50:56:20:3d:43 + } + } + rule 517 { + action drop + description Anti-spoofing_77.68.76.104 + source { + address 77.68.76.104 + mac-address !00:50:56:3c:80:ff + } + } + rule 518 { + action drop + description Anti-spoofing_77.68.114.136 + source { + address 77.68.114.136 + mac-address !00:50:56:38:34:6e + } + } + rule 519 { + action drop + description Anti-spoofing_77.68.77.115 + source { + address 77.68.77.115 + mac-address !00:50:56:2c:ad:ee + } + } + rule 520 { + action drop + description Anti-spoofing_77.68.77.178 + source { + address 77.68.77.178 + mac-address !00:50:56:14:c1:42 + } + } + rule 521 { + action drop + description Anti-spoofing_77.68.76.239 + source { + address 77.68.76.239 + mac-address !00:50:56:0d:5a:47 + } + } + rule 522 { + action drop + description Anti-spoofing_77.68.87.164 + source { + address 77.68.87.164 + mac-address !00:50:56:11:19:46 + } + } + rule 523 { + action drop + description Anti-spoofing_77.68.15.95 + source { + address 77.68.15.95 + mac-address !00:50:56:16:04:4e + } + } + rule 524 { + action drop + description Anti-spoofing_77.68.4.39 + source { + address 77.68.4.39 + mac-address !00:50:56:06:57:b6 + } + } + rule 525 { + action drop + description Anti-spoofing_77.68.76.30 + source { + address 77.68.76.30 + mac-address !00:50:56:25:b8:e3 + } + } + rule 526 { + action drop + description Anti-spoofing_77.68.77.249 + source { + address 77.68.77.249 + mac-address !00:50:56:36:5f:b3 + } + } + rule 527 { + action drop + description Anti-spoofing_77.68.76.59 + source { + address 77.68.76.59 + mac-address !00:50:56:06:e8:bb + } + } + rule 528 { + action drop + description Anti-spoofing_77.68.8.144 + source { + address 77.68.8.144 + mac-address !00:50:56:28:58:e5 + } + } + rule 529 { + action drop + description Anti-spoofing_77.68.77.44 + source { + address 77.68.77.44 + mac-address !00:50:56:31:c0:9d + } + } + rule 530 { + action drop + description Anti-spoofing_77.68.77.200 + source { + address 77.68.77.200 + mac-address !00:50:56:15:2e:a4 + } + } + rule 531 { + action drop + description Anti-spoofing_77.68.77.228 + source { + address 77.68.77.228 + mac-address !00:50:56:23:e4:44 + } + } + rule 532 { + action drop + description Anti-spoofing_77.68.4.25 + source { + address 77.68.4.25 + mac-address !00:50:56:33:0d:5e + } + } + rule 534 { + action drop + description Anti-spoofing_77.68.76.191 + source { + address 77.68.76.191 + mac-address !00:50:56:10:72:7c + } + } + rule 535 { + action drop + description Anti-spoofing_77.68.117.29 + source { + address 77.68.117.29 + mac-address !00:50:56:0c:e4:e3 + } + } + rule 536 { + action drop + description Anti-spoofing_213.171.212.90 + source { + address 213.171.212.90 + mac-address !00:50:56:35:fc:da + } + } + rule 537 { + action drop + description Anti-spoofing_77.68.76.102 + source { + address 77.68.76.102 + mac-address !00:50:56:35:87:43 + } + } + rule 538 { + action drop + description Anti-spoofing_185.132.39.37 + source { + address 185.132.39.37 + mac-address !00:50:56:21:72:64 + } + } + rule 539 { + action drop + description Anti-spoofing_185.132.38.142 + source { + address 185.132.38.142 + mac-address !00:50:56:09:e8:30 + } + } + rule 540 { + action drop + description Anti-spoofing_77.68.77.26 + source { + address 77.68.77.26 + mac-address !00:50:56:10:ec:c2 + } + } + rule 541 { + action drop + description Anti-spoofing_77.68.76.152 + source { + address 77.68.76.152 + mac-address !00:50:56:2b:79:48 + } + } + rule 542 { + action drop + description Anti-spoofing_185.132.37.83 + source { + address 185.132.37.83 + mac-address !00:50:56:09:b3:41 + } + } + rule 543 { + action drop + description Anti-spoofing_77.68.77.212 + source { + address 77.68.77.212 + mac-address !00:50:56:07:ab:f2 + } + } + rule 544 { + action drop + description Anti-spoofing_77.68.75.64 + source { + address 77.68.75.64 + mac-address !00:50:56:07:e2:85 + } + } + rule 546 { + action drop + description Anti-spoofing_77.68.85.73 + source { + address 77.68.85.73 + mac-address !00:50:56:14:68:9c + } + } + rule 547 { + action drop + description Anti-spoofing_77.68.116.119 + source { + address 77.68.116.119 + mac-address !00:50:56:0f:68:91 + } + } + rule 548 { + action drop + description Anti-spoofing_77.68.76.142 + source { + address 77.68.76.142 + mac-address !50:9a:4c:74:07:ea + } + } + rule 549 { + action drop + description Anti-spoofing_77.68.76.211 + source { + address 77.68.76.211 + mac-address !00:50:56:18:9d:15 + } + } + rule 550 { + action drop + description Anti-spoofing_77.68.76.60 + source { + address 77.68.76.60 + mac-address !00:50:56:2b:07:02 + } + } + rule 551 { + action drop + description Anti-spoofing_77.68.77.253 + source { + address 77.68.77.253 + mac-address !00:50:56:30:a5:77 + } + } + rule 552 { + action drop + description Anti-spoofing_77.68.75.245 + source { + address 77.68.75.245 + mac-address !00:50:56:12:00:e9 + } + } + rule 553 { + action drop + description Anti-spoofing_185.132.37.102 + source { + address 185.132.37.102 + mac-address !00:50:56:3d:ae:26 + } + } + rule 554 { + action drop + description Anti-spoofing_77.68.120.31 + source { + address 77.68.120.31 + mac-address !00:50:56:1f:29:84 + } + } + rule 555 { + action drop + description Anti-spoofing_77.68.76.54 + source { + address 77.68.76.54 + mac-address !00:50:56:30:b4:74 + } + } + rule 556 { + action drop + description Anti-spoofing_88.208.196.154 + source { + address 88.208.196.154 + mac-address !00:50:56:14:6f:a8 + } + } + rule 557 { + action drop + description Anti-spoofing_185.132.40.152 + source { + address 185.132.40.152 + mac-address !00:50:56:24:25:3c + } + } + rule 558 { + action drop + description Anti-spoofing_77.68.76.33 + source { + address 77.68.76.33 + mac-address !00:50:56:3c:9b:bc + } + } + rule 559 { + action drop + description Anti-spoofing_77.68.12.195 + source { + address 77.68.12.195 + mac-address !00:50:56:3d:52:1a + } + } + rule 560 { + action drop + description Anti-spoofing_77.68.77.114 + source { + address 77.68.77.114 + mac-address !00:50:56:06:80:89 + } + } + rule 561 { + action drop + description Anti-spoofing_77.68.77.176 + source { + address 77.68.77.176 + mac-address !00:50:56:3e:2b:da + } + } + rule 562 { + action drop + description Anti-spoofing_109.228.40.222 + source { + address 109.228.40.222 + mac-address !00:50:56:0a:dc:63 + } + } + rule 563 { + action drop + description Anti-spoofing_77.68.77.219 + source { + address 77.68.77.219 + mac-address !00:50:56:13:82:67 + } + } + rule 564 { + action drop + description Anti-spoofing_77.68.77.19 + source { + address 77.68.77.19 + mac-address !00:50:56:36:e3:b1 + } + } + rule 565 { + action drop + description Anti-spoofing_77.68.74.85 + source { + address 77.68.74.85 + mac-address !00:50:56:13:b7:2d + } + } + rule 566 { + action drop + description Anti-spoofing_77.68.116.221 + source { + address 77.68.116.221 + mac-address !00:50:56:24:67:bd + } + } + rule 567 { + action drop + description Anti-spoofing_77.68.77.22 + source { + address 77.68.77.22 + mac-address !00:50:56:07:09:ae + } + } + rule 568 { + action drop + description Anti-spoofing_77.68.112.184 + source { + address 77.68.112.184 + mac-address !00:50:56:2a:db:d3 + } + } + rule 569 { + action drop + description Anti-spoofing_77.68.77.248 + source { + address 77.68.77.248 + mac-address !00:50:56:18:03:92 + } + } + rule 570 { + action drop + description Anti-spoofing_77.68.76.161 + source { + address 77.68.76.161 + mac-address !00:50:56:34:57:75 + } + } + rule 571 { + action drop + description Anti-spoofing_77.68.77.56 + source { + address 77.68.77.56 + mac-address !00:50:56:38:22:ae + } + } + rule 572 { + action drop + description Anti-spoofing_77.68.77.129 + source { + address 77.68.77.129 + mac-address !00:50:56:08:d9:20 + } + } + rule 573 { + action drop + description Anti-spoofing_77.68.77.205 + source { + address 77.68.77.205 + mac-address !00:50:56:35:f1:c3 + } + } + rule 574 { + action drop + description Anti-spoofing_77.68.77.140 + source { + address 77.68.77.140 + mac-address !00:50:56:1b:2d:c7 + } + } + rule 575 { + action drop + description Anti-spoofing_77.68.120.146 + source { + address 77.68.120.146 + mac-address !00:50:56:0d:fb:7b + } + } + rule 576 { + action drop + description Anti-spoofing_77.68.78.73 + source { + address 77.68.78.73 + mac-address !00:50:56:14:4b:f4 + } + } + rule 577 { + action drop + description Anti-spoofing_77.68.76.177 + source { + address 77.68.76.177 + mac-address !00:50:56:26:ac:11 + } + } + rule 578 { + action drop + description Anti-spoofing_77.68.77.117 + source { + address 77.68.77.117 + mac-address !00:50:56:09:4d:ce + } + } + rule 579 { + action drop + description Anti-spoofing_77.68.77.108 + source { + address 77.68.77.108 + mac-address !00:50:56:3a:b7:59 + } + } + rule 580 { + action drop + description Anti-spoofing_77.68.7.222 + source { + address 77.68.7.222 + mac-address !00:50:56:36:cc:37 + } + } + rule 581 { + action drop + description Anti-spoofing_77.68.76.50 + source { + address 77.68.76.50 + mac-address !00:50:56:34:78:88 + } + } + rule 582 { + action drop + description Anti-spoofing_77.68.77.192 + source { + address 77.68.77.192 + mac-address !00:50:56:0f:eb:a4 + } + } + rule 583 { + action drop + description Anti-spoofing_77.68.76.217 + source { + address 77.68.76.217 + mac-address !00:50:56:29:6d:a9 + } + } + rule 584 { + action drop + description Anti-spoofing_77.68.92.186 + source { + address 77.68.92.186 + mac-address !00:50:56:08:8b:d0 + } + } + rule 585 { + action drop + description Anti-spoofing_77.68.76.165 + source { + address 77.68.76.165 + mac-address !00:50:56:19:74:17 + } + } + rule 586 { + action drop + description Anti-spoofing_77.68.91.22 + source { + address 77.68.91.22 + mac-address !00:50:56:2e:2c:cb + } + } + rule 587 { + action drop + description Anti-spoofing_77.68.77.160 + source { + address 77.68.77.160 + mac-address !00:50:56:27:75:65 + } + } + rule 588 { + action drop + description Anti-spoofing_77.68.77.30 + source { + address 77.68.77.30 + mac-address !00:50:56:3b:95:8f + } + } + rule 589 { + action drop + description Anti-spoofing_77.68.77.21 + source { + address 77.68.77.21 + mac-address !00:50:56:34:cd:82 + } + } + rule 590 { + action drop + description Anti-spoofing_77.68.76.29 + source { + address 77.68.76.29 + mac-address !00:50:56:2f:a3:ef + } + } + rule 591 { + action drop + description Anti-spoofing_213.171.212.136 + source { + address 213.171.212.136 + mac-address !00:50:56:19:fb:be + } + } + rule 592 { + action drop + description Anti-spoofing_77.68.76.158 + source { + address 77.68.76.158 + mac-address !00:50:56:36:97:69 + } + } + rule 593 { + action drop + description Anti-spoofing_77.68.76.203 + source { + address 77.68.76.203 + mac-address !00:50:56:2f:48:47 + } + } + rule 594 { + action drop + description Anti-spoofing_77.68.77.243 + source { + address 77.68.77.243 + mac-address !00:50:56:20:1f:c4 + } + } + rule 595 { + action drop + description Anti-spoofing_77.68.77.54 + source { + address 77.68.77.54 + mac-address !00:50:56:0e:da:e1 + } + } + rule 596 { + action drop + description Anti-spoofing_77.68.76.22 + source { + address 77.68.76.22 + mac-address !00:50:56:1b:a3:e6 + } + } + rule 597 { + action drop + description Anti-spoofing_77.68.103.120 + source { + address 77.68.103.120 + mac-address !00:50:56:1f:cb:8e + } + } + rule 598 { + action drop + description Anti-spoofing_109.228.37.174 + source { + address 109.228.37.174 + mac-address !00:50:56:1d:0f:a0 + } + } + rule 599 { + action drop + description Anti-spoofing_77.68.17.26 + source { + address 77.68.17.26 + mac-address !00:50:56:13:4a:e1 + } + } + rule 600 { + action drop + description Anti-spoofing_77.68.76.25 + source { + address 77.68.76.25 + mac-address !00:50:56:1f:54:d9 + } + } + rule 601 { + action drop + description Anti-spoofing_77.68.76.21 + source { + address 77.68.76.21 + mac-address !00:50:56:15:a8:33 + } + } + rule 602 { + action drop + description Anti-spoofing_77.68.77.221 + source { + address 77.68.77.221 + mac-address !00:50:56:06:2a:ae + } + } + rule 603 { + action drop + description Anti-spoofing_77.68.77.76 + source { + address 77.68.77.76 + mac-address !00:50:56:18:01:78 + } + } + rule 604 { + action drop + description Anti-spoofing_77.68.76.127 + source { + address 77.68.76.127 + mac-address !00:50:56:24:a4:85 + } + } + rule 605 { + action drop + description Anti-spoofing_77.68.77.139 + source { + address 77.68.77.139 + mac-address !00:50:56:3b:1e:be + } + } + rule 606 { + action drop + description Anti-spoofing_77.68.77.240 + source { + address 77.68.77.240 + mac-address !00:50:56:2b:d5:dd + } + } + rule 607 { + action drop + description Anti-spoofing_185.132.38.216 + source { + address 185.132.38.216 + mac-address !00:50:56:26:a7:47 + } + } + rule 608 { + action drop + description Anti-spoofing_77.68.76.39 + source { + address 77.68.76.39 + mac-address !00:50:56:1e:0d:c1 + } + } + rule 609 { + action drop + description Anti-spoofing_77.68.76.149 + source { + address 77.68.76.149 + mac-address !00:50:56:32:30:e7 + } + } + rule 610 { + action drop + description Anti-spoofing_77.68.77.57 + source { + address 77.68.77.57 + mac-address !00:50:56:26:33:75 + } + } + rule 611 { + action drop + description Anti-spoofing_77.68.77.185 + source { + address 77.68.77.185 + mac-address !00:50:56:22:72:c9 + } + } + rule 612 { + action drop + description Anti-spoofing_77.68.76.116 + source { + address 77.68.76.116 + mac-address !00:50:56:09:f2:df + } + } + rule 613 { + action drop + description Anti-spoofing_77.68.95.212 + source { + address 77.68.95.212 + mac-address !00:50:56:21:4b:e6 + } + } + rule 614 { + action drop + description Anti-spoofing_77.68.76.160 + source { + address 77.68.76.160 + mac-address !00:50:56:3a:fa:b3 + } + } + rule 615 { + action drop + description Anti-spoofing_77.68.77.70 + source { + address 77.68.77.70 + mac-address !00:50:56:37:9d:47 + } + } + rule 616 { + action drop + description Anti-spoofing_77.68.77.149 + source { + address 77.68.77.149 + mac-address !00:50:56:2c:f8:51 + } + } + rule 617 { + action drop + description Anti-spoofing_77.68.76.57 + source { + address 77.68.76.57 + mac-address !00:50:56:32:d9:0f + } + } + rule 618 { + action drop + description Anti-spoofing_77.68.76.115 + source { + address 77.68.76.115 + mac-address !00:50:56:09:67:90 + } + } + rule 619 { + action drop + description Anti-spoofing_185.132.41.72 + source { + address 185.132.41.72 + mac-address !00:50:56:2b:aa:79 + } + } + rule 620 { + action drop + description Anti-spoofing_77.68.84.155 + source { + address 77.68.84.155 + mac-address !00:50:56:05:52:76 + } + } + rule 621 { + action drop + description Anti-spoofing_77.68.76.200 + source { + address 77.68.76.200 + mac-address !00:50:56:00:5f:48 + } + } + rule 622 { + action drop + description Anti-spoofing_77.68.76.23 + source { + address 77.68.76.23 + mac-address !00:50:56:27:eb:9b + } + } + rule 623 { + action drop + description Anti-spoofing_77.68.77.46 + source { + address 77.68.77.46 + mac-address !00:50:56:22:73:37 + } + } + rule 624 { + action drop + description Anti-spoofing_77.68.91.195 + source { + address 77.68.91.195 + mac-address !00:50:56:09:f1:74 + } + } + rule 625 { + action drop + description Anti-spoofing_77.68.76.198 + source { + address 77.68.76.198 + mac-address !00:50:56:05:4b:16 + } + } + rule 626 { + action drop + description Anti-spoofing_77.68.77.141 + source { + address 77.68.77.141 + mac-address !00:50:56:0c:04:05 + } + } + rule 627 { + action drop + description Anti-spoofing_77.68.77.50 + source { + address 77.68.77.50 + mac-address !00:50:56:2d:5b:c6 + } + } + rule 628 { + action drop + description Anti-spoofing_77.68.77.128 + source { + address 77.68.77.128 + mac-address !00:50:56:27:0f:74 + } + } + rule 629 { + action drop + description Anti-spoofing_77.68.115.142 + source { + address 77.68.115.142 + mac-address !00:50:56:1b:e1:25 + } + } + rule 630 { + action drop + description Anti-spoofing_77.68.77.88 + source { + address 77.68.77.88 + mac-address !00:50:56:2b:db:7e + } + } + rule 631 { + action drop + description Anti-spoofing_77.68.4.74 + source { + address 77.68.4.74 + mac-address !00:50:56:0f:22:a5 + } + } + rule 632 { + action drop + description Anti-spoofing_77.68.76.80 + source { + address 77.68.76.80 + mac-address !00:50:56:1f:17:01 + } + } + rule 633 { + action drop + description Anti-spoofing_77.68.76.35 + source { + address 77.68.76.35 + mac-address !00:50:56:30:e3:a1 + } + } + rule 634 { + action drop + description Anti-spoofing_77.68.77.204 + source { + address 77.68.77.204 + mac-address !00:50:56:23:70:3a + } + } + rule 635 { + action drop + description Anti-spoofing_77.68.77.201 + source { + address 77.68.77.201 + mac-address !50:9a:4c:74:06:06 + } + } + rule 636 { + action drop + description Anti-spoofing_77.68.77.97 + source { + address 77.68.77.97 + mac-address !00:50:56:2f:48:47 + } + } + rule 637 { + action drop + description Anti-spoofing_77.68.76.195 + source { + address 77.68.76.195 + mac-address !00:50:56:14:c5:49 + } + } + rule 638 { + action drop + description Anti-spoofing_77.68.76.202 + source { + address 77.68.76.202 + mac-address !00:50:56:07:3c:3c + } + } + rule 640 { + action drop + description Anti-spoofing_77.68.76.157 + source { + address 77.68.76.157 + mac-address !00:50:56:35:c8:20 + } + } + rule 641 { + action drop + description Anti-spoofing_213.171.212.114 + source { + address 213.171.212.114 + mac-address !00:50:56:11:7f:32 + } + } + rule 642 { + action drop + description Anti-spoofing_77.68.77.159 + source { + address 77.68.77.159 + mac-address !00:50:56:14:d8:f0 + } + } + rule 643 { + action drop + description Anti-spoofing_213.171.214.234 + source { + address 213.171.214.234 + mac-address !00:50:56:29:94:38 + } + } + rule 644 { + action drop + description Anti-spoofing_77.68.76.48 + source { + address 77.68.76.48 + mac-address !00:50:56:33:38:d6 + } + } + rule 645 { + action drop + description Anti-spoofing_77.68.76.118 + source { + address 77.68.76.118 + mac-address !00:50:56:1c:cd:d3 + } + } + rule 646 { + action drop + description Anti-spoofing_77.68.76.38 + source { + address 77.68.76.38 + mac-address !00:50:56:01:59:2a + } + } + rule 647 { + action drop + description Anti-spoofing_77.68.31.144 + source { + address 77.68.31.144 + mac-address !00:50:56:01:89:fb + } + } + rule 648 { + action drop + description Anti-spoofing_77.68.23.35 + source { + address 77.68.23.35 + mac-address !00:50:56:3b:1f:ee + } + } + rule 649 { + action drop + description Anti-spoofing_77.68.4.80 + source { + address 77.68.4.80 + mac-address !00:50:56:1a:06:95 + } + } + rule 650 { + action drop + description Anti-spoofing_77.68.127.151 + source { + address 77.68.127.151 + mac-address !00:50:56:32:48:a6 + } + } + rule 651 { + action drop + description Anti-spoofing_77.68.77.203 + source { + address 77.68.77.203 + mac-address !00:50:56:11:05:40 + } + } + rule 652 { + action drop + description Anti-spoofing_77.68.77.233 + source { + address 77.68.77.233 + mac-address !00:50:56:37:0e:b3 + } + } + rule 653 { + action drop + description Anti-spoofing_77.68.77.163 + source { + address 77.68.77.163 + mac-address !00:50:56:08:a3:b4 + } + } + rule 654 { + action drop + description Anti-spoofing_77.68.77.49 + source { + address 77.68.77.49 + mac-address !00:50:56:03:ba:26 + } + } + rule 655 { + action drop + description Anti-spoofing_77.68.76.58 + source { + address 77.68.76.58 + mac-address !00:50:56:03:bd:d2 + } + } + rule 656 { + action drop + description Anti-spoofing_77.68.77.171 + source { + address 77.68.77.171 + mac-address !00:50:56:22:3d:21 + } + } + rule 657 { + action drop + description Anti-spoofing_77.68.116.220 + source { + address 77.68.116.220 + mac-address !00:50:56:2e:06:02 + } + } + rule 658 { + action drop + description Anti-spoofing_77.68.77.150 + source { + address 77.68.77.150 + mac-address !00:50:56:23:ac:01 + } + } + rule 659 { + action drop + description Anti-spoofing_77.68.121.106 + source { + address 77.68.121.106 + mac-address !00:50:56:38:2f:3f + } + } + rule 660 { + action drop + description Anti-spoofing_77.68.77.199 + source { + address 77.68.77.199 + mac-address !00:50:56:37:e8:23 + } + } + rule 661 { + action drop + description Anti-spoofing_77.68.76.220 + source { + address 77.68.76.220 + mac-address !00:50:56:26:27:93 + } + } + rule 662 { + action drop + description Anti-spoofing_77.68.85.172 + source { + address 77.68.85.172 + mac-address !00:50:56:24:a5:72 + } + } + rule 663 { + action drop + description Anti-spoofing_109.228.42.232 + source { + address 109.228.42.232 + mac-address !00:50:56:2c:34:e5 + } + } + rule 664 { + action drop + description Anti-spoofing_77.68.33.216 + source { + address 77.68.33.216 + mac-address !00:50:56:08:a3:d8 + } + } + rule 665 { + action drop + description Anti-spoofing_109.228.35.110 + source { + address 109.228.35.110 + mac-address !00:50:56:20:bc:f6 + } + } + rule 666 { + action drop + description Anti-spoofing_77.68.87.212 + source { + address 77.68.87.212 + mac-address !00:50:56:20:7a:5b + } + } + rule 667 { + action drop + description Anti-spoofing_109.228.36.174 + source { + address 109.228.36.174 + mac-address !00:50:56:05:73:0a + } + } + rule 668 { + action drop + description Anti-spoofing_77.68.122.241 + source { + address 77.68.122.241 + mac-address !00:50:56:3d:34:86 + } + } + rule 669 { + action drop + description Anti-spoofing_77.68.10.170 + source { + address 77.68.10.170 + mac-address !00:50:56:2e:a7:d6 + } + } + rule 670 { + action drop + description Anti-spoofing_109.228.59.247 + source { + address 109.228.59.247 + mac-address !00:50:56:11:77:61 + } + } + rule 671 { + action drop + description Anti-spoofing_77.68.77.156 + source { + address 77.68.77.156 + mac-address !00:50:56:37:e8:23 + } + } + rule 672 { + action drop + description Anti-spoofing_77.68.76.248 + source { + address 77.68.76.248 + mac-address !00:50:56:22:40:ae + } + } + rule 673 { + action drop + description Anti-spoofing_77.68.76.19 + source { + address 77.68.76.19 + mac-address !00:50:56:26:ce:06 + } + } + rule 674 { + action drop + description Anti-spoofing_77.68.77.29 + source { + address 77.68.77.29 + mac-address !00:50:56:11:83:b8 + } + } + rule 675 { + action drop + description Anti-spoofing_77.68.76.250 + source { + address 77.68.76.250 + mac-address !00:50:56:2d:ca:5b + } + } + rule 676 { + action drop + description Anti-spoofing_77.68.76.110 + source { + address 77.68.76.110 + mac-address !00:50:56:1e:db:08 + } + } + rule 677 { + action drop + description Anti-spoofing_77.68.76.171 + source { + address 77.68.76.171 + mac-address !00:50:56:01:8b:92 + } + } + rule 678 { + action drop + description Anti-spoofing_77.68.76.212 + source { + address 77.68.76.212 + mac-address !00:50:56:2b:28:99 + } + } + rule 679 { + action drop + description Anti-spoofing_77.68.112.248 + source { + address 77.68.112.248 + mac-address !00:50:56:35:e3:48 + } + } + rule 680 { + action drop + description Anti-spoofing_77.68.77.132 + source { + address 77.68.77.132 + mac-address !00:50:56:21:ab:ff + } + } + rule 681 { + action drop + description Anti-spoofing_77.68.120.218 + source { + address 77.68.120.218 + mac-address !00:50:56:10:a8:be + } + } + rule 682 { + action drop + description Anti-spoofing_77.68.120.249 + source { + address 77.68.120.249 + mac-address !00:50:56:2f:70:ed + } + } + rule 683 { + action drop + description Anti-spoofing_77.68.77.81 + source { + address 77.68.77.81 + mac-address !00:50:56:1e:9f:f8 + } + } + rule 684 { + action drop + description Anti-spoofing_77.68.76.37 + source { + address 77.68.76.37 + mac-address !00:50:56:07:f8:48 + } + } + rule 685 { + action drop + description Anti-spoofing_77.68.76.197 + source { + address 77.68.76.197 + mac-address !00:50:56:31:a0:ee + } + } + rule 686 { + action drop + description Anti-spoofing_77.68.76.20 + source { + address 77.68.76.20 + mac-address !00:50:56:18:a2:03 + } + } + rule 687 { + action drop + description Anti-spoofing_77.68.76.108 + source { + address 77.68.76.108 + mac-address !00:50:56:0d:4d:25 + } + } + rule 688 { + action drop + description Anti-spoofing_77.68.76.139 + source { + address 77.68.76.139 + mac-address !00:50:56:1c:52:a8 + } + } + rule 689 { + action drop + description Anti-spoofing_77.68.76.99 + source { + address 77.68.76.99 + mac-address !00:50:56:2e:8d:48 + } + } + rule 690 { + action drop + description Anti-spoofing_77.68.77.211 + source { + address 77.68.77.211 + mac-address !00:50:56:30:37:77 + } + } + rule 691 { + action drop + description Anti-spoofing_77.68.77.236 + source { + address 77.68.77.236 + mac-address !00:50:56:18:13:8b + } + } + rule 692 { + action drop + description Anti-spoofing_77.68.76.252 + source { + address 77.68.76.252 + mac-address !00:50:56:16:03:6e + } + } + rule 693 { + action drop + description Anti-spoofing_77.68.122.89 + source { + address 77.68.122.89 + mac-address !00:50:56:25:66:5d + } + } + rule 694 { + action drop + description Anti-spoofing_77.68.76.120 + source { + address 77.68.76.120 + mac-address !00:50:56:39:de:31 + } + } + rule 695 { + action drop + description Anti-spoofing_77.68.77.234 + source { + address 77.68.77.234 + mac-address !00:50:56:26:a1:9a + } + } + rule 696 { + action drop + description Anti-spoofing_77.68.77.32 + source { + address 77.68.77.32 + mac-address !00:50:56:38:e8:59 + } + } + rule 697 { + action drop + description Anti-spoofing_77.68.77.247 + source { + address 77.68.77.247 + mac-address !00:50:56:27:8a:8b + } + } + rule 698 { + action drop + description Anti-spoofing_77.68.76.229 + source { + address 77.68.76.229 + mac-address !00:50:56:16:56:30 + } + } + rule 699 { + action drop + description Anti-spoofing_77.68.76.209 + source { + address 77.68.76.209 + mac-address !00:50:56:19:24:73 + } + } + rule 700 { + action drop + description Anti-spoofing_77.68.125.32 + source { + address 77.68.125.32 + mac-address !00:50:56:00:07:47 + } + } + rule 701 { + action drop + description Anti-spoofing_77.68.76.219 + source { + address 77.68.76.219 + mac-address !00:50:56:2d:04:90 + } + } + rule 702 { + action drop + description Anti-spoofing_77.68.76.253 + source { + address 77.68.76.253 + mac-address !00:50:56:12:7b:d8 + } + } + rule 703 { + action drop + description Anti-spoofing_77.68.13.137 + source { + address 77.68.13.137 + mac-address !00:50:56:16:c6:86 + } + } + rule 704 { + action drop + description Anti-spoofing_77.68.85.115 + source { + address 77.68.85.115 + mac-address !00:50:56:3c:51:df + } + } + rule 705 { + action drop + description Anti-spoofing_77.68.77.202 + source { + address 77.68.77.202 + mac-address !00:50:56:0c:94:82 + } + } + rule 706 { + action drop + description Anti-spoofing_77.68.76.247 + source { + address 77.68.76.247 + mac-address !00:50:56:1b:f1:83 + } + } + rule 707 { + action drop + description Anti-spoofing_77.68.9.75 + source { + address 77.68.9.75 + mac-address !00:50:56:21:9b:fe + } + } + rule 708 { + action drop + description Anti-spoofing_109.228.39.157 + source { + address 109.228.39.157 + mac-address !00:50:56:2b:55:32 + } + } + rule 709 { + action drop + description Anti-spoofing_77.68.77.99 + source { + address 77.68.77.99 + mac-address !00:50:56:09:d5:e8 + } + } + rule 710 { + action drop + description Anti-spoofing_77.68.23.158 + source { + address 77.68.23.158 + mac-address !00:50:56:15:8f:75 + } + } + rule 711 { + action drop + description Anti-spoofing_77.68.76.169 + source { + address 77.68.76.169 + mac-address !00:50:56:0b:6d:e4 + } + } + rule 712 { + action drop + description Anti-spoofing_77.68.76.95 + source { + address 77.68.76.95 + mac-address !00:50:56:17:08:c9 + } + } + rule 713 { + action drop + description Anti-spoofing_77.68.76.187 + source { + address 77.68.76.187 + mac-address !00:50:56:14:79:08 + } + } + rule 714 { + action drop + description Anti-spoofing_109.228.37.114 + source { + address 109.228.37.114 + mac-address !00:50:56:15:3d:4b + } + } + rule 715 { + action drop + description Anti-spoofing_77.68.5.187 + source { + address 77.68.5.187 + mac-address !00:50:56:07:60:de + } + } + rule 716 { + action drop + description Anti-spoofing_77.68.77.222 + source { + address 77.68.77.222 + mac-address !00:50:56:38:03:ce + } + } + rule 717 { + action drop + description Anti-spoofing_77.68.77.53 + source { + address 77.68.77.53 + mac-address !00:50:56:18:cc:5a + } + } + rule 718 { + action drop + description Anti-spoofing_77.68.77.124 + source { + address 77.68.77.124 + mac-address !00:50:56:21:67:74 + } + } + rule 719 { + action drop + description Anti-spoofing_77.68.76.61 + source { + address 77.68.76.61 + mac-address !00:50:56:10:fa:46 + } + } + rule 720 { + action drop + description Anti-spoofing_109.228.37.240 + source { + address 109.228.37.240 + mac-address !00:50:56:0a:d3:2d + } + } + rule 721 { + action drop + description Anti-spoofing_77.68.27.27 + source { + address 77.68.27.27 + mac-address !00:50:56:14:b0:2a + } + } + rule 722 { + action drop + description Anti-spoofing_77.68.77.43 + source { + address 77.68.77.43 + mac-address !00:50:56:30:92:94 + } + } + rule 723 { + action drop + description Anti-spoofing_77.68.76.94 + source { + address 77.68.76.94 + mac-address !00:50:56:00:10:ce + } + } + rule 724 { + action drop + description Anti-spoofing_77.68.77.165 + source { + address 77.68.77.165 + mac-address !00:50:56:26:5f:42 + } + } + rule 725 { + action drop + description Anti-spoofing_77.68.77.251 + source { + address 77.68.77.251 + mac-address !00:50:56:39:db:9e + } + } + rule 726 { + action drop + description Anti-spoofing_77.68.77.152 + source { + address 77.68.77.152 + mac-address !00:50:56:12:68:ca + } + } + rule 727 { + action drop + description Anti-spoofing_185.132.43.164 + source { + address 185.132.43.164 + mac-address !00:50:56:2f:98:9b + } + } + rule 728 { + action drop + description Anti-spoofing_77.68.9.186 + source { + address 77.68.9.186 + mac-address !00:50:56:06:07:22 + } + } + rule 729 { + action drop + description Anti-spoofing_77.68.27.28 + source { + address 77.68.27.28 + mac-address !00:50:56:27:c6:2d + } + } + rule 730 { + action drop + description Anti-spoofing_77.68.84.147 + source { + address 77.68.84.147 + mac-address !00:50:56:28:d5:4d + } + } + rule 731 { + action drop + description Anti-spoofing_77.68.3.80 + source { + address 77.68.3.80 + mac-address !00:50:56:35:66:85 + } + } + rule 732 { + action drop + description Anti-spoofing_77.68.76.44 + source { + address 77.68.76.44 + mac-address !00:50:56:2b:8f:62 + } + } + rule 733 { + action drop + description Anti-spoofing_77.68.76.47 + source { + address 77.68.76.47 + mac-address !50:9a:4c:74:52:56 + } + } + rule 734 { + action drop + description Anti-spoofing_77.68.76.74 + source { + address 77.68.76.74 + mac-address !00:50:56:30:a0:57 + } + } + rule 735 { + action drop + description Anti-spoofing_77.68.5.166 + source { + address 77.68.5.166 + mac-address !00:50:56:17:e2:18 + } + } + rule 736 { + action drop + description Anti-spoofing_77.68.76.55 + source { + address 77.68.76.55 + mac-address !00:50:56:0f:46:86 + } + } + rule 737 { + action drop + description Anti-spoofing_77.68.10.142 + source { + address 77.68.10.142 + mac-address !00:50:56:19:04:d3 + } + } + rule 738 { + action drop + description Anti-spoofing_77.68.77.75 + source { + address 77.68.77.75 + mac-address !00:50:56:0e:a6:a8 + } + } + rule 739 { + action drop + description Anti-spoofing_77.68.77.239 + source { + address 77.68.77.239 + mac-address !00:50:56:26:f4:c8 + } + } + rule 740 { + action drop + description Anti-spoofing_213.171.208.176 + source { + address 213.171.208.176 + mac-address !00:50:56:34:50:f7 + } + } + rule 741 { + action drop + description Anti-spoofing_77.68.4.111 + source { + address 77.68.4.111 + mac-address !00:50:56:2a:61:0b + } + } + rule 742 { + action drop + description Anti-spoofing_77.68.118.120 + source { + address 77.68.118.120 + mac-address !00:50:56:3c:35:39 + } + } + rule 743 { + action drop + description Anti-spoofing_77.68.76.75 + source { + address 77.68.76.75 + mac-address !00:50:56:2a:42:ca + } + } + rule 744 { + action drop + description Anti-spoofing_77.68.77.71 + source { + address 77.68.77.71 + mac-address !00:50:56:38:ae:bf + } + } + rule 745 { + action drop + description Anti-spoofing_77.68.76.138 + source { + address 77.68.76.138 + mac-address !00:50:56:14:c0:d8 + } + } + rule 746 { + action drop + description Anti-spoofing_77.68.76.145 + source { + address 77.68.76.145 + mac-address !00:50:56:3b:e8:48 + } + } + rule 747 { + action drop + description Anti-spoofing_77.68.77.145 + source { + address 77.68.77.145 + mac-address !00:50:56:12:b0:43 + } + } + rule 748 { + action drop + description Anti-spoofing_77.68.3.121 + source { + address 77.68.3.121 + mac-address !00:50:56:03:7b:9d + } + } + rule 749 { + action drop + description Anti-spoofing_77.68.3.144 + source { + address 77.68.3.144 + mac-address !00:50:56:18:a0:ed + } + } + rule 750 { + action drop + description Anti-spoofing_77.68.77.68 + source { + address 77.68.77.68 + mac-address !00:50:56:3c:dc:4f + } + } + rule 751 { + action drop + description Anti-spoofing_77.68.76.126 + source { + address 77.68.76.126 + mac-address !00:50:56:0f:d0:ae + } + } + rule 752 { + action drop + description Anti-spoofing_77.68.76.88 + source { + address 77.68.76.88 + mac-address !00:50:56:15:d6:12 + } + } + rule 753 { + action drop + description Anti-spoofing_77.68.77.254 + source { + address 77.68.77.254 + mac-address !00:50:56:0e:5e:74 + } + } + rule 754 { + action drop + description Anti-spoofing_185.132.40.124 + source { + address 185.132.40.124 + mac-address !00:50:56:08:f8:6a + } + } + rule 755 { + action drop + description Anti-spoofing_77.68.20.231 + source { + address 77.68.20.231 + mac-address !00:50:56:05:35:ce + } + } + rule 756 { + action drop + description Anti-spoofing_77.68.77.181 + source { + address 77.68.77.181 + mac-address !00:50:56:20:03:6f + } + } + rule 757 { + action drop + description Anti-spoofing_77.68.22.146 + source { + address 77.68.22.146 + mac-address !00:50:56:0e:85:95 + } + } + rule 758 { + action drop + description Anti-spoofing_77.68.112.75 + source { + address 77.68.112.75 + mac-address !00:50:56:09:33:e6 + } + } + rule 759 { + action drop + description Anti-spoofing_77.68.4.22 + source { + address 77.68.4.22 + mac-address !00:50:56:14:be:3f + } + } + rule 760 { + action drop + description Anti-spoofing_77.68.76.96 + source { + address 77.68.76.96 + mac-address !00:50:56:32:91:fb + } + } + rule 761 { + action drop + description Anti-spoofing_77.68.3.161 + source { + address 77.68.3.161 + mac-address !00:50:56:12:82:40 + } + } + rule 762 { + action drop + description Anti-spoofing_109.228.37.10 + source { + address 109.228.37.10 + mac-address !00:50:56:0a:ef:ab + } + } + rule 763 { + action drop + description Anti-spoofing_77.68.76.228 + source { + address 77.68.76.228 + mac-address !00:50:56:2b:39:b1 + } + } + rule 764 { + action drop + description Anti-spoofing_77.68.121.94 + source { + address 77.68.121.94 + mac-address !00:50:56:0a:d7:68 + } + } + rule 765 { + action drop + description Anti-spoofing_77.68.3.194 + source { + address 77.68.3.194 + mac-address !00:50:56:10:90:6a + } + } + rule 766 { + action drop + description Anti-spoofing_77.68.76.112 + source { + address 77.68.76.112 + mac-address !00:50:56:24:e2:52 + } + } + rule 767 { + action drop + description Anti-spoofing_77.68.100.77 + source { + address 77.68.100.77 + mac-address !00:50:56:0e:f3:7a + } + } + rule 768 { + action drop + description Anti-spoofing_77.68.3.247 + source { + address 77.68.3.247 + mac-address !00:50:56:29:30:8a + } + } + rule 769 { + action drop + description Anti-spoofing_77.68.77.157 + source { + address 77.68.77.157 + mac-address !00:50:56:36:39:a5 + } + } + rule 770 { + action drop + description Anti-spoofing_77.68.29.65 + source { + address 77.68.29.65 + mac-address !00:50:56:2e:1b:f9 + } + } + rule 771 { + action drop + description Anti-spoofing_77.68.74.152 + source { + address 77.68.74.152 + mac-address !00:50:56:16:1d:31 + } + } + rule 772 { + action drop + description Anti-spoofing_185.132.39.145 + source { + address 185.132.39.145 + mac-address !00:50:56:03:77:75 + } + } + rule 773 { + action drop + description Anti-spoofing_77.68.28.139 + source { + address 77.68.28.139 + mac-address !00:50:56:25:a9:de + } + } + rule 774 { + action drop + description Anti-spoofing_77.68.77.33 + source { + address 77.68.77.33 + mac-address !00:50:56:09:16:76 + } + } + rule 775 { + action drop + description Anti-spoofing_77.68.77.137 + source { + address 77.68.77.137 + mac-address !00:50:56:15:b6:84 + } + } + rule 776 { + action drop + description Anti-spoofing_77.68.76.244 + source { + address 77.68.76.244 + mac-address !00:50:56:21:11:27 + } + } + rule 777 { + action drop + description Anti-spoofing_77.68.77.92 + source { + address 77.68.77.92 + mac-address !00:50:56:11:58:f5 + } + } + rule 778 { + action drop + description Anti-spoofing_77.68.7.227 + source { + address 77.68.7.227 + mac-address !00:50:56:34:a8:22 + } + } + rule 779 { + action drop + description Anti-spoofing_77.68.76.111 + source { + address 77.68.76.111 + mac-address !00:50:56:3e:44:ea + } + } + rule 780 { + action drop + description Anti-spoofing_77.68.76.185 + source { + address 77.68.76.185 + mac-address !00:50:56:1b:75:e8 + } + } + rule 781 { + action drop + description Anti-spoofing_77.68.76.208 + source { + address 77.68.76.208 + mac-address !50:9a:4c:98:c2:68 + } + } + rule 782 { + action drop + description Anti-spoofing_77.68.76.150 + source { + address 77.68.76.150 + mac-address !50:9a:4c:98:5c:c0 + } + } + rule 783 { + action drop + description Anti-spoofing_77.68.77.208 + source { + address 77.68.77.208 + mac-address !50:9a:4c:98:5c:c0 + } + } + rule 784 { + action drop + description Anti-spoofing_77.68.103.56 + source { + address 77.68.103.56 + mac-address !00:50:56:05:2f:9e + } + } + rule 785 { + action drop + description Anti-spoofing_77.68.125.60 + source { + address 77.68.125.60 + mac-address !00:50:56:2a:4a:20 + } + } + rule 786 { + action drop + description Anti-spoofing_77.68.76.42 + source { + address 77.68.76.42 + mac-address !00:50:56:3e:44:ea + } + } + rule 787 { + action drop + description Anti-spoofing_77.68.26.216 + source { + address 77.68.26.216 + mac-address !00:50:56:07:56:c4 + } + } + rule 788 { + action drop + description Anti-spoofing_77.68.76.164 + source { + address 77.68.76.164 + mac-address !00:50:56:1c:df:57 + } + } + rule 789 { + action drop + description Anti-spoofing_77.68.89.72 + source { + address 77.68.89.72 + mac-address !00:50:56:1b:84:5c + } + } + rule 790 { + action drop + description Anti-spoofing_77.68.76.181 + source { + address 77.68.76.181 + mac-address !00:50:56:36:5d:1e + } + } + rule 791 { + action drop + description Anti-spoofing_77.68.3.52 + source { + address 77.68.3.52 + mac-address !00:50:56:12:e2:00 + } + } + rule 792 { + action drop + description Anti-spoofing_77.68.77.207 + source { + address 77.68.77.207 + mac-address !00:50:56:16:24:34 + } + } + rule 793 { + action drop + description Anti-spoofing_77.68.81.44 + source { + address 77.68.81.44 + mac-address !00:50:56:1a:2f:81 + } + } + rule 794 { + action drop + description Anti-spoofing_77.68.28.145 + source { + address 77.68.28.145 + mac-address !00:50:56:39:78:a6 + } + } + rule 795 { + action drop + description Anti-spoofing_77.68.76.49 + source { + address 77.68.76.49 + mac-address !00:50:56:08:ae:5e + } + } + rule 796 { + action drop + description Anti-spoofing_77.68.77.227 + source { + address 77.68.77.227 + mac-address !ac:1f:6b:93:59:d4 + } + } + rule 797 { + action drop + description Anti-spoofing_77.68.76.136 + source { + address 77.68.76.136 + mac-address !00:50:56:0b:b2:b0 + } + } + rule 798 { + action drop + description Anti-spoofing_77.68.77.102 + source { + address 77.68.77.102 + mac-address !00:50:56:3d:91:75 + } + } + rule 799 { + action drop + description Anti-spoofing_77.68.5.155 + source { + address 77.68.5.155 + mac-address !00:50:56:13:33:02 + } + } + rule 801 { + action drop + description Anti-spoofing_77.68.88.100 + source { + address 77.68.88.100 + mac-address !00:50:56:08:dc:d0 + } + } + rule 802 { + action drop + description Anti-spoofing_77.68.72.254 + source { + address 77.68.72.254 + mac-address !00:50:56:0c:c2:8d + } + } + rule 803 { + action drop + description Anti-spoofing_77.68.77.74 + source { + address 77.68.77.74 + mac-address !00:50:56:18:d8:12 + } + } + rule 804 { + action drop + description Anti-spoofing_77.68.76.77 + source { + address 77.68.76.77 + mac-address !ac:1f:6b:4d:bd:60 + } + } + rule 805 { + action drop + description Anti-spoofing_77.68.76.123 + source { + address 77.68.76.123 + mac-address !00:50:56:38:5b:9d + } + } + rule 806 { + action drop + description Anti-spoofing_77.68.4.24 + source { + address 77.68.4.24 + mac-address !00:50:56:16:54:a8 + } + } + rule 807 { + action drop + description Anti-spoofing_213.171.214.167 + source { + address 213.171.214.167 + mac-address !00:50:56:13:7d:80 + } + } + rule 808 { + action drop + description Anti-spoofing_77.68.112.213 + source { + address 77.68.112.213 + mac-address !00:50:56:0b:ec:f2 + } + } + rule 809 { + action drop + description Anti-spoofing_185.132.40.166 + source { + address 185.132.40.166 + mac-address !00:50:56:22:c7:e0 + } + } + rule 810 { + action drop + description Anti-spoofing_77.68.76.31 + source { + address 77.68.76.31 + mac-address !00:50:56:38:22:33 + } + } + rule 811 { + action drop + description Anti-spoofing_77.68.76.148 + source { + address 77.68.76.148 + mac-address !00:50:56:16:6c:9c + } + } + rule 812 { + action drop + description Anti-spoofing_77.68.93.246 + source { + address 77.68.93.246 + mac-address !00:50:56:29:2c:65 + } + } + rule 813 { + action drop + description Anti-spoofing_77.68.77.120 + source { + address 77.68.77.120 + mac-address !00:50:56:39:92:1c + } + } + rule 814 { + action drop + description Anti-spoofing_77.68.7.123 + source { + address 77.68.7.123 + mac-address !00:50:56:33:46:a6 + } + } + rule 815 { + action drop + description Anti-spoofing_77.68.76.183 + source { + address 77.68.76.183 + mac-address !00:50:56:39:92:1c + } + } + rule 816 { + action drop + description Anti-spoofing_77.68.112.90 + source { + address 77.68.112.90 + mac-address !00:50:56:29:f8:91 + } + } + rule 817 { + action drop + description Anti-spoofing_77.68.50.90 + source { + address 77.68.50.90 + mac-address !00:50:56:11:d5:cb + } + } + rule 818 { + action drop + description Anti-spoofing_77.68.3.61 + source { + address 77.68.3.61 + mac-address !00:50:56:03:0b:87 + } + } + rule 819 { + action drop + description Anti-spoofing_213.171.213.42 + source { + address 213.171.213.42 + mac-address !00:50:56:37:90:bd + } + } + rule 820 { + action drop + description Anti-spoofing_77.68.77.107 + source { + address 77.68.77.107 + mac-address !00:50:56:1e:74:40 + } + } + rule 821 { + action drop + description Anti-spoofing_77.68.89.183 + source { + address 77.68.89.183 + mac-address !00:50:56:04:b9:ce + } + } + rule 822 { + action drop + description Anti-spoofing_77.68.112.83 + source { + address 77.68.112.83 + mac-address !00:50:56:38:03:ce + } + } + rule 823 { + action drop + description Anti-spoofing_77.68.76.141 + source { + address 77.68.76.141 + mac-address !00:50:56:12:2e:7c + } + } + rule 825 { + action drop + description Anti-spoofing_77.68.76.105 + source { + address 77.68.76.105 + mac-address !00:50:56:00:0b:f6 + } + } + rule 826 { + action drop + description Anti-spoofing_77.68.76.251 + source { + address 77.68.76.251 + mac-address !00:50:56:34:1e:f4 + } + } + rule 827 { + action drop + description Anti-spoofing_77.68.6.202 + source { + address 77.68.6.202 + mac-address !00:50:56:17:65:5f + } + } + rule 828 { + action drop + description Anti-spoofing_88.208.198.92 + source { + address 88.208.198.92 + mac-address !00:50:56:0c:5d:98 + } + } + rule 829 { + action drop + description Anti-spoofing_77.68.76.249 + source { + address 77.68.76.249 + mac-address !00:50:56:01:18:09 + } + } + rule 830 { + action drop + description Anti-spoofing_77.68.30.164 + source { + address 77.68.30.164 + mac-address !00:50:56:3c:2a:3a + } + } + rule 831 { + action drop + description Anti-spoofing_77.68.77.59 + source { + address 77.68.77.59 + mac-address !00:50:56:18:09:81 + } + } + rule 832 { + action drop + description Anti-spoofing_77.68.76.40 + source { + address 77.68.76.40 + mac-address !00:50:56:13:e6:96 + } + } + rule 833 { + action drop + description Anti-spoofing_77.68.88.164 + source { + address 77.68.88.164 + mac-address !00:50:56:07:f9:c8 + } + } + rule 834 { + action drop + description Anti-spoofing_77.68.77.37 + source { + address 77.68.77.37 + mac-address !00:50:56:2f:1e:7b + } + } + rule 835 { + action drop + description Anti-spoofing_185.132.39.99 + source { + address 185.132.39.99 + mac-address !00:50:56:1d:4e:dd + } + } + rule 836 { + action drop + description Anti-spoofing_77.68.121.127 + source { + address 77.68.121.127 + mac-address !00:50:56:29:fd:29 + } + } + rule 837 { + action drop + description Anti-spoofing_77.68.77.65 + source { + address 77.68.77.65 + mac-address !00:50:56:30:1f:8b + } + } + rule 838 { + action drop + description Anti-spoofing_77.68.27.211 + source { + address 77.68.27.211 + mac-address !00:50:56:25:b4:d1 + } + } + rule 839 { + action drop + description Anti-spoofing_77.68.24.112 + source { + address 77.68.24.112 + mac-address !00:50:56:06:50:e8 + } + } + rule 840 { + action drop + description Anti-spoofing_109.228.38.201 + source { + address 109.228.38.201 + mac-address !00:50:56:36:33:0c + } + } + rule 841 { + action drop + description Anti-spoofing_77.68.115.17 + source { + address 77.68.115.17 + mac-address !00:50:56:16:da:60 + } + } + rule 842 { + action drop + description Anti-spoofing_185.132.36.60 + source { + address 185.132.36.60 + mac-address !00:50:56:14:a7:b2 + } + } + rule 843 { + action drop + description Anti-spoofing_77.68.76.231 + source { + address 77.68.76.231 + mac-address !00:50:56:03:c5:bc + } + } + rule 844 { + action drop + description Anti-spoofing_185.132.37.23 + source { + address 185.132.37.23 + mac-address !00:50:56:27:46:b8 + } + } + rule 845 { + action drop + description Anti-spoofing_109.228.35.84 + source { + address 109.228.35.84 + mac-address !00:50:56:17:74:b7 + } + } + rule 846 { + action drop + description Anti-spoofing_77.68.11.140 + source { + address 77.68.11.140 + mac-address !00:50:56:08:ce:61 + } + } + rule 848 { + action drop + description Anti-spoofing_77.68.77.24 + source { + address 77.68.77.24 + mac-address !00:50:56:28:65:cb + } + } + rule 849 { + action drop + description Anti-spoofing_77.68.78.113 + source { + address 77.68.78.113 + mac-address !00:50:56:2c:5a:e3 + } + } + rule 850 { + action drop + description Anti-spoofing_185.132.39.219 + source { + address 185.132.39.219 + mac-address !00:50:56:11:0d:fd + } + } + rule 851 { + action drop + description Anti-spoofing_185.132.40.11 + source { + address 185.132.40.11 + mac-address !00:50:56:27:50:a3 + } + } + rule 852 { + action drop + description Anti-spoofing_77.68.23.64 + source { + address 77.68.23.64 + mac-address !00:50:56:0a:b2:3c + } + } + rule 853 { + action drop + description Anti-spoofing_185.132.37.133 + source { + address 185.132.37.133 + mac-address !00:50:56:0b:0a:21 + } + } + rule 854 { + action drop + description Anti-spoofing_77.68.85.27 + source { + address 77.68.85.27 + mac-address !00:50:56:34:82:24 + } + } + rule 855 { + action drop + description Anti-spoofing_77.68.26.221 + source { + address 77.68.26.221 + mac-address !00:50:56:30:56:a2 + } + } + rule 856 { + action drop + description Anti-spoofing_77.68.76.243 + source { + address 77.68.76.243 + mac-address !00:50:56:1c:a0:2d + } + } + rule 857 { + action drop + description Anti-spoofing_77.68.116.52 + source { + address 77.68.116.52 + mac-address !00:50:56:2b:59:35 + } + } + rule 858 { + action drop + description Anti-spoofing_77.68.120.26 + source { + address 77.68.120.26 + mac-address !00:50:56:07:3b:2b + } + } + rule 859 { + action drop + description Anti-spoofing_185.132.40.56 + source { + address 185.132.40.56 + mac-address !00:50:56:21:cb:e3 + } + } + rule 860 { + action drop + description Anti-spoofing_213.171.210.155 + source { + address 213.171.210.155 + mac-address !00:50:56:2a:53:9f + } + } + rule 861 { + action drop + description Anti-spoofing_185.132.43.157 + source { + address 185.132.43.157 + mac-address !00:50:56:27:e6:d5 + } + } + rule 862 { + action drop + description Anti-spoofing_77.68.4.252 + source { + address 77.68.4.252 + mac-address !00:50:56:08:ff:66 + } + } + rule 863 { + action drop + description Anti-spoofing_77.68.77.63 + source { + address 77.68.77.63 + mac-address !00:50:56:10:9c:ca + } + } + rule 864 { + action drop + description Anti-spoofing_77.68.20.161 + source { + address 77.68.20.161 + mac-address !00:50:56:0d:06:6f + } + } + rule 865 { + action drop + description Anti-spoofing_77.68.117.45 + source { + address 77.68.117.45 + mac-address !00:50:56:05:e0:11 + } + } + rule 866 { + action drop + description Anti-spoofing_77.68.76.234 + source { + address 77.68.76.234 + mac-address !00:50:56:3a:d3:9e + } + } + rule 867 { + action drop + description Anti-spoofing_185.132.40.90 + source { + address 185.132.40.90 + mac-address !00:50:56:2c:90:4f + } + } + rule 868 { + action drop + description Anti-spoofing_77.68.77.90 + source { + address 77.68.77.90 + mac-address !00:50:56:1d:ec:a2 + } + } + rule 869 { + action drop + description Anti-spoofing_77.68.76.93 + source { + address 77.68.76.93 + mac-address !00:50:56:19:cb:e8 + } + } + rule 870 { + action drop + description Anti-spoofing_77.68.26.166 + source { + address 77.68.26.166 + mac-address !00:50:56:1e:34:14 + } + } + rule 871 { + action drop + description Anti-spoofing_185.132.40.244 + source { + address 185.132.40.244 + mac-address !00:50:56:14:a7:b2 + } + } + rule 872 { + action drop + description Anti-spoofing_77.68.77.77 + source { + address 77.68.77.77 + mac-address !00:50:56:0c:9b:e1 + } + } + rule 873 { + action drop + description Anti-spoofing_77.68.27.57 + source { + address 77.68.27.57 + mac-address !00:50:56:3e:06:ca + } + } + rule 874 { + action drop + description Anti-spoofing_77.68.7.114 + source { + address 77.68.7.114 + mac-address !00:50:56:33:0d:5e + } + } + rule 875 { + action drop + description Anti-spoofing_109.228.36.229 + source { + address 109.228.36.229 + mac-address !00:50:56:32:a6:83 + } + } + rule 876 { + action drop + description Anti-spoofing_77.68.77.151 + source { + address 77.68.77.151 + mac-address !00:50:56:0a:e4:20 + } + } + rule 877 { + action drop + description Anti-spoofing_77.68.76.92 + source { + address 77.68.76.92 + mac-address !00:50:56:2b:a5:38 + } + } + rule 878 { + action drop + description Anti-spoofing_77.68.49.159 + source { + address 77.68.49.159 + mac-address !00:50:56:16:4f:24 + } + } + rule 879 { + action drop + description Anti-spoofing_77.68.77.38 + source { + address 77.68.77.38 + mac-address !00:50:56:2c:fe:a1 + } + } + rule 880 { + action drop + description Anti-spoofing_77.68.20.217 + source { + address 77.68.20.217 + mac-address !00:50:56:3a:61:47 + } + } + rule 881 { + action drop + description Anti-spoofing_77.68.92.92 + source { + address 77.68.92.92 + mac-address !00:50:56:1b:64:85 + } + } + rule 882 { + action drop + description Anti-spoofing_77.68.76.124 + source { + address 77.68.76.124 + mac-address !00:50:56:0e:c1:e4 + } + } + rule 884 { + action drop + description Anti-spoofing_77.68.126.101 + source { + address 77.68.126.101 + mac-address !00:50:56:31:d1:a3 + } + } + rule 885 { + action drop + description Anti-spoofing_77.68.76.235 + source { + address 77.68.76.235 + mac-address !00:50:56:15:d1:66 + } + } + rule 886 { + action drop + description Anti-spoofing_77.68.77.95 + source { + address 77.68.77.95 + mac-address !00:50:56:39:c6:52 + } + } + rule 887 { + action drop + description Anti-spoofing_77.68.26.228 + source { + address 77.68.26.228 + mac-address !00:50:56:03:ab:9e + } + } + rule 888 { + action drop + description Anti-spoofing_77.68.32.118 + source { + address 77.68.32.118 + mac-address !00:50:56:0e:db:9d + } + } + rule 889 { + action drop + description Anti-spoofing_77.68.24.172 + source { + address 77.68.24.172 + mac-address !00:50:56:0e:2a:9c + } + } + rule 891 { + action drop + description Anti-spoofing_77.68.77.190 + source { + address 77.68.77.190 + mac-address !00:50:56:31:e8:fb + } + } + rule 892 { + action drop + description Anti-spoofing_77.68.33.197 + source { + address 77.68.33.197 + mac-address !00:50:56:2b:27:c4 + } + } + rule 893 { + action drop + description Anti-spoofing_213.171.210.177 + source { + address 213.171.210.177 + mac-address !00:50:56:04:96:31 + } + } + rule 894 { + action drop + description Anti-spoofing_185.132.41.73 + source { + address 185.132.41.73 + mac-address !00:50:56:35:b4:a5 + } + } + rule 895 { + action drop + description Anti-spoofing_77.68.21.78 + source { + address 77.68.21.78 + mac-address !00:50:56:23:87:f2 + } + } + rule 896 { + action drop + description Anti-spoofing_77.68.77.209 + source { + address 77.68.77.209 + mac-address !00:50:56:3b:95:06 + } + } + rule 897 { + action drop + description Anti-spoofing_88.208.215.19 + source { + address 88.208.215.19 + mac-address !00:50:56:1f:e1:4b + } + } + rule 898 { + action drop + description Anti-spoofing_77.68.77.214 + source { + address 77.68.77.214 + mac-address !00:50:56:2b:03:2b + } + } + rule 899 { + action drop + description Anti-spoofing_77.68.76.91 + source { + address 77.68.76.91 + mac-address !00:50:56:3b:3c:fb + } + } + rule 900 { + action drop + description Anti-spoofing_77.68.119.92 + source { + address 77.68.119.92 + mac-address !00:50:56:25:ba:8c + } + } + rule 901 { + action drop + description Anti-spoofing_77.68.77.79 + source { + address 77.68.77.79 + mac-address !00:50:56:28:f5:72 + } + } + rule 902 { + action drop + description Anti-spoofing_77.68.75.45 + source { + address 77.68.75.45 + mac-address !00:50:56:04:51:74 + } + } + rule 903 { + action drop + description Anti-spoofing_109.228.56.185 + source { + address 109.228.56.185 + mac-address !00:50:56:13:e5:07 + } + } + rule 904 { + action drop + description Anti-spoofing_185.132.43.6 + source { + address 185.132.43.6 + mac-address !00:50:56:38:d1:d5 + } + } + rule 905 { + action drop + description Anti-spoofing_77.68.117.202 + source { + address 77.68.117.202 + mac-address !00:50:56:01:b2:9f + } + } + rule 906 { + action drop + description Anti-spoofing_77.68.86.40 + source { + address 77.68.86.40 + mac-address !00:50:56:03:e2:49 + } + } + rule 907 { + action drop + description Anti-spoofing_77.68.49.126 + source { + address 77.68.49.126 + mac-address !00:50:56:3b:47:f3 + } + } + rule 909 { + action drop + description Anti-spoofing_77.68.77.100 + source { + address 77.68.77.100 + mac-address !00:50:56:34:d7:5b + } + } + rule 910 { + action drop + description Anti-spoofing_109.228.46.196 + source { + address 109.228.46.196 + mac-address !00:50:56:1a:a0:0e + } + } + rule 911 { + action drop + description Anti-spoofing_77.68.77.72 + source { + address 77.68.77.72 + mac-address !00:50:56:1e:67:f7 + } + } + rule 912 { + action drop + description Anti-spoofing_185.132.43.28 + source { + address 185.132.43.28 + mac-address !00:50:56:35:a5:36 + } + } + rule 913 { + action drop + description Anti-spoofing_77.68.103.19 + source { + address 77.68.103.19 + mac-address !00:50:56:27:34:a3 + } + } + rule 914 { + action drop + description Anti-spoofing_77.68.118.104 + source { + address 77.68.118.104 + mac-address !00:50:56:2d:f8:d7 + } + } + rule 915 { + action drop + description Anti-spoofing_77.68.116.183 + source { + address 77.68.116.183 + mac-address !00:50:56:17:23:d4 + } + } + rule 916 { + action drop + description Anti-spoofing_77.68.76.107 + source { + address 77.68.76.107 + mac-address !00:50:56:36:c0:da + } + } + rule 917 { + action drop + description Anti-spoofing_77.68.93.164 + source { + address 77.68.93.164 + mac-address !00:50:56:36:cd:1a + } + } + rule 918 { + action drop + description Anti-spoofing_77.68.5.241 + source { + address 77.68.5.241 + mac-address !00:50:56:11:2d:22 + } + } + rule 919 { + action drop + description Anti-spoofing_185.132.43.98 + source { + address 185.132.43.98 + mac-address !00:50:56:20:7b:87 + } + } + rule 920 { + action drop + description Anti-spoofing_77.68.76.241 + source { + address 77.68.76.241 + mac-address !00:50:56:00:50:f6 + } + } + rule 921 { + action drop + description Anti-spoofing_77.68.74.232 + source { + address 77.68.74.232 + mac-address !00:50:56:19:df:41 + } + } + rule 922 { + action drop + description Anti-spoofing_77.68.76.26 + source { + address 77.68.76.26 + mac-address !00:50:56:36:c0:da + } + } + rule 923 { + action drop + description Anti-spoofing_77.68.28.207 + source { + address 77.68.28.207 + mac-address !00:50:56:36:41:da + } + } + rule 924 { + action drop + description Anti-spoofing_77.68.29.178 + source { + address 77.68.29.178 + mac-address !00:50:56:21:81:be + } + } + rule 925 { + action drop + description Anti-spoofing_77.68.121.119 + source { + address 77.68.121.119 + mac-address !00:50:56:0b:d8:e1 + } + } + rule 926 { + action drop + description Anti-spoofing_77.68.126.22 + source { + address 77.68.126.22 + mac-address !00:50:56:32:62:56 + } + } + rule 927 { + action drop + description Anti-spoofing_109.228.61.31 + source { + address 109.228.61.31 + mac-address !00:50:56:21:a0:04 + } + } + rule 928 { + action drop + description Anti-spoofing_77.68.114.205 + source { + address 77.68.114.205 + mac-address !00:50:56:2a:f1:3f + } + } + rule 929 { + action drop + description Anti-spoofing_77.68.75.113 + source { + address 77.68.75.113 + mac-address !00:50:56:33:6c:b9 + } + } + rule 930 { + action drop + description Anti-spoofing_77.68.79.206 + source { + address 77.68.79.206 + mac-address !00:50:56:36:86:66 + } + } + rule 931 { + action drop + description Anti-spoofing_88.208.198.64 + source { + address 88.208.198.64 + mac-address !00:50:56:39:2c:fe + } + } + rule 932 { + action drop + description Anti-spoofing_77.68.77.161 + source { + address 77.68.77.161 + mac-address !00:50:56:0a:7e:6c + } + } + rule 933 { + action drop + description Anti-spoofing_77.68.114.237 + source { + address 77.68.114.237 + mac-address !00:50:56:16:f4:39 + } + } + rule 934 { + action drop + description Anti-spoofing_109.228.36.119 + source { + address 109.228.36.119 + mac-address !00:50:56:28:63:37 + } + } + rule 935 { + action drop + description Anti-spoofing_77.68.76.254 + source { + address 77.68.76.254 + mac-address !00:50:56:3b:49:08 + } + } + rule 936 { + action drop + description Anti-spoofing_77.68.77.231 + source { + address 77.68.77.231 + mac-address !00:50:56:36:78:72 + } + } + rule 937 { + action drop + description Anti-spoofing_77.68.7.172 + source { + address 77.68.7.172 + mac-address !00:50:56:19:39:45 + } + } + rule 938 { + action drop + description Anti-spoofing_77.68.77.62 + source { + address 77.68.77.62 + mac-address !00:50:56:04:8c:b4 + } + } + rule 939 { + action drop + description Anti-spoofing_77.68.77.215 + source { + address 77.68.77.215 + mac-address !00:50:56:35:f3:5a + } + } + rule 940 { + action drop + description Anti-spoofing_77.68.6.105 + source { + address 77.68.6.105 + mac-address !00:50:56:03:0e:07 + } + } + rule 941 { + action drop + description Anti-spoofing_77.68.33.37 + source { + address 77.68.33.37 + mac-address !00:50:56:00:6b:a3 + } + } + rule 942 { + action drop + description Anti-spoofing_77.68.4.180 + source { + address 77.68.4.180 + mac-address !00:50:56:11:6c:dc + } + } + rule 943 { + action drop + description Anti-spoofing_77.68.78.229 + source { + address 77.68.78.229 + mac-address !00:50:56:1e:58:2f + } + } + rule 944 { + action drop + description Anti-spoofing_77.68.73.73 + source { + address 77.68.73.73 + mac-address !00:50:56:38:d7:1a + } + } + rule 945 { + action drop + description Anti-spoofing_77.68.2.215 + source { + address 77.68.2.215 + mac-address !00:50:56:31:3c:87 + } + } + rule 946 { + action drop + description Anti-spoofing_77.68.48.81 + source { + address 77.68.48.81 + mac-address !00:50:56:3a:13:df + } + } + rule 947 { + action drop + description Anti-spoofing_213.171.214.102 + source { + address 213.171.214.102 + mac-address !00:50:56:00:60:5a + } + } + rule 948 { + action drop + description Anti-spoofing_77.68.123.177 + source { + address 77.68.123.177 + mac-address !00:50:56:3c:07:ef + } + } + rule 949 { + action drop + description Anti-spoofing_77.68.7.160 + source { + address 77.68.7.160 + mac-address !00:50:56:09:6e:79 + } + } + rule 950 { + action drop + description Anti-spoofing_77.68.24.59 + source { + address 77.68.24.59 + mac-address !00:50:56:3c:b7:c1 + } + } + rule 951 { + action drop + description Anti-spoofing_77.68.80.97 + source { + address 77.68.80.97 + mac-address !00:50:56:15:cc:c6 + } + } + rule 952 { + action drop + description Anti-spoofing_77.68.7.67 + source { + address 77.68.7.67 + mac-address !00:50:56:13:92:b7 + } + } + rule 953 { + action drop + description Anti-spoofing_109.228.36.79 + source { + address 109.228.36.79 + mac-address !00:50:56:17:c9:65 + } + } + rule 954 { + action drop + description Anti-spoofing_77.68.32.43 + source { + address 77.68.32.43 + mac-address !00:50:56:13:6d:02 + } + } + rule 955 { + action drop + description Anti-spoofing_77.68.90.106 + source { + address 77.68.90.106 + mac-address !00:50:56:1b:6d:fb + } + } + rule 956 { + action drop + description Anti-spoofing_77.68.77.174 + source { + address 77.68.77.174 + mac-address !00:50:56:2a:61:0b + } + } + rule 957 { + action drop + description Anti-spoofing_77.68.94.181 + source { + address 77.68.94.181 + mac-address !00:50:56:0b:7c:cc + } + } + rule 958 { + action drop + description Anti-spoofing_77.68.4.136 + source { + address 77.68.4.136 + mac-address !00:50:56:10:4d:5c + } + } + rule 959 { + action drop + description Anti-spoofing_77.68.32.31 + source { + address 77.68.32.31 + mac-address !00:50:56:0a:f5:03 + } + } + rule 960 { + action drop + description Anti-spoofing_77.68.30.133 + source { + address 77.68.30.133 + mac-address !00:50:56:3a:96:4e + } + } + rule 961 { + action drop + description Anti-spoofing_77.68.72.202 + source { + address 77.68.72.202 + mac-address !00:50:56:2e:ca:a2 + } + } + rule 962 { + action drop + description Anti-spoofing_77.68.81.141 + source { + address 77.68.81.141 + mac-address !00:50:56:00:07:47 + } + } + rule 963 { + action drop + description Anti-spoofing_77.68.27.54 + source { + address 77.68.27.54 + mac-address !00:50:56:37:ad:51 + } + } + rule 964 { + action drop + description Anti-spoofing_77.68.32.254 + source { + address 77.68.32.254 + mac-address !00:50:56:2d:d0:36 + } + } + rule 965 { + action drop + description Anti-spoofing_77.68.10.152 + source { + address 77.68.10.152 + mac-address !00:50:56:38:d7:1a + } + } + rule 967 { + action drop + description Anti-spoofing_109.228.47.223 + source { + address 109.228.47.223 + mac-address !00:50:56:02:f7:24 + } + } + rule 968 { + action drop + description Anti-spoofing_77.68.5.125 + source { + address 77.68.5.125 + mac-address !00:50:56:16:21:98 + } + } + rule 969 { + action drop + description Anti-spoofing_77.68.119.14 + source { + address 77.68.119.14 + mac-address !00:50:56:2e:87:33 + } + } + rule 970 { + action drop + description Anti-spoofing_77.68.117.51 + source { + address 77.68.117.51 + mac-address !00:50:56:17:c0:6c + } + } + rule 971 { + action drop + description Anti-spoofing_77.68.118.102 + source { + address 77.68.118.102 + mac-address !00:50:56:3e:06:ca + } + } + rule 972 { + action drop + description Anti-spoofing_185.132.43.71 + source { + address 185.132.43.71 + mac-address !00:50:56:2d:6a:8d + } + } + rule 973 { + action drop + description Anti-spoofing_77.68.112.91 + source { + address 77.68.112.91 + mac-address !00:50:56:2b:c3:9f + } + } + rule 974 { + action drop + description Anti-spoofing_77.68.116.232 + source { + address 77.68.116.232 + mac-address !00:50:56:2a:f9:fd + } + } + rule 976 { + action drop + description Anti-spoofing_77.68.82.157 + source { + address 77.68.82.157 + mac-address !00:50:56:3d:81:41 + } + } + rule 977 { + action drop + description Anti-spoofing_77.68.117.222 + source { + address 77.68.117.222 + mac-address !00:50:56:16:92:58 + } + } + rule 978 { + action drop + description Anti-spoofing_77.68.118.15 + source { + address 77.68.118.15 + mac-address !00:50:56:28:28:de + } + } + rule 979 { + action drop + description Anti-spoofing_77.68.117.173 + source { + address 77.68.117.173 + mac-address !00:50:56:12:7a:57 + } + } + rule 980 { + action drop + description Anti-spoofing_77.68.83.41 + source { + address 77.68.83.41 + mac-address !00:50:56:13:ef:0e + } + } + rule 981 { + action drop + description Anti-spoofing_77.68.4.57 + source { + address 77.68.4.57 + mac-address !00:50:56:23:f0:c3 + } + } + rule 983 { + action drop + description Anti-spoofing_77.68.118.86 + source { + address 77.68.118.86 + mac-address !00:50:56:03:73:3d + } + } + rule 984 { + action drop + description Anti-spoofing_109.228.56.26 + source { + address 109.228.56.26 + mac-address !00:50:56:36:47:8c + } + } + rule 985 { + action drop + description Anti-spoofing_109.228.38.171 + source { + address 109.228.38.171 + mac-address !00:50:56:18:da:1c + } + } + rule 986 { + action drop + description Anti-spoofing_77.68.91.128 + source { + address 77.68.91.128 + mac-address !00:50:56:34:d0:41 + } + } + rule 987 { + action drop + description Anti-spoofing_77.68.79.89 + source { + address 77.68.79.89 + mac-address !00:50:56:14:67:52 + } + } + rule 988 { + action drop + description Anti-spoofing_88.208.198.66 + source { + address 88.208.198.66 + mac-address !00:50:56:3c:e0:8d + } + } + rule 989 { + action drop + description Anti-spoofing_77.68.118.88 + source { + address 77.68.118.88 + mac-address !00:50:56:2f:ac:5f + } + } + rule 990 { + action drop + description Anti-spoofing_109.228.60.215 + source { + address 109.228.60.215 + mac-address !00:50:56:2b:59:35 + } + } + rule 991 { + action drop + description Anti-spoofing_109.228.55.82 + source { + address 109.228.55.82 + mac-address !00:50:56:32:15:bc + } + } + rule 992 { + action drop + description Anti-spoofing_77.68.48.14 + source { + address 77.68.48.14 + mac-address !00:50:56:2e:2e:5a + } + } + rule 993 { + action drop + description Anti-spoofing_77.68.7.186 + source { + address 77.68.7.186 + mac-address !00:50:56:06:63:ae + } + } + rule 994 { + action drop + description Anti-spoofing_77.68.74.209 + source { + address 77.68.74.209 + mac-address !00:50:56:01:c5:88 + } + } + rule 995 { + action drop + description Anti-spoofing_77.68.6.32 + source { + address 77.68.6.32 + mac-address !00:50:56:19:b2:9e + } + } + rule 996 { + action drop + description Anti-spoofing_77.68.6.210 + source { + address 77.68.6.210 + mac-address !00:50:56:03:16:58 + } + } + rule 997 { + action drop + description Anti-spoofing_77.68.34.26 + source { + address 77.68.34.26 + mac-address !00:50:56:16:f0:f3 + } + } + rule 998 { + action drop + description Anti-spoofing_77.68.77.238 + source { + address 77.68.77.238 + mac-address !00:50:56:25:b8:e7 + } + } + rule 999 { + action drop + description Anti-spoofing_77.68.35.116 + source { + address 77.68.35.116 + mac-address !00:50:56:22:c6:b9 + } + } + rule 1000 { + action drop + description Anti-spoofing_77.68.23.112 + source { + address 77.68.23.112 + mac-address !00:50:56:1f:06:9f + } + } + rule 1001 { + action drop + description Anti-spoofing_77.68.120.241 + source { + address 77.68.120.241 + mac-address !00:50:56:18:1e:aa + } + } + rule 1002 { + action drop + description Anti-spoofing_77.68.34.28 + source { + address 77.68.34.28 + mac-address !00:50:56:24:5e:9a + } + } + rule 1003 { + action drop + description Anti-spoofing_77.68.122.195 + source { + address 77.68.122.195 + mac-address !00:50:56:0d:fd:66 + } + } + rule 1004 { + action drop + description Anti-spoofing_77.68.126.14 + source { + address 77.68.126.14 + mac-address !00:50:56:02:46:82 + } + } + rule 1005 { + action drop + description Anti-spoofing_109.228.38.117 + source { + address 109.228.38.117 + mac-address !00:50:56:05:55:f0 + } + } + rule 1006 { + action drop + description Anti-spoofing_77.68.33.171 + source { + address 77.68.33.171 + mac-address !00:50:56:07:69:46 + } + } + rule 1007 { + action drop + description Anti-spoofing_77.68.24.220 + source { + address 77.68.24.220 + mac-address !00:50:56:1f:53:df + } + } + rule 1008 { + action drop + description Anti-spoofing_88.208.197.23 + source { + address 88.208.197.23 + mac-address !00:50:56:23:fa:2f + } + } + rule 1009 { + action drop + description Anti-spoofing_77.68.80.26 + source { + address 77.68.80.26 + mac-address !00:50:56:21:23:8e + } + } + rule 1010 { + action drop + description Anti-spoofing_77.68.32.83 + source { + address 77.68.32.83 + mac-address !00:50:56:26:5d:1a + } + } + rule 1011 { + action drop + description Anti-spoofing_77.68.95.42 + source { + address 77.68.95.42 + mac-address !00:50:56:00:77:9a + } + } + rule 1012 { + action drop + description Anti-spoofing_213.171.209.217 + source { + address 213.171.209.217 + mac-address !00:50:56:18:7b:c2 + } + } + rule 1014 { + action drop + description Anti-spoofing_109.228.39.249 + source { + address 109.228.39.249 + mac-address !00:50:56:0e:4b:f9 + } + } + rule 1015 { + action drop + description Anti-spoofing_77.68.32.86 + source { + address 77.68.32.86 + mac-address !00:50:56:29:ff:6f + } + } + rule 1016 { + action drop + description Anti-spoofing_77.68.125.218 + source { + address 77.68.125.218 + mac-address !00:50:56:2f:4d:38 + } + } + rule 1017 { + action drop + description Anti-spoofing_77.68.17.186 + source { + address 77.68.17.186 + mac-address !00:50:56:2e:6b:f3 + } + } + rule 1018 { + action drop + description Anti-spoofing_77.68.12.45 + source { + address 77.68.12.45 + mac-address !00:50:56:15:e4:38 + } + } + rule 1019 { + action drop + description Anti-spoofing_109.228.40.247 + source { + address 109.228.40.247 + mac-address !00:50:56:20:62:b7 + } + } + rule 1020 { + action drop + description Anti-spoofing_77.68.32.89 + source { + address 77.68.32.89 + mac-address !00:50:56:2e:21:46 + } + } + rule 1022 { + action drop + description Anti-spoofing_77.68.34.138 + source { + address 77.68.34.138 + mac-address !00:50:56:10:0a:08 + } + } + rule 1023 { + action drop + description Anti-spoofing_77.68.34.139 + source { + address 77.68.34.139 + mac-address !00:50:56:0d:24:2f + } + } + rule 1024 { + action drop + description Anti-spoofing_213.171.208.40 + source { + address 213.171.208.40 + mac-address !00:50:56:07:df:6e + } + } + rule 1026 { + action drop + description Anti-spoofing_109.228.40.226 + source { + address 109.228.40.226 + mac-address !00:50:56:2d:c8:2a + } + } + rule 1028 { + action drop + description Anti-spoofing_185.132.39.109 + source { + address 185.132.39.109 + mac-address !00:50:56:2c:3e:98 + } + } + rule 1029 { + action drop + description Anti-spoofing_109.228.40.207 + source { + address 109.228.40.207 + mac-address !00:50:56:04:ba:9c + } + } + rule 1030 { + action drop + description Anti-spoofing_77.68.48.89 + source { + address 77.68.48.89 + mac-address !00:50:56:33:b3:05 + } + } + rule 1031 { + action drop + description Anti-spoofing_77.68.48.105 + source { + address 77.68.48.105 + mac-address !00:50:56:13:8d:55 + } + } + rule 1032 { + action drop + description Anti-spoofing_77.68.50.142 + source { + address 77.68.50.142 + mac-address !00:50:56:2e:58:85 + } + } + rule 1033 { + action drop + description Anti-spoofing_77.68.49.12 + source { + address 77.68.49.12 + mac-address !00:50:56:0f:ed:da + } + } + rule 1034 { + action drop + description Anti-spoofing_77.68.85.18 + source { + address 77.68.85.18 + mac-address !00:50:56:3b:0a:8b + } + } + rule 1035 { + action drop + description Anti-spoofing_77.68.49.4 + source { + address 77.68.49.4 + mac-address !00:50:56:05:e5:05 + } + } + rule 1036 { + action drop + description Anti-spoofing_109.228.37.187 + source { + address 109.228.37.187 + mac-address !00:50:56:37:21:f0 + } + } + rule 1037 { + action drop + description Anti-spoofing_77.68.49.178 + source { + address 77.68.49.178 + mac-address !00:50:56:26:00:f7 + } + } + rule 1038 { + action drop + description Anti-spoofing_77.68.82.147 + source { + address 77.68.82.147 + mac-address !00:50:56:13:75:25 + } + } + rule 1040 { + action drop + description Anti-spoofing_77.68.24.134 + source { + address 77.68.24.134 + mac-address !00:50:56:29:0b:02 + } + } + rule 1041 { + action drop + description Anti-spoofing_77.68.24.63 + source { + address 77.68.24.63 + mac-address !00:50:56:08:7e:4a + } + } + rule 1042 { + action drop + description Anti-spoofing_77.68.50.91 + source { + address 77.68.50.91 + mac-address !00:50:56:35:b6:4f + } + } + rule 1043 { + action drop + description Anti-spoofing_77.68.49.160 + source { + address 77.68.49.160 + mac-address !00:50:56:0e:29:ce + } + } + rule 1044 { + action drop + description Anti-spoofing_77.68.116.84 + source { + address 77.68.116.84 + mac-address !00:50:56:2d:e7:75 + } + } + rule 1045 { + action drop + description Anti-spoofing_77.68.126.160 + source { + address 77.68.126.160 + mac-address !00:50:56:19:a1:cf + } + } + rule 1046 { + action drop + description Anti-spoofing_185.132.41.240 + source { + address 185.132.41.240 + mac-address !00:50:56:08:f6:7c + } + } + rule 1047 { + action drop + description Anti-spoofing_77.68.50.193 + source { + address 77.68.50.193 + mac-address !00:50:56:0f:44:05 + } + } + rule 1048 { + action drop + description Anti-spoofing_77.68.49.161 + source { + address 77.68.49.161 + mac-address !00:50:56:09:4a:87 + } + } + rule 1049 { + action drop + description Anti-spoofing_109.228.58.134 + source { + address 109.228.58.134 + mac-address !00:50:56:06:82:eb + } + } + rule 1050 { + action drop + description Anti-spoofing_185.132.36.56 + source { + address 185.132.36.56 + mac-address !00:50:56:11:89:a1 + } + } + rule 1051 { + action drop + description Anti-spoofing_77.68.50.198 + source { + address 77.68.50.198 + mac-address !00:50:56:21:8f:66 + } + } + rule 1052 { + action drop + description Anti-spoofing_77.68.100.150 + source { + address 77.68.100.150 + mac-address !00:50:56:3a:15:0a + } + } + rule 1053 { + action drop + description Anti-spoofing_88.208.196.91 + source { + address 88.208.196.91 + mac-address !00:50:56:0a:06:31 + } + } + rule 1054 { + action drop + description Anti-spoofing_185.132.41.148 + source { + address 185.132.41.148 + mac-address !00:50:56:3b:d9:ec + } + } + rule 1055 { + action drop + description Anti-spoofing_213.171.210.25 + source { + address 213.171.210.25 + mac-address !00:50:56:0a:b8:6c + } + } + rule 1056 { + action drop + description Anti-spoofing_77.68.51.214 + source { + address 77.68.51.214 + mac-address !00:50:56:16:29:41 + } + } + rule 1057 { + action drop + description Anti-spoofing_77.68.51.202 + source { + address 77.68.51.202 + mac-address !00:50:56:24:5a:0f + } + } + rule 1058 { + action drop + description Anti-spoofing_77.68.100.132 + source { + address 77.68.100.132 + mac-address !00:50:56:27:18:b7 + } + } + rule 1059 { + action drop + description Anti-spoofing_77.68.77.42 + source { + address 77.68.77.42 + mac-address !00:50:56:34:d1:d5 + } + } + rule 1060 { + action drop + description Anti-spoofing_109.228.39.41 + source { + address 109.228.39.41 + mac-address !00:50:56:2e:6a:41 + } + } + rule 1061 { + action drop + description Anti-spoofing_77.68.100.134 + source { + address 77.68.100.134 + mac-address !00:50:56:19:a0:13 + } + } + rule 1062 { + action drop + description Anti-spoofing_77.68.89.247 + source { + address 77.68.89.247 + mac-address !00:50:56:2b:ed:68 + } + } + rule 1063 { + action drop + description Anti-spoofing_77.68.101.64 + source { + address 77.68.101.64 + mac-address !00:50:56:24:5a:0f + } + } + rule 1064 { + action drop + description Anti-spoofing_88.208.199.249 + source { + address 88.208.199.249 + mac-address !00:50:56:16:3e:ed + } + } + rule 1065 { + action drop + description Anti-spoofing_77.68.101.124 + source { + address 77.68.101.124 + mac-address !00:50:56:15:0e:e0 + } + } + rule 1066 { + action drop + description Anti-spoofing_77.68.101.125 + source { + address 77.68.101.125 + mac-address !00:50:56:33:ce:ff + } + } + rule 1068 { + action drop + description Anti-spoofing_77.68.100.167 + source { + address 77.68.100.167 + mac-address !00:50:56:34:b3:5d + } + } + rule 1069 { + action drop + description Anti-spoofing_77.68.49.152 + source { + address 77.68.49.152 + mac-address !00:50:56:1a:06:95 + } + } + rule 1070 { + action drop + description Anti-spoofing_77.68.103.147 + source { + address 77.68.103.147 + mac-address !00:50:56:2e:52:7f + } + } + rule 1071 { + action drop + description Anti-spoofing_77.68.48.202 + source { + address 77.68.48.202 + mac-address !00:50:56:0b:da:01 + } + } + rule 1072 { + action drop + description Anti-spoofing_77.68.112.175 + source { + address 77.68.112.175 + mac-address !00:50:56:05:9e:e5 + } + } + rule 1073 { + action drop + description Anti-spoofing_109.228.56.97 + source { + address 109.228.56.97 + mac-address !00:50:56:36:cd:04 + } + } + rule 1074 { + action drop + description Anti-spoofing_185.132.37.47 + source { + address 185.132.37.47 + mac-address !00:50:56:3a:de:38 + } + } + rule 1075 { + action drop + description Anti-spoofing_77.68.31.96 + source { + address 77.68.31.96 + mac-address !00:50:56:07:d0:cf + } + } + rule 1076 { + action drop + description Anti-spoofing_109.228.61.37 + source { + address 109.228.61.37 + mac-address !00:50:56:1a:93:80 + } + } + rule 1077 { + action drop + description Anti-spoofing_77.68.33.24 + source { + address 77.68.33.24 + mac-address !00:50:56:0d:ae:e8 + } + } + rule 1078 { + action drop + description Anti-spoofing_88.208.197.135 + source { + address 88.208.197.135 + mac-address !00:50:56:3b:39:6b + } + } + rule 1079 { + action drop + description Anti-spoofing_77.68.103.227 + source { + address 77.68.103.227 + mac-address !00:50:56:28:cd:95 + } + } + rule 1080 { + action drop + description Anti-spoofing_185.132.38.182 + source { + address 185.132.38.182 + mac-address !00:50:56:39:4b:e3 + } + } + rule 1081 { + action drop + description Anti-spoofing_88.208.197.118 + source { + address 88.208.197.118 + mac-address !00:50:56:2c:cd:e3 + } + } + rule 1082 { + action drop + description Anti-spoofing_88.208.196.92 + source { + address 88.208.196.92 + mac-address !00:50:56:05:77:19 + } + } + rule 1083 { + action drop + description Anti-spoofing_88.208.197.150 + source { + address 88.208.197.150 + mac-address !00:50:56:0c:ae:6c + } + } + rule 1084 { + action drop + description Anti-spoofing_88.208.215.121 + source { + address 88.208.215.121 + mac-address !00:50:56:16:0b:60 + } + } + rule 1085 { + action drop + description Anti-spoofing_88.208.197.10 + source { + address 88.208.197.10 + mac-address !00:50:56:1c:8b:fb + } + } + rule 1086 { + action drop + description Anti-spoofing_88.208.198.69 + source { + address 88.208.198.69 + mac-address !00:50:56:06:e7:eb + } + } + rule 1087 { + action drop + description Anti-spoofing_88.208.197.155 + source { + address 88.208.197.155 + mac-address !00:50:56:39:39:8e + } + } + rule 1088 { + action drop + description Anti-spoofing_88.208.198.39 + source { + address 88.208.198.39 + mac-address !00:50:56:22:2d:07 + } + } + rule 1089 { + action drop + description Anti-spoofing_88.208.197.160 + source { + address 88.208.197.160 + mac-address !00:50:56:2e:03:9a + } + } + rule 1090 { + action drop + description Anti-spoofing_88.208.197.60 + source { + address 88.208.197.60 + mac-address !00:50:56:3e:59:7c + } + } + rule 1091 { + action drop + description Anti-spoofing_77.68.102.129 + source { + address 77.68.102.129 + mac-address !00:50:56:2c:9d:a5 + } + } + rule 1092 { + action drop + description Anti-spoofing_88.208.196.123 + source { + address 88.208.196.123 + mac-address !00:50:56:21:ac:31 + } + } + rule 1093 { + action drop + description Anti-spoofing_88.208.215.61 + source { + address 88.208.215.61 + mac-address !00:50:56:05:91:dd + } + } + rule 1094 { + action drop + description Anti-spoofing_88.208.215.62 + source { + address 88.208.215.62 + mac-address !00:50:56:2d:ff:f4 + } + } + rule 1095 { + action drop + description Anti-spoofing_88.208.199.141 + source { + address 88.208.199.141 + mac-address !00:50:56:10:8f:10 + } + } + rule 1096 { + action drop + description Anti-spoofing_88.208.215.157 + source { + address 88.208.215.157 + mac-address !00:50:56:38:d7:1a + } + } + rule 1097 { + action drop + description Anti-spoofing_77.68.21.171 + source { + address 77.68.21.171 + mac-address !00:50:56:29:e0:5f + } + } + rule 1098 { + action drop + description Anti-spoofing_88.208.198.251 + source { + address 88.208.198.251 + mac-address !00:50:56:2b:2a:6a + } + } + rule 1099 { + action drop + description Anti-spoofing_88.208.199.233 + source { + address 88.208.199.233 + mac-address !00:50:56:1e:bf:95 + } + } + rule 1100 { + action drop + description Anti-spoofing_88.208.212.31 + source { + address 88.208.212.31 + mac-address !00:50:56:28:f4:aa + } + } + rule 1101 { + action drop + description Anti-spoofing_88.208.197.129 + source { + address 88.208.197.129 + mac-address !00:50:56:1f:71:bf + } + } + rule 1102 { + action drop + description Anti-spoofing_88.208.199.46 + source { + address 88.208.199.46 + mac-address !00:50:56:34:dc:e5 + } + } + rule 1103 { + action drop + description Anti-spoofing_88.208.212.94 + source { + address 88.208.212.94 + mac-address !00:50:56:3d:f5:16 + } + } + rule 1105 { + action drop + description Anti-spoofing_88.208.212.182 + source { + address 88.208.212.182 + mac-address !00:50:56:12:e4:1b + } + } + rule 1108 { + action drop + description Anti-spoofing_88.208.212.188 + source { + address 88.208.212.188 + mac-address !00:50:56:36:a8:9e + } + } + rule 1500 { + action drop + description "Block port 11211-udp" + protocol udp + source { + group { + address-group CLUSTER_ADDRESSES + } + port 11211 + } + } + rule 1510 { + action drop + description "Test Drive - Outgoing traffic blocked" + destination { + group { + network-group !NAS_NETWORKS + } + } + source { + group { + address-group DT_BLOCKED + } + } + } + rule 1520 { + action drop + description "Deny outgoing SMTP to new contracts" + destination { + port smtp + } + protocol tcp + source { + group { + address-group DT_SMTP_BLOCKED + } + } + } + rule 1600 { + action accept + description "Allow unicast requests to DHCP servers" + destination { + group { + address-group DHCP_SERVERS + } + port bootps + } + protocol tcp_udp + source { + group { + address-group CLUSTER_ADDRESSES + } + } + } + rule 1610 { + action accept + description "Allow DNS queries to dnscache servers" + destination { + group { + address-group DNSCACHE_SERVERS + } + port 53 + } + protocol tcp_udp + source { + group { + address-group CLUSTER_ADDRESSES + } + } + } + rule 1620 { + action accept + destination { + group { + address-group NAS_ARRAYS + } + } + source { + group { + address-group CLUSTER_ADDRESSES + } + } + } + rule 1630 { + action accept + description "Kerberos authentication to Domain Controllers" + destination { + group { + address-group NAS_DOMAIN_CONTROLLERS + } + port 88 + } + protocol tcp_udp + source { + group { + address-group CLUSTER_ADDRESSES + } + } + } + rule 1640 { + action drop + description "Deny rest of the traffic to NAS" + destination { + group { + network-group NAS_NETWORKS + } + } + } + rule 2000 { + action accept + description "TOP port - SSH" + destination { + group { + address-group G-22-TCP + } + port ssh + } + protocol tcp + } + rule 2001 { + action accept + description "TOP port - RDESKTOP" + destination { + group { + address-group G-3389-TCP + } + port 3389 + } + protocol tcp + } + rule 2002 { + action accept + description "TOP port - HTTP" + destination { + group { + address-group G-80-TCP + } + port http + } + protocol tcp + } + rule 2003 { + action accept + description "TOP port - HTTPS" + destination { + group { + address-group G-443-TCP + } + port https + } + protocol tcp + } + rule 2004 { + action accept + description "TOP port - DOMAIN TCP" + destination { + group { + address-group G-53-TCP + } + port domain + } + protocol tcp + } + rule 2005 { + action accept + description "TOP port - DOMAIN UDP" + destination { + group { + address-group G-53-UDP + } + port domain + } + protocol udp + } + rule 2006 { + action accept + description "TOP port - SMTP" + destination { + group { + address-group G-25-TCP + } + port smtp + } + protocol tcp + } + rule 2007 { + action accept + description "TOP port - IMAP" + destination { + group { + address-group G-143-TCP + } + port imap2 + } + protocol tcp + } + rule 2008 { + action accept + description "TOP port - POP3" + destination { + group { + address-group G-110-TCP + } + port pop3 + } + protocol tcp + } + rule 2009 { + action accept + description "TOP port - MSSQL TCP" + destination { + group { + address-group G-1433-TCP + } + port ms-sql-s + } + protocol tcp + } + rule 2010 { + action accept + description "TOP port - MYSQL TCP" + destination { + group { + address-group G-3306-TCP + } + port mysql + } + protocol tcp + } + rule 2011 { + action accept + description "TOP port - FTPDATA" + destination { + group { + address-group G-20-TCP + } + port ftp-data + } + protocol tcp + } + rule 2012 { + action accept + description "TOP port - FTP" + destination { + group { + address-group G-21-TCP + } + port ftp + } + protocol tcp + } + rule 2013 { + action accept + description "TOP port - SSMTP" + destination { + group { + address-group G-465-TCP + } + port ssmtp + } + protocol tcp + } + rule 2014 { + action accept + description "TOP port - SMTPS" + destination { + group { + address-group G-587-TCP + } + port 587 + } + protocol tcp + } + rule 2015 { + action accept + description "TOP port - IMAPS" + destination { + group { + address-group G-993-TCP + } + port imaps + } + protocol tcp + } + rule 2016 { + action accept + description "TOP port - POP3S" + destination { + group { + address-group G-995-TCP + } + port pop3s + } + protocol tcp + } + rule 2017 { + action accept + description "TOP port - TOMCAT" + destination { + group { + address-group G-8080-TCP + } + port 8080 + } + protocol tcp + } + rule 2018 { + action accept + description "TOP port - Alternative HTTPS" + destination { + group { + address-group G-8443-TCP + } + port 8443 + } + protocol tcp + } + rule 2019 { + action accept + description "TOP port - 10000/TCP" + destination { + group { + address-group G-10000-TCP + } + port 10000 + } + protocol tcp + } + rule 2020 { + action accept + description "TOP port - 8447/TCP" + destination { + group { + address-group G-8447-TCP + } + port 8447 + } + protocol tcp + } + rule 2040 { + action accept + description "TOP port - All ports open" + destination { + group { + address-group G-ALL_OPEN + } + } + } + rule 2050 { + action accept + description "ICMP group" + destination { + group { + address-group G-ICMP + } + } + protocol icmp + } + rule 2100 { + action accept + description FW2BB8D_1-TCP-ALLOW-104.192.143.2 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 7999,22 + } + protocol tcp + source { + address 104.192.143.2 + } + } + rule 2101 { + action accept + description FW19987_4-TCP-ALLOW-77.68.74.54 + destination { + group { + address-group DT_FW19987_4 + } + port 443 + } + protocol tcp + source { + address 77.68.74.54 + } + } + rule 2102 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-109.72.210.46 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 109.72.210.46 + } + } + rule 2103 { + action accept + description FW5A77C_16-TCP-ALLOW-213.171.217.107 + destination { + group { + address-group DT_FW5A77C_16 + } + port 22 + } + protocol tcp + source { + address 213.171.217.107 + } + } + rule 2104 { + action accept + description FW826BA_3-TCP-ALLOW-164.177.156.192 + destination { + group { + address-group DT_FW826BA_3 + } + port 3389,1433,21 + } + protocol tcp + source { + address 164.177.156.192 + } + } + rule 2105 { + action accept + description FWDAA4F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDAA4F_1 + } + port 22335 + } + protocol tcp + } + rule 2106 { + action accept + description FW6D0CD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6D0CD_1 + } + port 6900,7000 + } + protocol tcp + } + rule 2107 { + action accept + description FW6D0CD_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6D0CD_1 + } + port 9001 + } + protocol tcp_udp + } + rule 2108 { + action accept + description FW06176_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW06176_1 + } + port 5900 + } + protocol tcp + } + rule 2109 { + action accept + description FW19987_4-TCP-ALLOW-77.68.77.70 + destination { + group { + address-group DT_FW19987_4 + } + port 443 + } + protocol tcp + source { + address 77.68.77.70 + } + } + rule 2110 { + action accept + description FWF7B68_1-TCP-ALLOW-54.221.251.224 + destination { + group { + address-group DT_FWF7B68_1 + } + port 8443,3306,22,21,20 + } + protocol tcp + source { + address 54.221.251.224 + } + } + rule 2111 { + action accept + description FW05AD0_2-TCP-ALLOW-178.251.181.41 + destination { + group { + address-group DT_FW05AD0_2 + } + port 3389,1433,21 + } + protocol tcp + source { + address 178.251.181.41 + } + } + rule 2112 { + action accept + description FW05AD0_2-TCP-ALLOW-178.251.181.6 + destination { + group { + address-group DT_FW05AD0_2 + } + port 3389,1433,21 + } + protocol tcp + source { + address 178.251.181.6 + } + } + rule 2113 { + action accept + description VPN-7030-ANY-ALLOW-10.4.58.119 + destination { + group { + address-group DT_VPN-7030 + } + } + source { + address 10.4.58.119 + } + } + rule 2114 { + action accept + description FW58C69_4-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW58C69_4 + } + port 5666 + } + protocol tcp + } + rule 2115 { + action accept + description FW2BB8D_1-TCP-ALLOW-185.201.180.35 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000,22 + } + protocol tcp + source { + address 185.201.180.35 + } + } + rule 2116 { + action accept + description FW19987_4-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FW19987_4 + } + port 3389,445,443 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2117 { + action accept + description FW19987_4-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FW19987_4 + } + port 3389,445,443 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 2118 { + action accept + description FW5658C_1-TCP-ALLOW-212.159.160.65 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443,3389,3306,22,21 + } + protocol tcp + source { + address 212.159.160.65 + } + } + rule 2119 { + action accept + description FW5658C_1-TCP-ALLOW-79.78.20.149 + destination { + group { + address-group DT_FW5658C_1 + } + port 8447,8443,3389,3306,993,143,22,21 + } + protocol tcp + source { + address 79.78.20.149 + } + } + rule 2120 { + action accept + description FW5658C_1-TCP-ALLOW-77.68.77.185 + destination { + group { + address-group DT_FW5658C_1 + } + port 3306 + } + protocol tcp + source { + address 77.68.77.185 + } + } + rule 2121 { + action accept + description FW5658C_1-TCP-ALLOW-82.165.232.19 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443,3389 + } + protocol tcp + source { + address 82.165.232.19 + } + } + rule 2122 { + action accept + description FW2C5AE_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2C5AE_1 + } + port 30303,5717 + } + protocol tcp_udp + } + rule 2123 { + action accept + description VPN-12899-ANY-ALLOW-10.4.58.207 + destination { + group { + address-group DT_VPN-12899 + } + } + source { + address 10.4.58.207 + } + } + rule 2124 { + action accept + description FW7648D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW7648D_1 + } + port 8501,8050,7801,4444,1443 + } + protocol tcp + } + rule 2125 { + action accept + description FW0C2E6_4-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0C2E6_4 + } + port 1194 + } + protocol udp + } + rule 2126 { + action accept + description FW5658C_1-TCP-ALLOW-39.37.175.132 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 39.37.175.132 + } + } + rule 2127 { + action accept + description FW826BA_3-TCP-ALLOW-165.255.242.223 + destination { + group { + address-group DT_FW826BA_3 + } + port 3389,1433,21 + } + protocol tcp + source { + address 165.255.242.223 + } + } + rule 2128 { + action accept + description VPN-10131-ANY-ALLOW-10.4.56.51 + destination { + group { + address-group DT_VPN-10131 + } + } + source { + address 10.4.56.51 + } + } + rule 2129 { + action accept + description FW2BB8D_1-TCP-ALLOW-212.227.84.142 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 22 + } + protocol tcp + source { + address 212.227.84.142 + } + } + rule 2130 { + action accept + description FW2BB8D_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2BB8D_1 + } + port 53 + } + protocol tcp_udp + } + rule 2131 { + action accept + description FWFDD94_15-TCP-ALLOW-90.29.180.234 + destination { + group { + address-group DT_FWFDD94_15 + } + port 5683,1883 + } + protocol tcp + source { + address 90.29.180.234 + } + } + rule 2132 { + action accept + description VPN-10131-ANY-ALLOW-10.4.57.51 + destination { + group { + address-group DT_VPN-10131 + } + } + source { + address 10.4.57.51 + } + } + rule 2133 { + action accept + description FW2BB8D_1-TCP-ALLOW-109.228.49.193 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 5000 + } + protocol tcp + source { + address 109.228.49.193 + } + } + rule 2134 { + action accept + description FW81138_1-ICMP-ALLOW-3.10.221.168 + destination { + group { + address-group DT_FW81138_1 + } + } + protocol icmp + source { + address 3.10.221.168 + } + } + rule 2135 { + action accept + description FWB28B6_5-AH-ALLOW-77.68.36.46 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol ah + source { + address 77.68.36.46 + } + } + rule 2136 { + action accept + description FWB28B6_5-ESP-ALLOW-77.68.36.46 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol esp + source { + address 77.68.36.46 + } + } + rule 2137 { + action accept + description FW825C8_24-TCP-ALLOW-77.68.87.201 + destination { + group { + address-group DT_FW825C8_24 + } + port 1433 + } + protocol tcp + source { + address 77.68.87.201 + } + } + rule 2138 { + action accept + description FWB28B6_5-AH-ALLOW-213.171.196.146 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol ah + source { + address 213.171.196.146 + } + } + rule 2139 { + action accept + description FWB28B6_5-ESP-ALLOW-213.171.196.146 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol esp + source { + address 213.171.196.146 + } + } + rule 2140 { + action accept + description FWB28B6_5-UDP-ALLOW-213.171.196.146 + destination { + group { + address-group DT_FWB28B6_5 + } + port 500,4500 + } + protocol udp + source { + address 213.171.196.146 + } + } + rule 2141 { + action accept + description FWB28B6_5-TCP_UDP-ALLOW-213.171.196.146 + destination { + group { + address-group DT_FWB28B6_5 + } + port 1701 + } + protocol tcp_udp + source { + address 213.171.196.146 + } + } + rule 2142 { + action accept + description FWB28B6_5-TCP_UDP-ALLOW-77.68.36.46 + destination { + group { + address-group DT_FWB28B6_5 + } + port 1701 + } + protocol tcp_udp + source { + address 77.68.36.46 + } + } + rule 2143 { + action accept + description FWB28B6_5-UDP-ALLOW-77.68.36.46 + destination { + group { + address-group DT_FWB28B6_5 + } + port 500,4500 + } + protocol udp + source { + address 77.68.36.46 + } + } + rule 2144 { + action accept + description VPN-12899-ANY-ALLOW-10.4.59.207 + destination { + group { + address-group DT_VPN-12899 + } + } + source { + address 10.4.59.207 + } + } + rule 2145 { + action accept + description FWB28B6_5-TCP-ALLOW-81.130.141.175 + destination { + group { + address-group DT_FWB28B6_5 + } + port 3389 + } + protocol tcp + source { + address 81.130.141.175 + } + } + rule 2146 { + action accept + description FWB28B6_5-UDP-ALLOW-77.68.38.195 + destination { + group { + address-group DT_FWB28B6_5 + } + port 4500,500 + } + protocol udp + source { + address 77.68.38.195 + } + } + rule 2147 { + action accept + description FWB28B6_5-AH-ALLOW-77.68.38.195 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol ah + source { + address 77.68.38.195 + } + } + rule 2148 { + action accept + description FWB28B6_5-ESP-ALLOW-77.68.38.195 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol esp + source { + address 77.68.38.195 + } + } + rule 2149 { + action accept + description FWB28B6_5-TCP_UDP-ALLOW-77.68.38.195 + destination { + group { + address-group DT_FWB28B6_5 + } + port 1701 + } + protocol tcp_udp + source { + address 77.68.38.195 + } + } + rule 2150 { + action accept + description FW5658C_1-TCP-ALLOW-39.37.178.77 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 39.37.178.77 + } + } + rule 2151 { + action accept + description FW5A77C_16-TCP-ALLOW-51.241.139.56 + destination { + group { + address-group DT_FW5A77C_16 + } + port 22 + } + protocol tcp + source { + address 51.241.139.56 + } + } + rule 2152 { + action accept + description FWA86ED_101-TCP-ALLOW-150.143.57.138 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389 + } + protocol tcp + source { + address 150.143.57.138 + } + } + rule 2153 { + action accept + description FW6ECA4_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6ECA4_1 + } + port 3939,3335,3334,3333,3000,999,444 + } + protocol tcp_udp + } + rule 2154 { + action accept + description FW5658C_1-TCP-ALLOW-39.45.13.20 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 39.45.13.20 + } + } + rule 2155 { + action accept + description FW481D7_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW481D7_1 + } + port 3478 + } + protocol tcp_udp + } + rule 2156 { + action accept + description FW5A5D7_3-GRE-ALLOW-51.219.222.28 + destination { + group { + address-group DT_FW5A5D7_3 + } + } + protocol gre + source { + address 51.219.222.28 + } + } + rule 2157 { + action accept + description FWA86ED_101-TCP-ALLOW-94.195.127.217 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 94.195.127.217 + } + } + rule 2158 { + action accept + description FW2E060_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2E060_1 + } + port 49152-65535,8443-8447 + } + protocol tcp + } + rule 2159 { + action accept + description FWFDD94_15-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWFDD94_15 + } + port 9090,5080,1935 + } + protocol tcp + } + rule 2160 { + action accept + description FW5658C_1-TCP-ALLOW-39.45.190.224 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 39.45.190.224 + } + } + rule 2161 { + action accept + description FW9E550_1-TCP-ALLOW-109.249.187.56 + destination { + group { + address-group DT_FW9E550_1 + } + port 3389 + } + protocol tcp + source { + address 109.249.187.56 + } + } + rule 2162 { + action accept + description FW89619_1-TCP-ALLOW-81.133.80.114 + destination { + group { + address-group DT_FW89619_1 + } + port 22 + } + protocol tcp + source { + address 81.133.80.114 + } + } + rule 2163 { + action accept + description FW8A3FC_3-TCP-ALLOW-212.227.72.218 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 212.227.72.218 + } + } + rule 2164 { + action accept + description FW0E383_9-TCP-ALLOW-151.229.59.51 + destination { + group { + address-group DT_FW0E383_9 + } + port 1433 + } + protocol tcp + source { + address 151.229.59.51 + } + } + rule 2165 { + action accept + description FW8AFF1_7-TCP-ALLOW-178.251.181.41 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433,21 + } + protocol tcp + source { + address 178.251.181.41 + } + } + rule 2166 { + action accept + description FW3CAAB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW3CAAB_1 + } + port 49152-65535,30000-30400,8443-8447,5432,80-110,21-25 + } + protocol tcp + } + rule 2167 { + action accept + description FW91B7A_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW91B7A_1 + } + port 3389,80 + } + protocol tcp_udp + } + rule 2168 { + action accept + description FW40416_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW40416_1 + } + port 1-65535 + } + protocol tcp + } + rule 2169 { + action accept + description FW5A77C_16-TCP-ALLOW-81.151.24.216 + destination { + group { + address-group DT_FW5A77C_16 + } + port 10000,22 + } + protocol tcp + source { + address 81.151.24.216 + } + } + rule 2170 { + action accept + description VPN-7030-ANY-ALLOW-10.4.59.119 + destination { + group { + address-group DT_VPN-7030 + } + } + source { + address 10.4.59.119 + } + } + rule 2171 { + action accept + description FW0E383_9-TCP-ALLOW-62.252.94.138 + destination { + group { + address-group DT_FW0E383_9 + } + port 3389,1433 + } + protocol tcp + source { + address 62.252.94.138 + } + } + rule 2172 { + action accept + description FW89619_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW89619_1 + } + port 5015,5001,5000 + } + protocol tcp + } + rule 2173 { + action accept + description FW89619_1-TCP_UDP-ALLOW-167.98.162.142 + destination { + group { + address-group DT_FW89619_1 + } + port 5060 + } + protocol tcp_udp + source { + address 167.98.162.142 + } + } + rule 2174 { + action accept + description FW013EF_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW013EF_2 + } + port 44445,7770-7800,5090,5060-5070,5015,5001,2000-2500 + } + protocol tcp + } + rule 2175 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.12 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.12 + } + } + rule 2176 { + action accept + description VPN-15625-ANY-ALLOW-10.4.88.79 + destination { + group { + address-group DT_VPN-15625 + } + } + source { + address 10.4.88.79 + } + } + rule 2177 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.228.53.128 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306,22 + } + protocol tcp + source { + address 109.228.53.128 + } + } + rule 2178 { + action accept + description FW8AFF1_7-TCP-ALLOW-178.251.181.6 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 3389,1433,21 + } + protocol tcp + source { + address 178.251.181.6 + } + } + rule 2179 { + action accept + description FW578BE_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW578BE_1 + } + port 23,1521,1522 + } + protocol tcp + } + rule 2180 { + action accept + description FWE012D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE012D_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2181 { + action accept + description FW8AFF1_7-TCP-ALLOW-213.171.209.161 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 3389,1433,21 + } + protocol tcp + source { + address 213.171.209.161 + } + } + rule 2182 { + action accept + description VPN-8203-ANY-ALLOW-10.4.58.109 + destination { + group { + address-group DT_VPN-8203 + } + } + source { + address 10.4.58.109 + } + } + rule 2183 { + action accept + description VPN-9415-ANY-ALLOW-10.4.58.168 + destination { + group { + address-group DT_VPN-9415 + } + } + source { + address 10.4.58.168 + } + } + rule 2184 { + action accept + description VPN-9415-ANY-ALLOW-10.4.59.168 + destination { + group { + address-group DT_VPN-9415 + } + } + source { + address 10.4.59.168 + } + } + rule 2185 { + action accept + description FW27A8F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW27A8F_1 + } + port 9990,8458,8090,6543,5432 + } + protocol tcp + } + rule 2186 { + action accept + description FW2BB8D_1-TCP-ALLOW-77.68.11.224 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 5000 + } + protocol tcp + source { + address 77.68.11.224 + } + } + rule 2187 { + action accept + description VPN-15625-ANY-ALLOW-10.4.89.79 + destination { + group { + address-group DT_VPN-15625 + } + } + source { + address 10.4.89.79 + } + } + rule 2188 { + action accept + description VPN-14649-ANY-ALLOW-10.4.86.35 + destination { + group { + address-group DT_VPN-14649 + } + } + source { + address 10.4.86.35 + } + } + rule 2189 { + action accept + description VPN-14649-ANY-ALLOW-10.4.87.35 + destination { + group { + address-group DT_VPN-14649 + } + } + source { + address 10.4.87.35 + } + } + rule 2190 { + action accept + description VPN-14657-ANY-ALLOW-10.4.86.38 + destination { + group { + address-group DT_VPN-14657 + } + } + source { + address 10.4.86.38 + } + } + rule 2191 { + action accept + description VPN-14657-ANY-ALLOW-10.4.87.38 + destination { + group { + address-group DT_VPN-14657 + } + } + source { + address 10.4.87.38 + } + } + rule 2192 { + action accept + description VPN-14658-ANY-ALLOW-10.4.88.38 + destination { + group { + address-group DT_VPN-14658 + } + } + source { + address 10.4.88.38 + } + } + rule 2193 { + action accept + description VPN-14658-ANY-ALLOW-10.4.89.38 + destination { + group { + address-group DT_VPN-14658 + } + } + source { + address 10.4.89.38 + } + } + rule 2194 { + action accept + description FW0BB22_1-GRE-ALLOW-ANY + destination { + group { + address-group DT_FW0BB22_1 + } + } + protocol gre + } + rule 2195 { + action accept + description FW0BB22_1-ESP-ALLOW-ANY + destination { + group { + address-group DT_FW0BB22_1 + } + } + protocol esp + } + rule 2196 { + action accept + description FW1CC15_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1CC15_2 + } + port 8089,8085,990,81 + } + protocol tcp + } + rule 2197 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.0.124 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.0.124 + } + } + rule 2198 { + action accept + description FW5A5D7_3-TCP-ALLOW-51.219.222.28 + destination { + group { + address-group DT_FW5A5D7_3 + } + port 8172,3389,1723,1701,47 + } + protocol tcp + source { + address 51.219.222.28 + } + } + rule 2199 { + action accept + description FW1CB16_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW1CB16_1 + } + port 3306,27017,53 + } + protocol tcp_udp + } + rule 2200 { + action accept + description FWE47DA_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE47DA_1 + } + port 7770-7800,44445 + } + protocol tcp + } + rule 2201 { + action accept + description FW37E59_5-TCP-ALLOW-77.68.20.244 + destination { + group { + address-group DT_FW37E59_5 + } + port 30303 + } + protocol tcp + source { + address 77.68.20.244 + } + } + rule 2202 { + action accept + description FW274FD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW274FD_1 + } + port 49152-65534 + } + protocol tcp + } + rule 2203 { + action accept + description FW6CD7E_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6CD7E_2 + } + port 49152-65535 + } + protocol tcp + } + rule 2204 { + action accept + description FW826BA_3-TCP-ALLOW-178.17.252.59 + destination { + group { + address-group DT_FW826BA_3 + } + port 21 + } + protocol tcp + source { + address 178.17.252.59 + } + } + rule 2205 { + action accept + description FW89619_1-TCP_UDP-ALLOW-185.83.64.108 + destination { + group { + address-group DT_FW89619_1 + } + port 5060 + } + protocol tcp_udp + source { + address 185.83.64.108 + } + } + rule 2206 { + action accept + description FW0937A_1-TCP-ALLOW-83.135.134.13 + destination { + group { + address-group DT_FW0937A_1 + } + port 22 + } + protocol tcp + source { + address 83.135.134.13 + } + } + rule 2207 { + action accept + description FW2BB8D_1-TCP-ALLOW-77.68.112.64 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000 + } + protocol tcp + source { + address 77.68.112.64 + } + } + rule 2208 { + action accept + description FW6CD7E_2-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6CD7E_2 + } + port 53 + } + protocol tcp_udp + } + rule 2209 { + action accept + description FW1F3D0_6-TCP-ALLOW-194.73.17.47 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306,22 + } + protocol tcp + source { + address 194.73.17.47 + } + } + rule 2210 { + action accept + description FW0E383_9-TCP-ALLOW-77.68.115.33 + destination { + group { + address-group DT_FW0E383_9 + } + port 1433 + } + protocol tcp + source { + address 77.68.115.33 + } + } + rule 2211 { + action accept + description FWA3EA3_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA3EA3_1 + } + port 943 + } + protocol tcp + } + rule 2212 { + action accept + description FW6863A_4-TCP-ALLOW-82.165.100.25 + destination { + group { + address-group DT_FW6863A_4 + } + port 21-10000 + } + protocol tcp + source { + address 82.165.100.25 + } + } + rule 2213 { + action accept + description FWECBFB_14-TCP-ALLOW-109.228.59.50 + destination { + group { + address-group DT_FWECBFB_14 + } + port 22 + } + protocol tcp + source { + address 109.228.59.50 + } + } + rule 2214 { + action accept + description FW2F868_6-TCP-ALLOW-213.171.217.100 + destination { + group { + address-group DT_FW2F868_6 + } + port 22 + } + protocol tcp + source { + address 213.171.217.100 + } + } + rule 2215 { + action accept + description FWD7EAB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD7EAB_1 + } + port 60000-60100 + } + protocol tcp + } + rule 2216 { + action accept + description FWEB321_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWEB321_1 + } + port 113,4190 + } + protocol tcp + } + rule 2217 { + action accept + description FW9C682_3-TCP-ALLOW-195.206.180.132 + destination { + group { + address-group DT_FW9C682_3 + } + port 8443,22 + } + protocol tcp + source { + address 195.206.180.132 + } + } + rule 2218 { + action accept + description VPN-8159-ANY-ALLOW-10.4.58.91 + destination { + group { + address-group DT_VPN-8159 + } + } + source { + address 10.4.58.91 + } + } + rule 2219 { + action accept + description VPN-21673-ANY-ALLOW-10.4.88.187 + destination { + group { + address-group DT_VPN-21673 + } + } + source { + address 10.4.88.187 + } + } + rule 2220 { + action accept + description VPN-21673-ANY-ALLOW-10.4.89.187 + destination { + group { + address-group DT_VPN-21673 + } + } + source { + address 10.4.89.187 + } + } + rule 2221 { + action accept + description VPN-21821-ANY-ALLOW-10.4.88.49 + destination { + group { + address-group DT_VPN-21821 + } + } + source { + address 10.4.88.49 + } + } + rule 2222 { + action accept + description VPN-21821-ANY-ALLOW-10.4.89.49 + destination { + group { + address-group DT_VPN-21821 + } + } + source { + address 10.4.89.49 + } + } + rule 2223 { + action accept + description FWECBFB_14-TCP-ALLOW-81.133.80.58 + destination { + group { + address-group DT_FWECBFB_14 + } + port 22 + } + protocol tcp + source { + address 81.133.80.58 + } + } + rule 2224 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.238 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.238 + } + } + rule 2225 { + action accept + description FW826BA_3-TCP-ALLOW-185.212.168.51 + destination { + group { + address-group DT_FW826BA_3 + } + port 3389,1433,21 + } + protocol tcp + source { + address 185.212.168.51 + } + } + rule 2226 { + action accept + description FW8B21D_1-ANY-ALLOW-212.187.250.2 + destination { + group { + address-group DT_FW8B21D_1 + } + } + source { + address 212.187.250.2 + } + } + rule 2227 { + action accept + description FW35F7B_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW35F7B_1 + } + port 1434 + } + protocol tcp_udp + } + rule 2228 { + action accept + description FWD338A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD338A_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2229 { + action accept + description FW35F7B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW35F7B_1 + } + port 56791 + } + protocol tcp + } + rule 2230 { + action accept + description FW0E383_9-TCP-ALLOW-77.68.77.114 + destination { + group { + address-group DT_FW0E383_9 + } + port 1433 + } + protocol tcp + source { + address 77.68.77.114 + } + } + rule 2231 { + action accept + description FW90AE3_1-TCP-ALLOW-194.74.137.17 + destination { + group { + address-group DT_FW90AE3_1 + } + port 22 + } + protocol tcp + source { + address 194.74.137.17 + } + } + rule 2232 { + action accept + description FW52F6F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW52F6F_1 + } + port 53 + } + protocol tcp_udp + } + rule 2233 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.23.109 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306,22 + } + protocol tcp + source { + address 77.68.23.109 + } + } + rule 2234 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.247 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.247 + } + } + rule 2235 { + action accept + description FW4E314_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW4E314_1 + } + port 53 + } + protocol tcp_udp + } + rule 2236 { + action accept + description FW73573_2-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW73573_2 + } + port 25 + } + protocol tcp_udp + } + rule 2237 { + action accept + description FW0E383_9-TCP-ALLOW-77.68.93.89 + destination { + group { + address-group DT_FW0E383_9 + } + port 1433 + } + protocol tcp + source { + address 77.68.93.89 + } + } + rule 2238 { + action accept + description FW856FA_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW856FA_1 + } + port 6003 + } + protocol tcp + } + rule 2239 { + action accept + description FWECBFB_14-TCP-ALLOW-81.19.214.155 + destination { + group { + address-group DT_FWECBFB_14 + } + port 22 + } + protocol tcp + source { + address 81.19.214.155 + } + } + rule 2240 { + action accept + description FW826BA_3-TCP-ALLOW-51.219.168.170 + destination { + group { + address-group DT_FW826BA_3 + } + port 3389,1433,21 + } + protocol tcp + source { + address 51.219.168.170 + } + } + rule 2241 { + action accept + description FW30D21_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW30D21_1 + } + port 2083-2087,53,2812,2096,25,993,587 + } + protocol tcp_udp + } + rule 2242 { + action accept + description FWA076E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA076E_1 + } + port 2199,2197 + } + protocol tcp + } + rule 2243 { + action accept + description FWA076E_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA076E_1 + } + port 8000-8010 + } + protocol tcp_udp + } + rule 2244 { + action accept + description FW8A3FC_3-TCP-ALLOW-82.165.166.41 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 8447,8443,443,80,22 + } + protocol tcp + source { + address 82.165.166.41 + } + } + rule 2245 { + action accept + description FW2F868_6-TCP-ALLOW-213.171.217.180 + destination { + group { + address-group DT_FW2F868_6 + } + port 22,80 + } + protocol tcp + source { + address 213.171.217.180 + } + } + rule 2246 { + action accept + description FW2F868_6-TCP-ALLOW-213.171.217.184 + destination { + group { + address-group DT_FW2F868_6 + } + port 22 + } + protocol tcp + source { + address 213.171.217.184 + } + } + rule 2247 { + action accept + description FW2F868_6-TCP-ALLOW-213.171.217.185 + destination { + group { + address-group DT_FW2F868_6 + } + port 22 + } + protocol tcp + source { + address 213.171.217.185 + } + } + rule 2248 { + action accept + description FW2F868_6-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2F868_6 + } + port 161 + } + protocol udp + } + rule 2249 { + action accept + description FW2F868_6-TCP-ALLOW-213.171.217.102 + destination { + group { + address-group DT_FW2F868_6 + } + port 22,24 + } + protocol tcp + source { + address 213.171.217.102 + } + } + rule 2250 { + action accept + description FW9C682_3-TCP-ALLOW-80.194.78.162 + destination { + group { + address-group DT_FW9C682_3 + } + port 8443,22 + } + protocol tcp + source { + address 80.194.78.162 + } + } + rule 2251 { + action accept + description VPN-21822-ANY-ALLOW-10.4.54.47 + destination { + group { + address-group DT_VPN-21822 + } + } + source { + address 10.4.54.47 + } + } + rule 2252 { + action accept + description FW825C8_19-TCP-ALLOW-77.68.75.244 + destination { + group { + address-group DT_FW825C8_19 + } + port 1433 + } + protocol tcp + source { + address 77.68.75.244 + } + } + rule 2253 { + action accept + description FW2B279_4-TCP-ALLOW-195.147.173.92 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,22 + } + protocol tcp + source { + address 195.147.173.92 + } + } + rule 2254 { + action accept + description FW1D511_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1D511_2 + } + port 8090 + } + protocol tcp + } + rule 2255 { + action accept + description FW8A3FC_3-TCP-ALLOW-85.17.25.47 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 85.17.25.47 + } + } + rule 2256 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.89.209 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306,22 + } + protocol tcp + source { + address 77.68.89.209 + } + } + rule 2257 { + action accept + description FWE2AB5_8-TCP-ALLOW-213.171.217.184 + destination { + group { + address-group DT_FWE2AB5_8 + } + port 7000 + } + protocol tcp + source { + address 213.171.217.184 + } + } + rule 2258 { + action accept + description FW0E383_9-TCP-ALLOW-77.68.94.177 + destination { + group { + address-group DT_FW0E383_9 + } + port 1433 + } + protocol tcp + source { + address 77.68.94.177 + } + } + rule 2259 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.95.129 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306,22 + } + protocol tcp + source { + address 77.68.95.129 + } + } + rule 2260 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.104.118.136 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 109.104.118.136 + } + } + rule 2261 { + action accept + description FW1FA9E_1-TCP-ALLOW-78.88.254.99 + destination { + group { + address-group DT_FW1FA9E_1 + } + port 9000,8200,5601,4444 + } + protocol tcp + source { + address 78.88.254.99 + } + } + rule 2262 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.46.27 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.46.27 + } + } + rule 2263 { + action accept + description FWA7A50_1-TCP-ALLOW-81.110.192.198 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp + source { + address 81.110.192.198 + } + } + rule 2264 { + action accept + description VPN-21822-ANY-ALLOW-10.4.55.47 + destination { + group { + address-group DT_VPN-21822 + } + } + source { + address 10.4.55.47 + } + } + rule 2265 { + action accept + description FW2BB8D_1-TCP-ALLOW-77.68.31.195 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000 + } + protocol tcp + source { + address 77.68.31.195 + } + } + rule 2266 { + action accept + description FW45BEB_1-TCP-ALLOW-62.3.71.238 + destination { + group { + address-group DT_FW45BEB_1 + } + port 3389 + } + protocol tcp + source { + address 62.3.71.238 + } + } + rule 2267 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.113 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.113 + } + } + rule 2268 { + action accept + description VPN-23946-ANY-ALLOW-10.4.58.13 + destination { + group { + address-group DT_VPN-23946 + } + } + source { + address 10.4.58.13 + } + } + rule 2269 { + action accept + description FW98818_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW98818_1 + } + port 27015 + } + protocol tcp + } + rule 2270 { + action accept + description VPN-23946-ANY-ALLOW-10.4.59.13 + destination { + group { + address-group DT_VPN-23946 + } + } + source { + address 10.4.59.13 + } + } + rule 2271 { + action accept + description VPN-28031-ANY-ALLOW-10.4.88.197 + destination { + group { + address-group DT_VPN-28031 + } + } + source { + address 10.4.88.197 + } + } + rule 2272 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.104.118.231 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 109.104.118.231 + } + } + rule 2273 { + action accept + description FW5A5D7_3-TCP_UDP-ALLOW-51.219.222.28 + destination { + group { + address-group DT_FW5A5D7_3 + } + port 500 + } + protocol tcp_udp + source { + address 51.219.222.28 + } + } + rule 2274 { + action accept + description FW32EFF_25-TCP-ALLOW-185.106.220.231 + destination { + group { + address-group DT_FW32EFF_25 + } + port 443 + } + protocol tcp + source { + address 185.106.220.231 + } + } + rule 2275 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.104.118.66 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 109.104.118.66 + } + } + rule 2276 { + action accept + description FW934AE_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW934AE_1 + } + port 1194 + } + protocol udp + } + rule 2277 { + action accept + description VPN-28031-ANY-ALLOW-10.4.89.197 + destination { + group { + address-group DT_VPN-28031 + } + } + source { + address 10.4.89.197 + } + } + rule 2278 { + action accept + description FW6863A_4-TCP_UDP-ALLOW-82.165.166.41 + destination { + group { + address-group DT_FW6863A_4 + } + port 21-10000 + } + protocol tcp_udp + source { + address 82.165.166.41 + } + } + rule 2279 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.104.119.162 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 109.104.119.162 + } + } + rule 2280 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.74.199.143 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 109.74.199.143 + } + } + rule 2281 { + action accept + description FW1F3D0_6-TCP-ALLOW-185.92.25.48 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 185.92.25.48 + } + } + rule 2282 { + action accept + description FW1F3D0_6-TCP-ALLOW-207.148.2.40 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 207.148.2.40 + } + } + rule 2283 { + action accept + description FW1F3D0_6-TCP-ALLOW-45.76.235.62 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 45.76.235.62 + } + } + rule 2284 { + action accept + description FW1F3D0_6-TCP-ALLOW-45.76.236.93 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 45.76.236.93 + } + } + rule 2285 { + action accept + description FW1F3D0_6-TCP-ALLOW-45.76.59.5 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 45.76.59.5 + } + } + rule 2286 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.15.134 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4444,3306 + } + protocol tcp + source { + address 77.68.15.134 + } + } + rule 2287 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.22.208 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4444,3306 + } + protocol tcp + source { + address 77.68.22.208 + } + } + rule 2288 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.23.108 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 77.68.23.108 + } + } + rule 2289 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.23.54 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 77.68.23.54 + } + } + rule 2290 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.30.45 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 77.68.30.45 + } + } + rule 2291 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.7.198 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 77.68.7.198 + } + } + rule 2292 { + action accept + description VPN-29631-ANY-ALLOW-10.4.54.76 + destination { + group { + address-group DT_VPN-29631 + } + } + source { + address 10.4.54.76 + } + } + rule 2293 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.89.200 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4444,3306 + } + protocol tcp + source { + address 77.68.89.200 + } + } + rule 2294 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.91.50 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 77.68.91.50 + } + } + rule 2295 { + action accept + description FW1F3D0_6-TCP-ALLOW-82.165.206.230 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 82.165.206.230 + } + } + rule 2296 { + action accept + description FW1F3D0_6-TCP-ALLOW-82.165.207.109 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4444,3306 + } + protocol tcp + source { + address 82.165.207.109 + } + } + rule 2297 { + action accept + description FW1F3D0_6-TCP-ALLOW-94.196.156.5 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 94.196.156.5 + } + } + rule 2298 { + action accept + description FW1F3D0_6-TCP_UDP-ALLOW-77.68.15.134 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4567-4568 + } + protocol tcp_udp + source { + address 77.68.15.134 + } + } + rule 2299 { + action accept + description FW1F3D0_6-TCP_UDP-ALLOW-77.68.22.208 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4567-4568 + } + protocol tcp_udp + source { + address 77.68.22.208 + } + } + rule 2300 { + action accept + description FW1F3D0_6-TCP_UDP-ALLOW-77.68.23.109 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4567-4568 + } + protocol tcp_udp + source { + address 77.68.23.109 + } + } + rule 2301 { + action accept + description FW1F3D0_6-TCP_UDP-ALLOW-77.68.89.200 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4567-4568 + } + protocol tcp_udp + source { + address 77.68.89.200 + } + } + rule 2302 { + action accept + description FW05339_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW05339_1 + } + port 8085,5055,5013,5005,444 + } + protocol tcp + } + rule 2303 { + action accept + description FW32EFF_25-TCP-ALLOW-217.169.61.164 + destination { + group { + address-group DT_FW32EFF_25 + } + port 443 + } + protocol tcp + source { + address 217.169.61.164 + } + } + rule 2304 { + action accept + description FW89619_1-TCP_UDP-ALLOW-185.83.65.45 + destination { + group { + address-group DT_FW89619_1 + } + port 5060 + } + protocol tcp_udp + source { + address 185.83.65.45 + } + } + rule 2305 { + action accept + description VPN-13983-ANY-ALLOW-10.4.58.176 + destination { + group { + address-group DT_VPN-13983 + } + } + source { + address 10.4.58.176 + } + } + rule 2306 { + action accept + description FWDAF47_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWDAF47_1 + } + port 8090,7080,443,53 + } + protocol tcp_udp + } + rule 2307 { + action accept + description VPN-29631-ANY-ALLOW-10.4.55.77 + destination { + group { + address-group DT_VPN-29631 + } + } + source { + address 10.4.55.77 + } + } + rule 2308 { + action accept + description VPN-34309-ANY-ALLOW-10.4.58.142 + destination { + group { + address-group DT_VPN-34309 + } + } + source { + address 10.4.58.142 + } + } + rule 2309 { + action accept + description FW27949_2-TCP-ALLOW-138.124.142.180 + destination { + group { + address-group DT_FW27949_2 + } + port 443,80 + } + protocol tcp + source { + address 138.124.142.180 + } + } + rule 2310 { + action accept + description FWF8F85_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF8F85_1 + } + port 3306 + } + protocol tcp_udp + } + rule 2311 { + action accept + description FWDAF47_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDAF47_1 + } + port 40110-40210 + } + protocol tcp + } + rule 2312 { + action accept + description VPN-34309-ANY-ALLOW-10.4.59.142 + destination { + group { + address-group DT_VPN-34309 + } + } + source { + address 10.4.59.142 + } + } + rule 2313 { + action accept + description FWA0531_1-TCP-ALLOW-87.224.39.220 + destination { + group { + address-group DT_FWA0531_1 + } + port 22 + } + protocol tcp + source { + address 87.224.39.220 + } + } + rule 2314 { + action accept + description FW5A5D7_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW5A5D7_3 + } + port 1334 + } + protocol tcp + } + rule 2315 { + action accept + description FW8C927_1-TCP_UDP-ALLOW-84.92.125.78 + destination { + group { + address-group DT_FW8C927_1 + } + port 3306,22 + } + protocol tcp_udp + source { + address 84.92.125.78 + } + } + rule 2316 { + action accept + description FW8C927_1-TCP_UDP-ALLOW-88.208.238.152 + destination { + group { + address-group DT_FW8C927_1 + } + port 3306,22 + } + protocol tcp_udp + source { + address 88.208.238.152 + } + } + rule 2317 { + action accept + description FW81138_1-ICMP-ALLOW-82.165.232.19 + destination { + group { + address-group DT_FW81138_1 + } + } + protocol icmp + source { + address 82.165.232.19 + } + } + rule 2318 { + action accept + description FW28892_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW28892_1 + } + port 7000 + } + protocol tcp + } + rule 2319 { + action accept + description FWC96A1_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC96A1_1 + } + port 222 + } + protocol tcp + } + rule 2320 { + action accept + description VPN-13983-ANY-ALLOW-10.4.59.176 + destination { + group { + address-group DT_VPN-13983 + } + } + source { + address 10.4.59.176 + } + } + rule 2321 { + action accept + description FW2FB61_1-TCP-ALLOW-5.183.104.15 + destination { + group { + address-group DT_FW2FB61_1 + } + port 22 + } + protocol tcp + source { + address 5.183.104.15 + } + } + rule 2322 { + action accept + description FW81138_1-ICMP-ALLOW-82.20.69.137 + destination { + group { + address-group DT_FW81138_1 + } + } + protocol icmp + source { + address 82.20.69.137 + } + } + rule 2323 { + action accept + description FW72F37_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW72F37_1 + } + port 7770-7800,44445 + } + protocol tcp + } + rule 2324 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-81.111.155.34 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 81.111.155.34 + } + } + rule 2325 { + action accept + description VPN-20306-ANY-ALLOW-10.4.88.173 + destination { + group { + address-group DT_VPN-20306 + } + } + source { + address 10.4.88.173 + } + } + rule 2326 { + action accept + description FW6C992_1-TCP-ALLOW-89.33.185.0_24 + destination { + group { + address-group DT_FW6C992_1 + } + port 8447,8443,22 + } + protocol tcp + source { + address 89.33.185.0/24 + } + } + rule 2327 { + action accept + description FW2FB61_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2FB61_1 + } + port 45000 + } + protocol tcp + } + rule 2328 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.46.202 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 175.157.46.202 + } + } + rule 2329 { + action accept + description FWF9C28_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF9C28_2 + } + port 7770-7800,44445 + } + protocol tcp + } + rule 2330 { + action accept + description FW3DBF8_9-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW3DBF8_9 + } + port 8088,8080,5090,5060,3478,1935 + } + protocol tcp_udp + } + rule 2331 { + action accept + description FW3DBF8_9-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW3DBF8_9 + } + port 5062,5061,5015,5001 + } + protocol tcp + } + rule 2332 { + action accept + description VPN-16402-ANY-ALLOW-10.4.88.60 + destination { + group { + address-group DT_VPN-16402 + } + } + source { + address 10.4.88.60 + } + } + rule 2333 { + action accept + description FWC1315_1-TCP-ALLOW-62.3.71.238 + destination { + group { + address-group DT_FWC1315_1 + } + port 3389 + } + protocol tcp + source { + address 62.3.71.238 + } + } + rule 2334 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA7A50_1 + } + port 8001,80 + } + protocol tcp_udp + } + rule 2335 { + action accept + description FWAFF0A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWAFF0A_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2336 { + action accept + description FW2B279_4-TCP-ALLOW-195.20.253.19 + destination { + group { + address-group DT_FW2B279_4 + } + port 22 + } + protocol tcp + source { + address 195.20.253.19 + } + } + rule 2337 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.73 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.73 + } + } + rule 2338 { + action accept + description VPN-16402-ANY-ALLOW-10.4.89.60 + destination { + group { + address-group DT_VPN-16402 + } + } + source { + address 10.4.89.60 + } + } + rule 2339 { + action accept + description VPN-15951-ANY-ALLOW-10.4.86.90 + destination { + group { + address-group DT_VPN-15951 + } + } + source { + address 10.4.86.90 + } + } + rule 2340 { + action accept + description FW2BB8D_1-TCP-ALLOW-77.68.77.181 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000 + } + protocol tcp + source { + address 77.68.77.181 + } + } + rule 2341 { + action accept + description FWE9F7D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE9F7D_1 + } + port 4035 + } + protocol tcp + } + rule 2342 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.131 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.131 + } + } + rule 2343 { + action accept + description VPN-15951-ANY-ALLOW-10.4.87.90 + destination { + group { + address-group DT_VPN-15951 + } + } + source { + address 10.4.87.90 + } + } + rule 2344 { + action accept + description FW2BB8D_1-TCP-ALLOW-77.68.93.190 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000 + } + protocol tcp + source { + address 77.68.93.190 + } + } + rule 2345 { + action accept + description VPN-8159-ANY-ALLOW-10.4.59.91 + destination { + group { + address-group DT_VPN-8159 + } + } + source { + address 10.4.59.91 + } + } + rule 2346 { + action accept + description VPN-12870-ANY-ALLOW-10.4.54.67 + destination { + group { + address-group DT_VPN-12870 + } + } + source { + address 10.4.54.67 + } + } + rule 2347 { + action accept + description FW930F3_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW930F3_1 + } + port 53 + } + protocol tcp_udp + } + rule 2348 { + action accept + description FW12C32_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW12C32_1 + } + port 465,53,25 + } + protocol tcp_udp + } + rule 2349 { + action accept + description FW28EC8_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW28EC8_1 + } + port 20443 + } + protocol tcp + } + rule 2350 { + action accept + description VPN-12870-ANY-ALLOW-10.4.55.68 + destination { + group { + address-group DT_VPN-12870 + } + } + source { + address 10.4.55.68 + } + } + rule 2351 { + action accept + description FW934AE_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW934AE_1 + } + port 32401,32400,8081 + } + protocol tcp_udp + } + rule 2352 { + action accept + description FW6863A_4-TCP-ALLOW-185.173.161.154 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 185.173.161.154 + } + } + rule 2353 { + action accept + description FW013EF_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW013EF_2 + } + port 10600-10998,9000-9398,5090,5060-5070 + } + protocol udp + } + rule 2354 { + action accept + description FW85040_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW85040_1 + } + port 3210 + } + protocol tcp_udp + } + rule 2355 { + action accept + description FW8B21D_1-TCP_UDP-ALLOW-131.153.100.98 + destination { + group { + address-group DT_FW8B21D_1 + } + port 22 + } + protocol tcp_udp + source { + address 131.153.100.98 + } + } + rule 2356 { + action accept + description FW8B21D_1-TCP_UDP-ALLOW-213.133.99.176 + destination { + group { + address-group DT_FW8B21D_1 + } + port 22 + } + protocol tcp_udp + source { + address 213.133.99.176 + } + } + rule 2357 { + action accept + description FW6EFD7_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6EFD7_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2358 { + action accept + description FW8B21D_1-TCP_UDP-ALLOW-62.253.153.163 + destination { + group { + address-group DT_FW8B21D_1 + } + port 8443,22 + } + protocol tcp_udp + source { + address 62.253.153.163 + } + } + rule 2359 { + action accept + description FWCB0CF_7-TCP-ALLOW-212.159.153.201 + destination { + group { + address-group DT_FWCB0CF_7 + } + port 6443,5432-5434,5000-5100,3306-3308,990,989,22,21 + } + protocol tcp + source { + address 212.159.153.201 + } + } + rule 2360 { + action accept + description FW75CA4_6-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW75CA4_6 + } + port 51472,3747,3420 + } + protocol tcp + } + rule 2361 { + action accept + description FWF9C28_4-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF9C28_4 + } + port 23,7770-7800,44445,6109 + } + protocol tcp + } + rule 2362 { + action accept + description FW6B39D_1-TCP-ALLOW-120.72.95.88_29 + destination { + group { + address-group DT_FW6B39D_1 + } + port 3306 + } + protocol tcp + source { + address 120.72.95.88/29 + } + } + rule 2363 { + action accept + description FW934AE_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW934AE_1 + } + port 20000 + } + protocol tcp + } + rule 2364 { + action accept + description FW12C32_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW12C32_1 + } + port 2323,953 + } + protocol tcp + } + rule 2365 { + action accept + description FW49897_1-TCP-ALLOW-2.121.90.207 + destination { + group { + address-group DT_FW49897_1 + } + port 22 + } + protocol tcp + source { + address 2.121.90.207 + } + } + rule 2366 { + action accept + description FW6B39D_1-TCP-ALLOW-120.72.91.104_29 + destination { + group { + address-group DT_FW6B39D_1 + } + port 3306 + } + protocol tcp + source { + address 120.72.91.104/29 + } + } + rule 2367 { + action accept + description FW4F5EE_10-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4F5EE_10 + } + port 83,86,82 + } + protocol tcp + } + rule 2368 { + action accept + description FWF791C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF791C_1 + } + port 6001 + } + protocol tcp + } + rule 2369 { + action accept + description FWEF92E_5-ESP-ALLOW-109.228.37.19 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 109.228.37.19 + } + } + rule 2370 { + action accept + description FWE57AD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE57AD_1 + } + port 57000-58000 + } + protocol tcp + } + rule 2371 { + action accept + description FWC0CE0_1-TCP-ALLOW-62.232.209.221 + destination { + group { + address-group DT_FWC0CE0_1 + } + port 49152-65535,8447,8443,22,21 + } + protocol tcp + source { + address 62.232.209.221 + } + } + rule 2372 { + action accept + description FW0192C_1-TCP-ALLOW-41.140.242.86 + destination { + group { + address-group DT_FW0192C_1 + } + port 3306,22 + } + protocol tcp + source { + address 41.140.242.86 + } + } + rule 2373 { + action accept + description FWEEC75_1-TCP-ALLOW-54.171.71.110 + destination { + group { + address-group DT_FWEEC75_1 + } + port 21 + } + protocol tcp + source { + address 54.171.71.110 + } + } + rule 2374 { + action accept + description FW8B21D_1-TCP_UDP-ALLOW-95.149.182.69 + destination { + group { + address-group DT_FW8B21D_1 + } + port 22 + } + protocol tcp_udp + source { + address 95.149.182.69 + } + } + rule 2375 { + action accept + description FW8B21D_1-TCP-ALLOW-185.201.16.0_22 + destination { + group { + address-group DT_FW8B21D_1 + } + port 25 + } + protocol tcp + source { + address 185.201.16.0/22 + } + } + rule 2376 { + action accept + description FW8B21D_1-TCP-ALLOW-213.133.99.176 + destination { + group { + address-group DT_FW8B21D_1 + } + port 25 + } + protocol tcp + source { + address 213.133.99.176 + } + } + rule 2377 { + action accept + description FW8B21D_1-TCP-ALLOW-95.211.160.147 + destination { + group { + address-group DT_FW8B21D_1 + } + port 25 + } + protocol tcp + source { + address 95.211.160.147 + } + } + rule 2378 { + action accept + description FW6863A_4-TCP-ALLOW-212.227.9.72 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 212.227.9.72 + } + } + rule 2379 { + action accept + description FW8B21D_1-ESP-ALLOW-ANY + destination { + group { + address-group DT_FW8B21D_1 + } + } + protocol esp + } + rule 2380 { + action accept + description FW8B21D_1-AH-ALLOW-ANY + destination { + group { + address-group DT_FW8B21D_1 + } + } + protocol ah + } + rule 2381 { + action accept + description FW8B21D_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW8B21D_1 + } + port 8181,4500,1194,993,941,500,53 + } + protocol tcp_udp + } + rule 2382 { + action accept + description FW6863A_4-TCP-ALLOW-85.17.25.47 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 85.17.25.47 + } + } + rule 2383 { + action accept + description FW6863A_4-TCP-ALLOW-91.232.105.39 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 91.232.105.39 + } + } + rule 2384 { + action accept + description FW6863A_4-TCP-ALLOW-93.190.142.120 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 93.190.142.120 + } + } + rule 2385 { + action accept + description FW6863A_4-TCP-ALLOW-95.168.171.130 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 95.168.171.130 + } + } + rule 2386 { + action accept + description FW6863A_4-TCP-ALLOW-95.168.171.157 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 95.168.171.157 + } + } + rule 2387 { + action accept + description FWD4A27_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD4A27_1 + } + port 32400 + } + protocol tcp + } + rule 2388 { + action accept + description FW2ACFF_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2ACFF_1 + } + port 10299,60050-60055 + } + protocol tcp_udp + } + rule 2389 { + action accept + description FWCB0CF_7-TCP-ALLOW-193.248.62.45 + destination { + group { + address-group DT_FWCB0CF_7 + } + port 22 + } + protocol tcp + source { + address 193.248.62.45 + } + } + rule 2390 { + action accept + description FWCB0CF_7-TCP-ALLOW-78.249.208.17 + destination { + group { + address-group DT_FWCB0CF_7 + } + port 22 + } + protocol tcp + source { + address 78.249.208.17 + } + } + rule 2391 { + action accept + description FWC8E8E_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC8E8E_1 + } + port 6000 + } + protocol tcp_udp + } + rule 2392 { + action accept + description FW30D21_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW30D21_1 + } + port 2476 + } + protocol tcp + } + rule 2393 { + action accept + description FW0192C_1-TCP-ALLOW-41.140.242.94 + destination { + group { + address-group DT_FW0192C_1 + } + port 3306,22 + } + protocol tcp + source { + address 41.140.242.94 + } + } + rule 2394 { + action accept + description FW59F39_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW59F39_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2395 { + action accept + description FWEF92E_7-ESP-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_7 + } + } + protocol esp + source { + address 77.68.77.57 + } + } + rule 2396 { + action accept + description FW826BA_3-TCP-ALLOW-51.219.47.177 + destination { + group { + address-group DT_FW826BA_3 + } + port 3389,21 + } + protocol tcp + source { + address 51.219.47.177 + } + } + rule 2397 { + action accept + description FW826BA_3-TCP-ALLOW-86.172.128.50 + destination { + group { + address-group DT_FW826BA_3 + } + port 1433,21 + } + protocol tcp + source { + address 86.172.128.50 + } + } + rule 2398 { + action accept + description FW826BA_3-TCP-ALLOW-88.105.1.20 + destination { + group { + address-group DT_FW826BA_3 + } + port 21 + } + protocol tcp + source { + address 88.105.1.20 + } + } + rule 2399 { + action accept + description FW6863A_4-TCP-ALLOW-95.211.243.198 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 95.211.243.198 + } + } + rule 2400 { + action accept + description FW25843_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW25843_1 + } + port 9001,7070,5500,5488,5000,4500,4000,3500,3000,1883,1880 + } + protocol tcp + } + rule 2401 { + action accept + description FW89619_1-TCP_UDP-ALLOW-185.83.65.46 + destination { + group { + address-group DT_FW89619_1 + } + port 5060 + } + protocol tcp_udp + source { + address 185.83.65.46 + } + } + rule 2402 { + action accept + description FW5858F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW5858F_1 + } + port 1883 + } + protocol tcp + } + rule 2403 { + action accept + description FW826BA_3-TCP-ALLOW-95.147.108.173 + destination { + group { + address-group DT_FW826BA_3 + } + port 21 + } + protocol tcp + source { + address 95.147.108.173 + } + } + rule 2404 { + action accept + description FW9C682_3-TCP-ALLOW-52.56.193.88 + destination { + group { + address-group DT_FW9C682_3 + } + port 3306 + } + protocol tcp + source { + address 52.56.193.88 + } + } + rule 2405 { + action accept + description FW0745F_5-TCP-ALLOW-109.228.63.82 + destination { + group { + address-group DT_FW0745F_5 + } + port 5666 + } + protocol tcp + source { + address 109.228.63.82 + } + } + rule 2406 { + action accept + description FWC0CE0_1-TCP-ALLOW-90.255.228.213 + destination { + group { + address-group DT_FWC0CE0_1 + } + port 49152-65535,8443,21 + } + protocol tcp + source { + address 90.255.228.213 + } + } + rule 2407 { + action accept + description FW210E2_8-AH-ALLOW-ANY + destination { + group { + address-group DT_FW210E2_8 + } + } + protocol ah + } + rule 2408 { + action accept + description FW210E2_8-ESP-ALLOW-ANY + destination { + group { + address-group DT_FW210E2_8 + } + } + protocol esp + } + rule 2409 { + action accept + description FW210E2_8-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW210E2_8 + } + port 41,62000,23,4500,50,9876,3391,88,135 + } + protocol tcp + } + rule 2410 { + action accept + description FW210E2_8-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW210E2_8 + } + port 500 + } + protocol udp + } + rule 2411 { + action accept + description VPN-8625-ANY-ALLOW-10.4.54.103 + destination { + group { + address-group DT_VPN-8625 + } + } + source { + address 10.4.54.103 + } + } + rule 2412 { + action accept + description VPN-8625-ANY-ALLOW-10.4.55.104 + destination { + group { + address-group DT_VPN-8625 + } + } + source { + address 10.4.55.104 + } + } + rule 2413 { + action accept + description FW73A64_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW73A64_1 + } + port 61616,8181,8161,8082,4244,4243,4242,4241 + } + protocol tcp + } + rule 2414 { + action accept + description VPN-19135-ANY-ALLOW-10.4.86.165 + destination { + group { + address-group DT_VPN-19135 + } + } + source { + address 10.4.86.165 + } + } + rule 2415 { + action accept + description FWCB0CF_7-TCP-ALLOW-82.65.107.3 + destination { + group { + address-group DT_FWCB0CF_7 + } + port 22 + } + protocol tcp + source { + address 82.65.107.3 + } + } + rule 2416 { + action accept + description FWCB0CF_7-TCP-ALLOW-195.2.139.221 + destination { + group { + address-group DT_FWCB0CF_7 + } + port 5432-5434,3306-3308 + } + protocol tcp + source { + address 195.2.139.221 + } + } + rule 2417 { + action accept + description VPN-19135-ANY-ALLOW-10.4.87.165 + destination { + group { + address-group DT_VPN-19135 + } + } + source { + address 10.4.87.165 + } + } + rule 2418 { + action accept + description FW2BB8D_1-TCP-ALLOW-87.75.109.83 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000 + } + protocol tcp + source { + address 87.75.109.83 + } + } + rule 2419 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.83 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.83 + } + } + rule 2420 { + action accept + description FW2ED4D_2-TCP-ALLOW-84.92.65.192 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 22 + } + protocol tcp + source { + address 84.92.65.192 + } + } + rule 2421 { + action accept + description FW73A64_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW73A64_1 + } + port 9200,5601,4247,4246,4245 + } + protocol tcp_udp + } + rule 2422 { + action accept + description FW4735F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4735F_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2423 { + action accept + description FW2ED4D_2-TCP-ALLOW-109.176.154.238 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 7990,3389 + } + protocol tcp + source { + address 109.176.154.238 + } + } + rule 2424 { + action accept + description FW6863A_4-TCP-ALLOW-95.211.243.206 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 95.211.243.206 + } + } + rule 2425 { + action accept + description FW89619_1-TCP_UDP-ALLOW-81.133.80.114 + destination { + group { + address-group DT_FW89619_1 + } + port 5060 + } + protocol tcp_udp + source { + address 81.133.80.114 + } + } + rule 2426 { + action accept + description FW89619_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW89619_1 + } + port 5090 + } + protocol tcp_udp + } + rule 2427 { + action accept + description FW8A57A_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW8A57A_1 + } + port 49155,49154,7700,53,43 + } + protocol tcp_udp + } + rule 2428 { + action accept + description FW8C72E_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW8C72E_1 + } + port 500,4500 + } + protocol udp + } + rule 2429 { + action accept + description FW2ED4D_2-TCP-ALLOW-18.135.66.162 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 18.135.66.162 + } + } + rule 2430 { + action accept + description FW2C5AE_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2C5AE_1 + } + port 58080,58008,8545,7175 + } + protocol tcp + } + rule 2431 { + action accept + description FW2ED4D_2-TCP-ALLOW-80.209.144.52 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 80.209.144.52 + } + } + rule 2432 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.153.21.103 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 7990,3389 + } + protocol tcp + source { + address 82.153.21.103 + } + } + rule 2433 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.41 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.41 + } + } + rule 2434 { + action accept + description FW0745F_5-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0745F_5 + } + port 32770,8001,7801 + } + protocol tcp + } + rule 2435 { + action accept + description FW85E02_11-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW85E02_11 + } + port 5090,5060 + } + protocol tcp_udp + } + rule 2436 { + action accept + description VPN-21982-ANY-ALLOW-10.4.58.43 + destination { + group { + address-group DT_VPN-21982 + } + } + source { + address 10.4.58.43 + } + } + rule 2437 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.17.52.191 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.17.52.191 + } + } + rule 2438 { + action accept + description FW66347_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW66347_1 + } + port 53 + } + protocol tcp_udp + } + rule 2439 { + action accept + description FW11082_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW11082_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2440 { + action accept + description VPN-21982-ANY-ALLOW-10.4.59.43 + destination { + group { + address-group DT_VPN-21982 + } + } + source { + address 10.4.59.43 + } + } + rule 2441 { + action accept + description FW2BB8D_1-TCP-ALLOW-92.207.193.203 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 5000 + } + protocol tcp + source { + address 92.207.193.203 + } + } + rule 2442 { + action accept + description FWC2D30_1-TCP-ALLOW-77.99.253.161 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,22,21 + } + protocol tcp + source { + address 77.99.253.161 + } + } + rule 2443 { + action accept + description FW0E383_9-TCP-ALLOW-77.99.245.103 + destination { + group { + address-group DT_FW0E383_9 + } + port 3389 + } + protocol tcp + source { + address 77.99.245.103 + } + } + rule 2444 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.19.19.52 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 7990,3389 + } + protocol tcp + source { + address 82.19.19.52 + } + } + rule 2445 { + action accept + description FWEF92E_7-AH-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_7 + } + } + protocol ah + source { + address 77.68.77.57 + } + } + rule 2446 { + action accept + description VPN-16450-ANY-ALLOW-10.4.88.99 + destination { + group { + address-group DT_VPN-16450 + } + } + source { + address 10.4.88.99 + } + } + rule 2447 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.2.186.129 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.2.186.129 + } + } + rule 2448 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.157 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.215.157 + } + } + rule 2449 { + action accept + description FW8EA04_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW8EA04_1 + } + port 1194 + } + protocol udp + } + rule 2450 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.21.59.207 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.21.59.207 + } + } + rule 2451 { + action accept + description FWC2D30_1-TCP-ALLOW-82.9.22.158 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,21 + } + protocol tcp + source { + address 82.9.22.158 + } + } + rule 2452 { + action accept + description FWF3A1B_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF3A1B_1 + } + port 1981,53 + } + protocol tcp_udp + } + rule 2453 { + action accept + description FWEF92E_5-ESP-ALLOW-77.68.11.54 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 77.68.11.54 + } + } + rule 2454 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.40.177.186 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.40.177.186 + } + } + rule 2455 { + action accept + description FW0C25B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0C25B_1 + } + port 49152-65535,5224 + } + protocol tcp + } + rule 2456 { + action accept + description FW85A7C_1-TCP-ALLOW-82.24.242.137 + destination { + group { + address-group DT_FW85A7C_1 + } + port 22 + } + protocol tcp + source { + address 82.24.242.137 + } + } + rule 2457 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.68.25.66 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.68.25.66 + } + } + rule 2458 { + action accept + description FW826BA_3-TCP-ALLOW-51.89.148.173 + destination { + group { + address-group DT_FW826BA_3 + } + port 1433 + } + protocol tcp + source { + address 51.89.148.173 + } + } + rule 2459 { + action accept + description FWA69A0_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA69A0_1 + } + port 48402 + } + protocol udp + } + rule 2460 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.69.79.85 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.69.79.85 + } + } + rule 2461 { + action accept + description FWEF92E_5-ESP-ALLOW-77.68.77.149 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 77.68.77.149 + } + } + rule 2462 { + action accept + description FWEF92E_6-ESP-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_6 + } + } + protocol esp + source { + address 77.68.77.57 + } + } + rule 2463 { + action accept + description FWEF92E_7-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FWEF92E_7 + } + port 3389,445 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2464 { + action accept + description FW49C3D_4-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FW49C3D_4 + } + port 3389,445,443,80 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2465 { + action accept + description FW49C3D_6-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FW49C3D_6 + } + port 3389,445 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2466 { + action accept + description FW34C91_3-TCP-ALLOW-77.68.121.4 + destination { + group { + address-group DT_FW34C91_3 + } + port 1433 + } + protocol tcp + source { + address 77.68.121.4 + } + } + rule 2467 { + action accept + description VPN-16450-ANY-ALLOW-10.4.89.99 + destination { + group { + address-group DT_VPN-16450 + } + } + source { + address 10.4.89.99 + } + } + rule 2468 { + action accept + description FW0BB22_1-AH-ALLOW-ANY + destination { + group { + address-group DT_FW0BB22_1 + } + } + protocol ah + } + rule 2469 { + action accept + description FW2ED4D_2-TCP-ALLOW-86.139.57.116 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 86.139.57.116 + } + } + rule 2470 { + action accept + description FW9E550_1-TCP-ALLOW-86.142.67.13 + destination { + group { + address-group DT_FW9E550_1 + } + port 3389 + } + protocol tcp + source { + address 86.142.67.13 + } + } + rule 2471 { + action accept + description FW8B21D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW8B21D_1 + } + port 2096,2095,2087,2086,2083,2082 + } + protocol tcp + } + rule 2472 { + action accept + description FW050AC_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW050AC_1 + } + port 2087 + } + protocol tcp + } + rule 2473 { + action accept + description FW1FA9E_1-TCP-ALLOW-109.228.50.206 + destination { + group { + address-group DT_FW1FA9E_1 + } + port 5432 + } + protocol tcp + source { + address 109.228.50.206 + } + } + rule 2474 { + action accept + description FW8A3FC_3-TCP-ALLOW-217.23.11.155 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 217.23.11.155 + } + } + rule 2475 { + action accept + description FW2ED4D_2-TCP-ALLOW-88.96.110.198 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 88.96.110.198 + } + } + rule 2476 { + action accept + description FWEAE53_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWEAE53_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2477 { + action accept + description VPN-19474-ANY-ALLOW-10.4.88.161 + destination { + group { + address-group DT_VPN-19474 + } + } + source { + address 10.4.88.161 + } + } + rule 2478 { + action accept + description VPN-19474-ANY-ALLOW-10.4.89.161 + destination { + group { + address-group DT_VPN-19474 + } + } + source { + address 10.4.89.161 + } + } + rule 2479 { + action accept + description FW90AE3_1-TCP-ALLOW-68.33.220.233 + destination { + group { + address-group DT_FW90AE3_1 + } + port 22 + } + protocol tcp + source { + address 68.33.220.233 + } + } + rule 2480 { + action accept + description FWC2D30_1-TCP-ALLOW-86.10.163.127 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,21 + } + protocol tcp + source { + address 86.10.163.127 + } + } + rule 2481 { + action accept + description FW2FB61_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2FB61_1 + } + port 60182 + } + protocol udp + } + rule 2482 { + action accept + description FW85A7C_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW85A7C_1 + } + port 2457,2456 + } + protocol tcp_udp + } + rule 2483 { + action accept + description FWBED52_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBED52_1 + } + port 1221,9000 + } + protocol tcp + } + rule 2484 { + action accept + description FWA86ED_101-TCP-ALLOW-90.250.2.109 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 90.250.2.109 + } + } + rule 2485 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.49 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.213.49 + } + } + rule 2486 { + action accept + description FWEF92E_5-ESP-ALLOW-77.68.77.70 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 77.68.77.70 + } + } + rule 2487 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.250 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.250 + } + } + rule 2488 { + action accept + description FW8A3FC_3-TCP-ALLOW-95.168.171.131 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 95.168.171.131 + } + } + rule 2489 { + action accept + description FW2379F_14-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2379F_14 + } + port 48030,10997,10993,10992,10991,10902,1723,1701 + } + protocol tcp + } + rule 2490 { + action accept + description FW8C927_1-TCP-ALLOW-84.92.125.78 + destination { + group { + address-group DT_FW8C927_1 + } + port 80 + } + protocol tcp + source { + address 84.92.125.78 + } + } + rule 2491 { + action accept + description FWC2D30_1-TCP-ALLOW-86.146.220.229 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,21 + } + protocol tcp + source { + address 86.146.220.229 + } + } + rule 2492 { + action accept + description FW2B279_4-TCP-ALLOW-2.218.5.59 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,22 + } + protocol tcp + source { + address 2.218.5.59 + } + } + rule 2493 { + action accept + description VPN-18830-ANY-ALLOW-10.4.86.156 + destination { + group { + address-group DT_VPN-18830 + } + } + source { + address 10.4.86.156 + } + } + rule 2494 { + action accept + description VPN-18830-ANY-ALLOW-10.4.87.156 + destination { + group { + address-group DT_VPN-18830 + } + } + source { + address 10.4.87.156 + } + } + rule 2495 { + action accept + description FWEF92E_5-ESP-ALLOW-77.68.92.33 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 77.68.92.33 + } + } + rule 2496 { + action accept + description FWA86ED_101-TCP-ALLOW-146.198.100.105 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 146.198.100.105 + } + } + rule 2497 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.55 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.211.55 + } + } + rule 2498 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.84.113 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 123.231.84.113 + } + } + rule 2499 { + action accept + description FW8C72E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW8C72E_1 + } + port 60134,60135 + } + protocol tcp + } + rule 2500 { + action accept + description FWAB44B_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWAB44B_1 + } + port 3306 + } + protocol tcp_udp + } + rule 2501 { + action accept + description FW2379F_14-TCP-ALLOW-51.148.87.29 + destination { + group { + address-group DT_FW2379F_14 + } + port 3389,21 + } + protocol tcp + source { + address 51.148.87.29 + } + } + rule 2502 { + action accept + description VPN-23738-ANY-ALLOW-10.4.56.13 + destination { + group { + address-group DT_VPN-23738 + } + } + source { + address 10.4.56.13 + } + } + rule 2503 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.100 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.210.100 + } + } + rule 2504 { + action accept + description FW996B4_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW996B4_2 + } + port 43595,30160 + } + protocol tcp + } + rule 2505 { + action accept + description FW8871B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW8871B_1 + } + port 15672,8083,8082,8081,5672 + } + protocol tcp + } + rule 2506 { + action accept + description FWAB44B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWAB44B_1 + } + port 9090,8069,5432 + } + protocol tcp + } + rule 2507 { + action accept + description FW6187E_1-ICMP-ALLOW-85.214.201.250 + destination { + group { + address-group DT_FW6187E_1 + } + } + protocol icmp + source { + address 85.214.201.250 + } + } + rule 2508 { + action accept + description FW8A3FC_3-TCP-ALLOW-217.23.11.126 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 217.23.11.126 + } + } + rule 2509 { + action accept + description FW78137_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW78137_1 + } + port 1-65535 + } + protocol tcp + } + rule 2510 { + action accept + description FW32EFF_25-TCP-ALLOW-46.252.65.10 + destination { + group { + address-group DT_FW32EFF_25 + } + port 443 + } + protocol tcp + source { + address 46.252.65.10 + } + } + rule 2511 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.50 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.50 + } + } + rule 2512 { + action accept + description FW6A684_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6A684_1 + } + port 53 + } + protocol tcp_udp + } + rule 2513 { + action accept + description FWF48EB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF48EB_1 + } + port 9204,9202,3395 + } + protocol tcp + } + rule 2514 { + action accept + description FW44217_2-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW44217_2 + } + port 443,80 + } + protocol tcp_udp + } + rule 2515 { + action accept + description FW6187E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6187E_1 + } + port 2282 + } + protocol tcp + } + rule 2516 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.0.58 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.0.58 + } + } + rule 2517 { + action accept + description VPN-34501-ANY-ALLOW-10.4.86.235 + destination { + group { + address-group DT_VPN-34501 + } + } + source { + address 10.4.86.235 + } + } + rule 2518 { + action accept + description FW1271A_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1271A_2 + } + port 5090,5061,5060,5015,5001 + } + protocol tcp + } + rule 2519 { + action accept + description FW1271A_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW1271A_2 + } + port 9000-10999,5090,5060 + } + protocol udp + } + rule 2520 { + action accept + description FW1226C_3-TCP-ALLOW-216.113.160.71 + destination { + group { + address-group DT_FW1226C_3 + } + port 80,22 + } + protocol tcp + source { + address 216.113.160.71 + } + } + rule 2521 { + action accept + description FW32EFF_16-TCP-ALLOW-84.19.45.82 + destination { + group { + address-group DT_FW32EFF_16 + } + port 33888 + } + protocol tcp + source { + address 84.19.45.82 + } + } + rule 2522 { + action accept + description FW03F2E_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW03F2E_1 + } + port 1194 + } + protocol udp + } + rule 2523 { + action accept + description FW03F2E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW03F2E_1 + } + port 4432,4431,4430 + } + protocol tcp + } + rule 2524 { + action accept + description FW1226C_3-TCP-ALLOW-216.113.162.65 + destination { + group { + address-group DT_FW1226C_3 + } + port 80,22 + } + protocol tcp + source { + address 216.113.162.65 + } + } + rule 2525 { + action accept + description VPN-20306-ANY-ALLOW-10.4.89.173 + destination { + group { + address-group DT_VPN-20306 + } + } + source { + address 10.4.89.173 + } + } + rule 2526 { + action accept + description FW8A49A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW8A49A_1 + } + port 2525,8448-65535 + } + protocol tcp + } + rule 2527 { + action accept + description FWD3431_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD3431_2 + } + port 43595,30377,30289 + } + protocol tcp + } + rule 2528 { + action accept + description FW1226C_3-TCP-ALLOW-66.135.200.200 + destination { + group { + address-group DT_FW1226C_3 + } + port 80,22 + } + protocol tcp + source { + address 66.135.200.200 + } + } + rule 2529 { + action accept + description FW1226C_3-TCP-ALLOW-193.28.178.38 + destination { + group { + address-group DT_FW1226C_3 + } + port 80 + } + protocol tcp + source { + address 193.28.178.38 + } + } + rule 2530 { + action accept + description FWAE88B_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWAE88B_1 + } + port 65432,8080,7300,1195,1194,993,587,465,443,442,143,110,80,53,22 + } + protocol tcp_udp + } + rule 2531 { + action accept + description FW1226C_3-TCP-ALLOW-195.234.136.80 + destination { + group { + address-group DT_FW1226C_3 + } + port 80 + } + protocol tcp + source { + address 195.234.136.80 + } + } + rule 2532 { + action accept + description FW1226C_3-TCP-ALLOW-93.94.41.83 + destination { + group { + address-group DT_FW1226C_3 + } + port 80 + } + protocol tcp + source { + address 93.94.41.83 + } + } + rule 2533 { + action accept + description VPN-6103-ANY-ALLOW-10.4.56.102 + destination { + group { + address-group DT_VPN-6103 + } + } + source { + address 10.4.56.102 + } + } + rule 2534 { + action accept + description VPN-6103-ANY-ALLOW-10.4.57.102 + destination { + group { + address-group DT_VPN-6103 + } + } + source { + address 10.4.57.102 + } + } + rule 2535 { + action accept + description FW9E550_1-TCP-ALLOW-86.198.190.104 + destination { + group { + address-group DT_FW9E550_1 + } + port 3389 + } + protocol tcp + source { + address 86.198.190.104 + } + } + rule 2536 { + action accept + description FW34C91_3-TCP-ALLOW-81.149.71.244 + destination { + group { + address-group DT_FW34C91_3 + } + port 1433 + } + protocol tcp + source { + address 81.149.71.244 + } + } + rule 2537 { + action accept + description FW0BB22_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0BB22_1 + } + port 27917,27017,9592,9092,1080,587 + } + protocol tcp_udp + } + rule 2538 { + action accept + description FWC2D30_1-TCP-ALLOW-89.213.26.156 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,21 + } + protocol tcp + source { + address 89.213.26.156 + } + } + rule 2539 { + action accept + description FW34C91_3-UDP-ALLOW-81.149.71.244 + destination { + group { + address-group DT_FW34C91_3 + } + port 1434 + } + protocol udp + source { + address 81.149.71.244 + } + } + rule 2540 { + action accept + description VPN-17207-ANY-ALLOW-10.4.86.121 + destination { + group { + address-group DT_VPN-17207 + } + } + source { + address 10.4.86.121 + } + } + rule 2541 { + action accept + description FW0B352_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0B352_1 + } + port 4500,500 + } + protocol udp + } + rule 2542 { + action accept + description FW85E02_11-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW85E02_11 + } + port 5854,5853,5061 + } + protocol tcp + } + rule 2543 { + action accept + description FW0BB22_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0BB22_1 + } + port 9200,8082 + } + protocol tcp + } + rule 2544 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.140 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.140 + } + } + rule 2545 { + action accept + description FWC2D30_1-TCP-ALLOW-91.125.244.28 + destination { + group { + address-group DT_FWC2D30_1 + } + port 21 + } + protocol tcp + source { + address 91.125.244.28 + } + } + rule 2546 { + action accept + description FWA86ED_101-TCP-ALLOW-86.172.252.221 + destination { + group { + address-group DT_FWA86ED_101 + } + port 80-3389 + } + protocol tcp + source { + address 86.172.252.221 + } + } + rule 2547 { + action accept + description FWC2D30_1-TCP-ALLOW-92.207.184.106 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,21 + } + protocol tcp + source { + address 92.207.184.106 + } + } + rule 2548 { + action accept + description FW45F3D_1-ANY-ALLOW-146.255.0.198 + destination { + group { + address-group DT_FW45F3D_1 + } + } + source { + address 146.255.0.198 + } + } + rule 2549 { + action accept + description FWBFDED_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBFDED_1 + } + port 1723,445 + } + protocol tcp + } + rule 2550 { + action accept + description FW8A3FC_3-TCP-ALLOW-212.227.9.72 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 212.227.9.72 + } + } + rule 2551 { + action accept + description FWE928F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE928F_1 + } + port 2082,2083,2086,2087,2096 + } + protocol tcp + } + rule 2552 { + action accept + description FW5CBB2_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW5CBB2_1 + } + port 2082,2083,2086,2087 + } + protocol tcp + } + rule 2553 { + action accept + description FW63230_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW63230_1 + } + port 445,139 + } + protocol tcp_udp + } + rule 2554 { + action accept + description FW90AE3_1-TCP-ALLOW-71.244.176.5 + destination { + group { + address-group DT_FW90AE3_1 + } + port 22 + } + protocol tcp + source { + address 71.244.176.5 + } + } + rule 2555 { + action accept + description FWA4BC8_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA4BC8_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2556 { + action accept + description VPN-17207-ANY-ALLOW-10.4.87.121 + destination { + group { + address-group DT_VPN-17207 + } + } + source { + address 10.4.87.121 + } + } + rule 2557 { + action accept + description VPN-17558-ANY-ALLOW-10.4.86.143 + destination { + group { + address-group DT_VPN-17558 + } + } + source { + address 10.4.86.143 + } + } + rule 2558 { + action accept + description FWB2CD2_1-TCP-ALLOW-86.167.68.241 + destination { + group { + address-group DT_FWB2CD2_1 + } + port 21 + } + protocol tcp + source { + address 86.167.68.241 + } + } + rule 2559 { + action accept + description FW32EFF_25-TCP-ALLOW-84.19.45.82 + destination { + group { + address-group DT_FW32EFF_25 + } + port 33888,443 + } + protocol tcp + source { + address 84.19.45.82 + } + } + rule 2560 { + action accept + description FW44217_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW44217_2 + } + port 9001,7946,2376 + } + protocol tcp + } + rule 2561 { + action accept + description FW7DAE2_3-TCP-ALLOW-212.227.253.11 + destination { + group { + address-group DT_FW7DAE2_3 + } + port 25,22 + } + protocol tcp + source { + address 212.227.253.11 + } + } + rule 2562 { + action accept + description FW7DAE2_3-TCP-ALLOW-217.160.126.118 + destination { + group { + address-group DT_FW7DAE2_3 + } + port 25,22 + } + protocol tcp + source { + address 217.160.126.118 + } + } + rule 2563 { + action accept + description FWAF6E8_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWAF6E8_1 + } + port 2082,2083,2086,2087,2096 + } + protocol tcp + } + rule 2564 { + action accept + description FWCD7CE_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWCD7CE_1 + } + port 49152-65534 + } + protocol tcp + } + rule 2565 { + action accept + description FW32EFF_16-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW32EFF_16 + } + port 47779,47778,47777,47776 + } + protocol tcp + } + rule 2566 { + action accept + description FW0745F_5-TCP-ALLOW-77.68.117.222 + destination { + group { + address-group DT_FW0745F_5 + } + port 49170 + } + protocol tcp + source { + address 77.68.117.222 + } + } + rule 2567 { + action accept + description FWC2D30_1-TCP-ALLOW-92.207.199.107 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,22,21 + } + protocol tcp + source { + address 92.207.199.107 + } + } + rule 2568 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.0.89 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.0.89 + } + } + rule 2569 { + action accept + description FW8A3FC_3-TCP-ALLOW-190.2.130.41 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 190.2.130.41 + } + } + rule 2570 { + action accept + description FWFDCC7_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWFDCC7_1 + } + port 10000 + } + protocol tcp_udp + } + rule 2571 { + action accept + description FWF19FB_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF19FB_2 + } + port 43595,40001,30616-30631,30531,30204-30435 + } + protocol tcp + } + rule 2572 { + action accept + description FW2B279_4-TCP-ALLOW-213.171.217.107 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,22 + } + protocol tcp + source { + address 213.171.217.107 + } + } + rule 2573 { + action accept + description FW4E314_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4E314_1 + } + port 21543,888 + } + protocol tcp + } + rule 2574 { + action accept + description FW73215_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW73215_1 + } + port 4380 + } + protocol udp + } + rule 2575 { + action accept + description VPN-31301-ANY-ALLOW-10.4.86.223 + destination { + group { + address-group DT_VPN-31301 + } + } + source { + address 10.4.86.223 + } + } + rule 2576 { + action accept + description FW8428B_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW8428B_1 + } + port 48402 + } + protocol udp + } + rule 2577 { + action accept + description FWF3A1B_1-TCP_UDP-ALLOW-185.195.124.169 + destination { + group { + address-group DT_FWF3A1B_1 + } + port 2222 + } + protocol tcp_udp + source { + address 185.195.124.169 + } + } + rule 2578 { + action accept + description FW34C91_3-UDP-ALLOW-77.68.121.4 + destination { + group { + address-group DT_FW34C91_3 + } + port 1434 + } + protocol udp + source { + address 77.68.121.4 + } + } + rule 2579 { + action accept + description FW73215_1-TCP-ALLOW-82.38.58.135 + destination { + group { + address-group DT_FW73215_1 + } + port 10685 + } + protocol tcp + source { + address 82.38.58.135 + } + } + rule 2580 { + action accept + description FW52F6F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW52F6F_1 + } + port 8888 + } + protocol tcp + } + rule 2581 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.86 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.86 + } + } + rule 2582 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.125.13 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.125.13 + } + } + rule 2583 { + action accept + description FWEE03C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWEE03C_1 + } + port 2087,2083 + } + protocol tcp + } + rule 2584 { + action accept + description FW748B7_1-TCP-ALLOW-157.231.123.154 + destination { + group { + address-group DT_FW748B7_1 + } + port 22 + } + protocol tcp + source { + address 157.231.123.154 + } + } + rule 2585 { + action accept + description VPN-34501-ANY-ALLOW-10.4.87.235 + destination { + group { + address-group DT_VPN-34501 + } + } + source { + address 10.4.87.235 + } + } + rule 2586 { + action accept + description FWE47DA_1-TCP-ALLOW-81.134.85.245 + destination { + group { + address-group DT_FWE47DA_1 + } + port 22 + } + protocol tcp + source { + address 81.134.85.245 + } + } + rule 2587 { + action accept + description FWD61BF_1-ANY-ALLOW-193.237.81.213_32 + destination { + group { + address-group DT_FWD61BF_1 + } + } + source { + address 193.237.81.213/32 + } + } + rule 2588 { + action accept + description FW2B279_4-TCP-ALLOW-23.106.238.241 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,3306,22 + } + protocol tcp + source { + address 23.106.238.241 + } + } + rule 2589 { + action accept + description FW2B279_4-TCP-ALLOW-35.204.202.196 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,3306,22 + } + protocol tcp + source { + address 35.204.202.196 + } + } + rule 2590 { + action accept + description FW2B279_4-TCP-ALLOW-35.242.141.128 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,3306,22 + } + protocol tcp + source { + address 35.242.141.128 + } + } + rule 2591 { + action accept + description FWC2EF2_2-TCP-ALLOW-90.251.221.19 + destination { + group { + address-group DT_FWC2EF2_2 + } + port 995,993,587,465,143,110,25,22 + } + protocol tcp + source { + address 90.251.221.19 + } + } + rule 2592 { + action accept + description VPN-14673-ANY-ALLOW-10.4.88.44 + destination { + group { + address-group DT_VPN-14673 + } + } + source { + address 10.4.88.44 + } + } + rule 2593 { + action accept + description FWA83DF_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA83DF_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2594 { + action accept + description FW31525_6-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW31525_6 + } + port 35467 + } + protocol tcp + } + rule 2595 { + action accept + description FW4293B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4293B_1 + } + port 9080,8888,8881,7815,8419 + } + protocol tcp + } + rule 2596 { + action accept + description FW4AE7D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4AE7D_1 + } + port 8083,81 + } + protocol tcp + } + rule 2597 { + action accept + description FWC2D30_1-TCP-ALLOW-143.52.53.22 + destination { + group { + address-group DT_FWC2D30_1 + } + port 22 + } + protocol tcp + source { + address 143.52.53.22 + } + } + rule 2598 { + action accept + description FW44217_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW44217_2 + } + port 7946,4789 + } + protocol udp + } + rule 2599 { + action accept + description FW2B279_4-TCP-ALLOW-46.249.82.162 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,22 + } + protocol tcp + source { + address 46.249.82.162 + } + } + rule 2600 { + action accept + description FW27949_2-TCP-ALLOW-80.95.202.106 + destination { + group { + address-group DT_FW27949_2 + } + port 443,80 + } + protocol tcp + source { + address 80.95.202.106 + } + } + rule 2601 { + action accept + description FWEF92E_5-ESP-ALLOW-77.68.93.82 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 77.68.93.82 + } + } + rule 2602 { + action accept + description FW2ACFF_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2ACFF_1 + } + port 8082,5093 + } + protocol tcp + } + rule 2603 { + action accept + description FWC2EF2_2-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC2EF2_2 + } + port 10000,953,53 + } + protocol tcp_udp + } + rule 2604 { + action accept + description FW0C8E1_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0C8E1_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2605 { + action accept + description FWA86ED_101-TCP_UDP-ALLOW-82.5.189.5 + destination { + group { + address-group DT_FWA86ED_101 + } + port 1-65535 + } + protocol tcp_udp + source { + address 82.5.189.5 + } + } + rule 2606 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.179 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.179 + } + } + rule 2607 { + action accept + description FWEF92E_5-ESP-ALLOW-88.208.198.93 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 88.208.198.93 + } + } + rule 2608 { + action accept + description FW5658C_1-TCP-ALLOW-39.45.43.109 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 39.45.43.109 + } + } + rule 2609 { + action accept + description FW5658C_1-TCP-ALLOW-5.67.3.195 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 5.67.3.195 + } + } + rule 2610 { + action accept + description FWDCA36_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDCA36_3 + } + port 49152-65534,5901 + } + protocol tcp + } + rule 2611 { + action accept + description FWE928F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWE928F_1 + } + port 53 + } + protocol tcp_udp + } + rule 2612 { + action accept + description FW69D6D_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW69D6D_2 + } + port 5001,5090,5060,5015 + } + protocol tcp + } + rule 2613 { + action accept + description FW69D6D_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW69D6D_2 + } + port 5090,5060,9000-9500 + } + protocol udp + } + rule 2614 { + action accept + description VPN-9765-ANY-ALLOW-10.4.56.45 + destination { + group { + address-group DT_VPN-9765 + } + } + source { + address 10.4.56.45 + } + } + rule 2615 { + action accept + description VPN-9765-ANY-ALLOW-10.4.57.45 + destination { + group { + address-group DT_VPN-9765 + } + } + source { + address 10.4.57.45 + } + } + rule 2616 { + action accept + description FW4C136_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW4C136_1 + } + port 1194 + } + protocol tcp_udp + } + rule 2617 { + action accept + description FW6F539_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6F539_1 + } + port 49152-65534 + } + protocol tcp + } + rule 2618 { + action accept + description FWDD089_5-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWDD089_5 + } + port 5666-5667,12489 + } + protocol tcp_udp + } + rule 2619 { + action accept + description FWDD089_5-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDD089_5 + } + port 161-162 + } + protocol tcp + } + rule 2620 { + action accept + description FWEF92E_5-AH-ALLOW-109.228.37.19 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 109.228.37.19 + } + } + rule 2621 { + action accept + description FW0A5C4_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0A5C4_1 + } + port 9000,6697,6667,5000 + } + protocol tcp + } + rule 2622 { + action accept + description FWEF92E_5-AH-ALLOW-77.68.11.54 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 77.68.11.54 + } + } + rule 2623 { + action accept + description FW2BB8D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2BB8D_1 + } + port 7990 + } + protocol tcp + } + rule 2624 { + action accept + description FWAF6E8_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWAF6E8_1 + } + port 7770-7800,44445,53 + } + protocol tcp_udp + } + rule 2625 { + action accept + description FW81286_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW81286_1 + } + port 2082,2083,2086,2087,2096 + } + protocol tcp + } + rule 2626 { + action accept + description FW05064_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW05064_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2627 { + action accept + description FWD7382_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWD7382_1 + } + port 4500,1701,500 + } + protocol udp + } + rule 2628 { + action accept + description FWD7382_1-TCP-ALLOW-174.91.7.198 + destination { + group { + address-group DT_FWD7382_1 + } + port 3389 + } + protocol tcp + source { + address 174.91.7.198 + } + } + rule 2629 { + action accept + description VPN-9484-ANY-ALLOW-10.4.56.164 + destination { + group { + address-group DT_VPN-9484 + } + } + source { + address 10.4.56.164 + } + } + rule 2630 { + action accept + description VPN-9484-ANY-ALLOW-10.4.57.164 + destination { + group { + address-group DT_VPN-9484 + } + } + source { + address 10.4.57.164 + } + } + rule 2631 { + action accept + description VPN-9749-ANY-ALLOW-10.4.58.144 + destination { + group { + address-group DT_VPN-9749 + } + } + source { + address 10.4.58.144 + } + } + rule 2632 { + action accept + description FWEF92E_5-AH-ALLOW-77.68.77.149 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 77.68.77.149 + } + } + rule 2633 { + action accept + description FW10FEE_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW10FEE_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2634 { + action accept + description FW5658C_1-TCP-ALLOW-5.71.30.141 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 5.71.30.141 + } + } + rule 2635 { + action accept + description VPN-9749-ANY-ALLOW-10.4.59.144 + destination { + group { + address-group DT_VPN-9749 + } + } + source { + address 10.4.59.144 + } + } + rule 2636 { + action accept + description FWEF92E_5-AH-ALLOW-77.68.77.70 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 77.68.77.70 + } + } + rule 2637 { + action accept + description FWEF92E_5-AH-ALLOW-77.68.92.33 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 77.68.92.33 + } + } + rule 2638 { + action accept + description FWEF92E_5-AH-ALLOW-77.68.93.82 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 77.68.93.82 + } + } + rule 2639 { + action accept + description FWEF92E_6-AH-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_6 + } + } + protocol ah + source { + address 77.68.77.57 + } + } + rule 2640 { + action accept + description FWEF92E_6-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FWEF92E_6 + } + port 3389,445 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2641 { + action accept + description FWEF92E_5-AH-ALLOW-88.208.198.93 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 88.208.198.93 + } + } + rule 2642 { + action accept + description FWEF92E_7-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FWEF92E_7 + } + port 3389,445 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 2643 { + action accept + description FWEF92E_7-TCP-ALLOW-87.224.6.174 + destination { + group { + address-group DT_FWEF92E_7 + } + port 3389,445 + } + protocol tcp + source { + address 87.224.6.174 + } + } + rule 2644 { + action accept + description FWEF92E_5-TCP-ALLOW-109.228.37.19 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 109.228.37.19 + } + } + rule 2645 { + action accept + description FW49C3D_4-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FW49C3D_4 + } + port 3389,445,80 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 2646 { + action accept + description FW49C3D_4-TCP-ALLOW-82.0.198.226 + destination { + group { + address-group DT_FW49C3D_4 + } + port 3389,445 + } + protocol tcp + source { + address 82.0.198.226 + } + } + rule 2647 { + action accept + description FW49C3D_6-TCP-ALLOW-82.0.198.226 + destination { + group { + address-group DT_FW49C3D_6 + } + port 3389,445 + } + protocol tcp + source { + address 82.0.198.226 + } + } + rule 2648 { + action accept + description FW49C3D_6-TCP-ALLOW-83.100.136.74 + destination { + group { + address-group DT_FW49C3D_6 + } + port 3389,445 + } + protocol tcp + source { + address 83.100.136.74 + } + } + rule 2649 { + action accept + description FWEF92E_6-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FWEF92E_6 + } + port 3389,445 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 2650 { + action accept + description FWEF92E_5-TCP-ALLOW-194.145.189.162 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 194.145.189.162 + } + } + rule 2651 { + action accept + description FW3DBF8_9-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW3DBF8_9 + } + port 9000-10999 + } + protocol udp + } + rule 2652 { + action accept + description VPN-19807-ANY-ALLOW-10.4.86.172 + destination { + group { + address-group DT_VPN-19807 + } + } + source { + address 10.4.86.172 + } + } + rule 2653 { + action accept + description FWEEC75_1-TCP-ALLOW-82.8.245.40 + destination { + group { + address-group DT_FWEEC75_1 + } + port 21 + } + protocol tcp + source { + address 82.8.245.40 + } + } + rule 2654 { + action accept + description FW3AD6F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW3AD6F_1 + } + port 53,465 + } + protocol tcp_udp + } + rule 2655 { + action accept + description FWCDBC7_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWCDBC7_1 + } + port 53 + } + protocol tcp_udp + } + rule 2656 { + action accept + description FWA373F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA373F_1 + } + port 2087,2086,2083,2082 + } + protocol tcp + } + rule 2657 { + action accept + description FW2B279_4-TCP-ALLOW-94.155.221.50 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,22 + } + protocol tcp + source { + address 94.155.221.50 + } + } + rule 2658 { + action accept + description FWC2D30_1-TCP-ALLOW-213.171.217.107 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,22 + } + protocol tcp + source { + address 213.171.217.107 + } + } + rule 2659 { + action accept + description VPN-30791-ANY-ALLOW-10.4.88.215 + destination { + group { + address-group DT_VPN-30791 + } + } + source { + address 10.4.88.215 + } + } + rule 2660 { + action accept + description VPN-30791-ANY-ALLOW-10.4.89.215 + destination { + group { + address-group DT_VPN-30791 + } + } + source { + address 10.4.89.215 + } + } + rule 2661 { + action accept + description FW2EF2C_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2EF2C_1 + } + port 10000,3478 + } + protocol udp + } + rule 2662 { + action accept + description FW32EFF_49-TCP-ALLOW-195.217.232.0_26 + destination { + group { + address-group DT_FW32EFF_49 + } + port 5589 + } + protocol tcp + source { + address 195.217.232.0/26 + } + } + rule 2663 { + action accept + description FW4AE7D_1-TCP-ALLOW-81.136.8.24 + destination { + group { + address-group DT_FW4AE7D_1 + } + port 3389 + } + protocol tcp + source { + address 81.136.8.24 + } + } + rule 2664 { + action accept + description FW2EF2C_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2EF2C_1 + } + port 5222 + } + protocol tcp_udp + } + rule 2665 { + action accept + description FW48A55_2-TCP-ALLOW-86.29.225.60 + destination { + group { + address-group DT_FW48A55_2 + } + port 443,80,22 + } + protocol tcp + source { + address 86.29.225.60 + } + } + rule 2666 { + action accept + description FW48A55_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW48A55_2 + } + port 1337 + } + protocol udp + } + rule 2667 { + action accept + description VPN-11913-ANY-ALLOW-10.4.56.191 + destination { + group { + address-group DT_VPN-11913 + } + } + source { + address 10.4.56.191 + } + } + rule 2668 { + action accept + description FWEF92E_5-TCP-ALLOW-194.145.189.163 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 194.145.189.163 + } + } + rule 2669 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.0.90 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.0.90 + } + } + rule 2670 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.24.66 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.24.66 + } + } + rule 2671 { + action accept + description VPN-11913-ANY-ALLOW-10.4.57.191 + destination { + group { + address-group DT_VPN-11913 + } + } + source { + address 10.4.57.191 + } + } + rule 2672 { + action accept + description FW73573_2-TCP-ALLOW-86.9.185.195 + destination { + group { + address-group DT_FW73573_2 + } + port 22 + } + protocol tcp + source { + address 86.9.185.195 + } + } + rule 2673 { + action accept + description VPN-17558-ANY-ALLOW-10.4.87.143 + destination { + group { + address-group DT_VPN-17558 + } + } + source { + address 10.4.87.143 + } + } + rule 2674 { + action accept + description FW748B7_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW748B7_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2675 { + action accept + description FW16375_5-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW16375_5 + } + port 2082,2083,2086,2087 + } + protocol tcp + } + rule 2676 { + action accept + description FW5A77C_16-TCP-ALLOW-88.98.204.68 + destination { + group { + address-group DT_FW5A77C_16 + } + port 22 + } + protocol tcp + source { + address 88.98.204.68 + } + } + rule 2677 { + action accept + description FW73573_1-TCP-ALLOW-86.9.185.195 + destination { + group { + address-group DT_FW73573_1 + } + port 22 + } + protocol tcp + source { + address 86.9.185.195 + } + } + rule 2678 { + action accept + description FWEF92E_5-TCP-ALLOW-194.145.190.4 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 194.145.190.4 + } + } + rule 2679 { + action accept + description FWC2D30_1-TCP-ALLOW-140.82.112.0_20 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 140.82.112.0/20 + } + } + rule 2680 { + action accept + description FW62858_12-ICMP-ALLOW-77.68.122.41 + destination { + group { + address-group DT_FW62858_12 + } + } + protocol icmp + source { + address 77.68.122.41 + } + } + rule 2681 { + action accept + description FWB118A_1-TCP-ALLOW-147.148.96.136 + destination { + group { + address-group DT_FWB118A_1 + } + port 49152-65534,8447,8443,22,21,20 + } + protocol tcp + source { + address 147.148.96.136 + } + } + rule 2682 { + action accept + description FW5A77C_16-TCP-ALLOW-92.207.237.42 + destination { + group { + address-group DT_FW5A77C_16 + } + port 10000,22 + } + protocol tcp + source { + address 92.207.237.42 + } + } + rule 2683 { + action accept + description FW364CF_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW364CF_1 + } + port 4022,8099 + } + protocol tcp + } + rule 2684 { + action accept + description VPN-25822-ANY-ALLOW-10.4.54.42 + destination { + group { + address-group DT_VPN-25822 + } + } + source { + address 10.4.54.42 + } + } + rule 2685 { + action accept + description FW7F28A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW7F28A_1 + } + port 10051,10050 + } + protocol tcp + } + rule 2686 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.53.159 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.53.159 + } + } + rule 2687 { + action accept + description FWE47DA_1-TCP-ALLOW-185.22.211.0_24 + destination { + group { + address-group DT_FWE47DA_1 + } + port 22 + } + protocol tcp + source { + address 185.22.211.0/24 + } + } + rule 2688 { + action accept + description FWC6301_1-TCP-ALLOW-95.34.208.4 + destination { + group { + address-group DT_FWC6301_1 + } + port 22 + } + protocol tcp + source { + address 95.34.208.4 + } + } + rule 2689 { + action accept + description FW45000_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW45000_1 + } + port 990 + } + protocol tcp + } + rule 2690 { + action accept + description FW481D7_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW481D7_1 + } + port 6789 + } + protocol tcp + } + rule 2691 { + action accept + description VPN-8203-ANY-ALLOW-10.4.59.109 + destination { + group { + address-group DT_VPN-8203 + } + } + source { + address 10.4.59.109 + } + } + rule 2692 { + action accept + description VPN-3575-ANY-ALLOW-10.4.54.124 + destination { + group { + address-group DT_VPN-3575 + } + } + source { + address 10.4.54.124 + } + } + rule 2693 { + action accept + description VPN-3575-ANY-ALLOW-10.4.55.125 + destination { + group { + address-group DT_VPN-3575 + } + } + source { + address 10.4.55.125 + } + } + rule 2694 { + action accept + description FW42661_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW42661_3 + } + port 44445,25672,15672,9876,7770-7800 + } + protocol tcp + } + rule 2695 { + action accept + description FWBF494_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBF494_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2696 { + action accept + description FWD0E22_4-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD0E22_4 + } + port 8000,19005 + } + protocol tcp + } + rule 2697 { + action accept + description FW98818_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW98818_1 + } + port 27015 + } + protocol udp + } + rule 2698 { + action accept + description FW62858_12-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW62858_12 + } + port 5001,5000 + } + protocol tcp + } + rule 2699 { + action accept + description VPN-34006-ANY-ALLOW-10.4.86.242 + destination { + group { + address-group DT_VPN-34006 + } + } + source { + address 10.4.86.242 + } + } + rule 2700 { + action accept + description VPN-34006-ANY-ALLOW-10.4.87.242 + destination { + group { + address-group DT_VPN-34006 + } + } + source { + address 10.4.87.242 + } + } + rule 2701 { + action accept + description FWF879C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF879C_1 + } + port 8888 + } + protocol tcp + } + rule 2702 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.11.54 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.11.54 + } + } + rule 2703 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.74.89 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.74.89 + } + } + rule 2704 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.77.149 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.77.149 + } + } + rule 2705 { + action accept + description FW8A57A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW8A57A_1 + } + port 49153,5666 + } + protocol tcp + } + rule 2706 { + action accept + description FW62858_12-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW62858_12 + } + port 5090,5061,5060 + } + protocol tcp_udp + } + rule 2707 { + action accept + description FW62858_12-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW62858_12 + } + port 9000-10999 + } + protocol udp + } + rule 2708 { + action accept + description FW0E2EE_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0E2EE_1 + } + port 1024-65535 + } + protocol tcp_udp + } + rule 2709 { + action accept + description FWEEC75_1-TCP-ALLOW-82.5.80.210 + destination { + group { + address-group DT_FWEEC75_1 + } + port 22 + } + protocol tcp + source { + address 82.5.80.210 + } + } + rule 2710 { + action accept + description FW4F81F_4-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW4F81F_4 + } + port 26900,27005,27015,51000,51005,51030 + } + protocol tcp_udp + } + rule 2711 { + action accept + description VPN-7902-ANY-ALLOW-10.4.56.78 + destination { + group { + address-group DT_VPN-7902 + } + } + source { + address 10.4.56.78 + } + } + rule 2712 { + action accept + description VPN-7902-ANY-ALLOW-10.4.57.78 + destination { + group { + address-group DT_VPN-7902 + } + } + source { + address 10.4.57.78 + } + } + rule 2713 { + action accept + description FWB36A0_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWB36A0_1 + } + port 20-21,990 + } + protocol tcp_udp + } + rule 2714 { + action accept + description FWD2082_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD2082_1 + } + port 8001,8002 + } + protocol tcp + } + rule 2715 { + action accept + description FW8A3FC_3-TCP-ALLOW-212.8.242.171 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 212.8.242.171 + } + } + rule 2716 { + action accept + description FWB9699_11-TCP-ALLOW-213.171.217.184 + destination { + group { + address-group DT_FWB9699_11 + } + port 443,80,8800,22 + } + protocol tcp + source { + address 213.171.217.184 + } + } + rule 2717 { + action accept + description VPN-11083-ANY-ALLOW-10.4.54.186 + destination { + group { + address-group DT_VPN-11083 + } + } + source { + address 10.4.54.186 + } + } + rule 2718 { + action accept + description VPN-11083-ANY-ALLOW-10.4.55.187 + destination { + group { + address-group DT_VPN-11083 + } + } + source { + address 10.4.55.187 + } + } + rule 2719 { + action accept + description VPN-34583-ANY-ALLOW-10.4.86.243 + destination { + group { + address-group DT_VPN-34583 + } + } + source { + address 10.4.86.243 + } + } + rule 2720 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.84.155 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.84.155 + } + } + rule 2721 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.117 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.117 + } + } + rule 2722 { + action accept + description FW7A9B0_9-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW7A9B0_9 + } + port 11112 + } + protocol tcp + } + rule 2723 { + action accept + description FW3F465_1-TCP-ALLOW-77.68.127.177 + destination { + group { + address-group DT_FW3F465_1 + } + port 3306 + } + protocol tcp + source { + address 77.68.127.177 + } + } + rule 2724 { + action accept + description VPN-34583-ANY-ALLOW-10.4.87.243 + destination { + group { + address-group DT_VPN-34583 + } + } + source { + address 10.4.87.243 + } + } + rule 2725 { + action accept + description FW930F3_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW930F3_1 + } + port 9089,5900,5666,5272 + } + protocol tcp + } + rule 2726 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.165 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.165 + } + } + rule 2727 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.140 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.140 + } + } + rule 2728 { + action accept + description FW90AE3_1-TCP-ALLOW-82.11.114.136 + destination { + group { + address-group DT_FW90AE3_1 + } + port 3306,22 + } + protocol tcp + source { + address 82.11.114.136 + } + } + rule 2729 { + action accept + description FW73215_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW73215_1 + } + port 27015 + } + protocol tcp_udp + } + rule 2730 { + action accept + description FWC2EF2_1-TCP-ALLOW-18.130.156.250 + destination { + group { + address-group DT_FWC2EF2_1 + } + port 22 + } + protocol tcp + source { + address 18.130.156.250 + } + } + rule 2731 { + action accept + description FWC2EF2_1-TCP-ALLOW-90.251.221.19 + destination { + group { + address-group DT_FWC2EF2_1 + } + port 22 + } + protocol tcp + source { + address 90.251.221.19 + } + } + rule 2732 { + action accept + description FW90AE3_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW90AE3_1 + } + port 8765,8001,8000 + } + protocol tcp + } + rule 2733 { + action accept + description FWC2EF2_1-TCP-ALLOW-87.74.110.191 + destination { + group { + address-group DT_FWC2EF2_1 + } + port 8443 + } + protocol tcp + source { + address 87.74.110.191 + } + } + rule 2734 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.77.70 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.77.70 + } + } + rule 2735 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.93 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.93 + } + } + rule 2736 { + action accept + description FW81138_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW81138_1 + } + port 123 + } + protocol udp + } + rule 2737 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.64 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.64 + } + } + rule 2738 { + action accept + description FW03B35_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW03B35_1 + } + port 1-65535 + } + protocol tcp_udp + } + rule 2739 { + action accept + description VPN-19807-ANY-ALLOW-10.4.87.172 + destination { + group { + address-group DT_VPN-19807 + } + } + source { + address 10.4.87.172 + } + } + rule 2740 { + action accept + description FW5658C_1-TCP-ALLOW-94.12.73.154 + destination { + group { + address-group DT_FW5658C_1 + } + port 8447 + } + protocol tcp + source { + address 94.12.73.154 + } + } + rule 2741 { + action accept + description FW5658C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW5658C_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2742 { + action accept + description FW0B352_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0B352_1 + } + port 3443 + } + protocol tcp_udp + } + rule 2743 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FWEF92E_5 + } + port 3389,445,443 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2744 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.92.33 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.92.33 + } + } + rule 2745 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.93.82 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.93.82 + } + } + rule 2746 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.44 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.44 + } + } + rule 2747 { + action accept + description FW34C91_3-TCP-ALLOW-188.220.176.104 + destination { + group { + address-group DT_FW34C91_3 + } + port 1433 + } + protocol tcp + source { + address 188.220.176.104 + } + } + rule 2748 { + action accept + description FW3F465_1-TCP-ALLOW-77.68.16.101 + destination { + group { + address-group DT_FW3F465_1 + } + port 3306 + } + protocol tcp + source { + address 77.68.16.101 + } + } + rule 2749 { + action accept + description FWEF92E_5-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FWEF92E_5 + } + port 3389,445,443 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 2750 { + action accept + description FW34C91_3-UDP-ALLOW-188.220.176.104 + destination { + group { + address-group DT_FW34C91_3 + } + port 1434 + } + protocol udp + source { + address 188.220.176.104 + } + } + rule 2751 { + action accept + description FWE47DA_1-TCP-ALLOW-185.22.208.0_25 + destination { + group { + address-group DT_FWE47DA_1 + } + port 22 + } + protocol tcp + source { + address 185.22.208.0/25 + } + } + rule 2752 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.187 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.187 + } + } + rule 2753 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.84 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.84 + } + } + rule 2754 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.246.52 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 116.206.246.52 + } + } + rule 2755 { + action accept + description FW8AFF1_7-TCP-ALLOW-77.68.92.154 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 77.68.92.154 + } + } + rule 2756 { + action accept + description FW8AFF1_7-TCP-ALLOW-77.68.93.156 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 77.68.93.156 + } + } + rule 2757 { + action accept + description VPN-24398-ANY-ALLOW-10.4.88.151 + destination { + group { + address-group DT_VPN-24398 + } + } + source { + address 10.4.88.151 + } + } + rule 2758 { + action accept + description VPN-24398-ANY-ALLOW-10.4.89.151 + destination { + group { + address-group DT_VPN-24398 + } + } + source { + address 10.4.89.151 + } + } + rule 2759 { + action accept + description VPN-24589-ANY-ALLOW-10.4.56.9 + destination { + group { + address-group DT_VPN-24589 + } + } + source { + address 10.4.56.9 + } + } + rule 2760 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.29 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.29 + } + } + rule 2761 { + action accept + description FWC7D36_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC7D36_1 + } + port 27017,11080 + } + protocol tcp + } + rule 2762 { + action accept + description FWBB718_1-TCP_UDP-ALLOW-77.68.73.116 + destination { + group { + address-group DT_FWBB718_1 + } + port 1433 + } + protocol tcp_udp + source { + address 77.68.73.116 + } + } + rule 2763 { + action accept + description FWBB718_1-UDP-ALLOW-77.68.73.116 + destination { + group { + address-group DT_FWBB718_1 + } + port 1434 + } + protocol udp + source { + address 77.68.73.116 + } + } + rule 2764 { + action accept + description FWB9699_11-TCP-ALLOW-213.171.217.102 + destination { + group { + address-group DT_FWB9699_11 + } + port 22,80,443,8800 + } + protocol tcp + source { + address 213.171.217.102 + } + } + rule 2765 { + action accept + description FW18E6E_3-TCP-ALLOW-103.8.164.5 + destination { + group { + address-group DT_FW18E6E_3 + } + port 22 + } + protocol tcp + source { + address 103.8.164.5 + } + } + rule 2766 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.193 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.193 + } + } + rule 2768 { + action accept + description FW26F0A_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW26F0A_1 + } + port 53 + } + protocol tcp_udp + } + rule 2769 { + action accept + description FWCC18F_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWCC18F_2 + } + port 8883,1883 + } + protocol tcp + } + rule 2771 { + action accept + description FW633DD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW633DD_1 + } + port 28967,14002,9984,9983,9982,9981,8888,8884 + } + protocol tcp + } + rule 2772 { + action accept + description FWDEDB9_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDEDB9_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2773 { + action accept + description VPN-18646-ANY-ALLOW-10.4.88.109 + destination { + group { + address-group DT_VPN-18646 + } + } + source { + address 10.4.88.109 + } + } + rule 2774 { + action accept + description VPN-18646-ANY-ALLOW-10.4.89.109 + destination { + group { + address-group DT_VPN-18646 + } + } + source { + address 10.4.89.109 + } + } + rule 2775 { + action accept + description FWA0531_1-TCP-ALLOW-87.224.39.221 + destination { + group { + address-group DT_FWA0531_1 + } + port 8082,3003,22 + } + protocol tcp + source { + address 87.224.39.221 + } + } + rule 2776 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.94 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.94 + } + } + rule 2777 { + action accept + description FWA0531_1-TCP-ALLOW-92.237.97.92 + destination { + group { + address-group DT_FWA0531_1 + } + port 8082,3003,22 + } + protocol tcp + source { + address 92.237.97.92 + } + } + rule 2778 { + action accept + description VPN-25822-ANY-ALLOW-10.4.55.42 + destination { + group { + address-group DT_VPN-25822 + } + } + source { + address 10.4.55.42 + } + } + rule 2779 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.88 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.211.88 + } + } + rule 2780 { + action accept + description FWC2D30_1-TCP-ALLOW-143.55.64.0_20 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 143.55.64.0/20 + } + } + rule 2781 { + action accept + description FW18E6E_3-TCP-ALLOW-194.176.78.206 + destination { + group { + address-group DT_FW18E6E_3 + } + port 22 + } + protocol tcp + source { + address 194.176.78.206 + } + } + rule 2782 { + action accept + description FW18E6E_3-TCP-ALLOW-195.243.221.50 + destination { + group { + address-group DT_FW18E6E_3 + } + port 22 + } + protocol tcp + source { + address 195.243.221.50 + } + } + rule 2783 { + action accept + description FW18E6E_3-TCP-ALLOW-213.171.217.107 + destination { + group { + address-group DT_FW18E6E_3 + } + port 22 + } + protocol tcp + source { + address 213.171.217.107 + } + } + rule 2784 { + action accept + description FW18E6E_3-TCP-ALLOW-81.150.168.54 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306,22 + } + protocol tcp + source { + address 81.150.168.54 + } + } + rule 2785 { + action accept + description FW18E6E_3-TCP-ALLOW-89.197.133.235 + destination { + group { + address-group DT_FW18E6E_3 + } + port 22 + } + protocol tcp + source { + address 89.197.133.235 + } + } + rule 2786 { + action accept + description FW18E6E_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW18E6E_3 + } + port 60000-60100,873 + } + protocol tcp + } + rule 2787 { + action accept + description FW2BF20_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2BF20_3 + } + port 49152-65534,990 + } + protocol tcp + } + rule 2788 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.98 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.98 + } + } + rule 2789 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.65 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.65 + } + } + rule 2791 { + action accept + description FW197DB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW197DB_1 + } + port 49152-65534 + } + protocol tcp + } + rule 2792 { + action accept + description FW1208C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1208C_1 + } + port 2087,2083,2096 + } + protocol tcp + } + rule 2793 { + action accept + description FW00D98_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW00D98_1 + } + port 4430 + } + protocol tcp + } + rule 2794 { + action accept + description FW03B35_1-ESP-ALLOW-ANY + destination { + group { + address-group DT_FW03B35_1 + } + } + protocol esp + } + rule 2795 { + action accept + description FW03B35_1-AH-ALLOW-ANY + destination { + group { + address-group DT_FW03B35_1 + } + } + protocol ah + } + rule 2796 { + action accept + description FWEF92E_5-TCP-ALLOW-87.224.6.174 + destination { + group { + address-group DT_FWEF92E_5 + } + port 3389,445,443 + } + protocol tcp + source { + address 87.224.6.174 + } + } + rule 2797 { + action accept + description FW825C8_19-TCP-ALLOW-159.253.51.74 + destination { + group { + address-group DT_FW825C8_19 + } + port 3389,1433,995 + } + protocol tcp + source { + address 159.253.51.74 + } + } + rule 2798 { + action accept + description FW825C8_19-TCP-ALLOW-77.68.76.111 + destination { + group { + address-group DT_FW825C8_19 + } + port 1433 + } + protocol tcp + source { + address 77.68.76.111 + } + } + rule 2799 { + action accept + description FW825C8_19-TCP-ALLOW-77.68.28.63 + destination { + group { + address-group DT_FW825C8_19 + } + port 995 + } + protocol tcp + source { + address 77.68.28.63 + } + } + rule 2801 { + action accept + description FW2EF2C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2EF2C_1 + } + port 5349 + } + protocol tcp + } + rule 2802 { + action accept + description FWEF92E_5-TCP-ALLOW-88.208.198.93 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 88.208.198.93 + } + } + rule 2803 { + action accept + description FWC3921_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC3921_1 + } + port 25000,25001-25005,26000-26006 + } + protocol tcp + } + rule 2804 { + action accept + description FWEF92E_5-UDP-ALLOW-109.228.37.19 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 109.228.37.19 + } + } + rule 2805 { + action accept + description FWEF92E_5-UDP-ALLOW-77.68.11.54 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 77.68.11.54 + } + } + rule 2806 { + action accept + description FW5AE10_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW5AE10_1 + } + port 53 + } + protocol tcp_udp + } + rule 2810 { + action accept + description FW45F87_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW45F87_1 + } + port 60000-60100 + } + protocol tcp + } + rule 2811 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.108.158 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 123.231.108.158 + } + } + rule 2813 { + action accept + description FW825C8_19-TCP-ALLOW-109.228.1.233 + destination { + group { + address-group DT_FW825C8_19 + } + port 1433 + } + protocol tcp + source { + address 109.228.1.233 + } + } + rule 2814 { + action accept + description FW20449_2-ICMP-ALLOW-3.10.221.168 + destination { + group { + address-group DT_FW20449_2 + } + } + protocol icmp + source { + address 3.10.221.168 + } + } + rule 2815 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.100 + destination { + group { + address-group DT_FWB9699_7 + } + port 22 + } + protocol tcp + source { + address 213.171.217.100 + } + } + rule 2816 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.180 + destination { + group { + address-group DT_FWB9699_7 + } + port 22 + } + protocol tcp + source { + address 213.171.217.180 + } + } + rule 2817 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.184 + destination { + group { + address-group DT_FWB9699_7 + } + port 22 + } + protocol tcp + source { + address 213.171.217.184 + } + } + rule 2818 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.185 + destination { + group { + address-group DT_FWB9699_7 + } + port 22 + } + protocol tcp + source { + address 213.171.217.185 + } + } + rule 2819 { + action accept + description FWB9699_7-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWB9699_7 + } + port 161 + } + protocol udp + } + rule 2820 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.102 + destination { + group { + address-group DT_FWB9699_7 + } + port 22,8443 + } + protocol tcp + source { + address 213.171.217.102 + } + } + rule 2821 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.103 + destination { + group { + address-group DT_FWB9699_7 + } + port 22 + } + protocol tcp + source { + address 213.171.217.103 + } + } + rule 2824 { + action accept + description FWE3E77_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE3E77_1 + } + port 10010,10009 + } + protocol tcp + } + rule 2825 { + action accept + description FW8A3FC_3-TCP-ALLOW-93.190.142.120 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 93.190.142.120 + } + } + rule 2826 { + action accept + description FW20449_2-ICMP-ALLOW-82.20.69.137 + destination { + group { + address-group DT_FW20449_2 + } + } + protocol icmp + source { + address 82.20.69.137 + } + } + rule 2827 { + action accept + description FW8A3FC_3-TCP-ALLOW-46.101.232.93 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 21-10000 + } + protocol tcp + source { + address 46.101.232.93 + } + } + rule 2828 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.5 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.5 + } + } + rule 2829 { + action accept + description FWD2440_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD2440_1 + } + port 1-65535 + } + protocol tcp + } + rule 2831 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.105 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.105 + } + } + rule 2833 { + action accept + description FW825C8_24-TCP-ALLOW-159.253.51.74 + destination { + group { + address-group DT_FW825C8_24 + } + port 3389,1433,995 + } + protocol tcp + source { + address 159.253.51.74 + } + } + rule 2834 { + action accept + description FW825C8_24-TCP-ALLOW-77.68.77.120 + destination { + group { + address-group DT_FW825C8_24 + } + port 1433 + } + protocol tcp + source { + address 77.68.77.120 + } + } + rule 2839 { + action accept + description FWD2440_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWD2440_1 + } + port 1-65535 + } + protocol udp + } + rule 2840 { + action accept + description FW1C8F2_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1C8F2_1 + } + port 7000-10000,5554,5443,5080,1935,1111 + } + protocol tcp + } + rule 2843 { + action accept + description FWE7180_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWE7180_1 + } + port 443,53 + } + protocol tcp_udp + } + rule 2844 { + action accept + description FWC6301_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC6301_1 + } + port 2456 + } + protocol tcp_udp + } + rule 2845 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.113 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.113 + } + } + rule 2846 { + action accept + description VPN-24589-ANY-ALLOW-10.4.57.9 + destination { + group { + address-group DT_VPN-24589 + } + } + source { + address 10.4.57.9 + } + } + rule 2847 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.237 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.212.237 + } + } + rule 2849 { + action accept + description FWFD9AF_9-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWFD9AF_9 + } + port 445 + } + protocol tcp_udp + } + rule 2850 { + action accept + description VPN-23209-ANY-ALLOW-10.4.58.8 + destination { + group { + address-group DT_VPN-23209 + } + } + source { + address 10.4.58.8 + } + } + rule 2851 { + action accept + description VPN-23209-ANY-ALLOW-10.4.59.8 + destination { + group { + address-group DT_VPN-23209 + } + } + source { + address 10.4.59.8 + } + } + rule 2853 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.29 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.29 + } + } + rule 2854 { + action accept + description FW16375_5-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW16375_5 + } + port 2096 + } + protocol tcp_udp + } + rule 2856 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.173 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.173 + } + } + rule 2858 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.35 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.35 + } + } + rule 2859 { + action accept + description FW73573_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW73573_1 + } + port 25 + } + protocol tcp_udp + } + rule 2860 { + action accept + description FW18E6E_3-TCP-ALLOW-148.253.173.242 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306 + } + protocol tcp + source { + address 148.253.173.242 + } + } + rule 2861 { + action accept + description FW8ECF4_1-TCP-ALLOW-77.68.2.215 + destination { + group { + address-group DT_FW8ECF4_1 + } + port 3306 + } + protocol tcp + source { + address 77.68.2.215 + } + } + rule 2862 { + action accept + description FW8A3FC_3-TCP_UDP-ALLOW-82.165.100.25 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 21-10000 + } + protocol tcp_udp + source { + address 82.165.100.25 + } + } + rule 2863 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.235 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.235 + } + } + rule 2864 { + action accept + description VPN-18647-ANY-ALLOW-10.4.86.114 + destination { + group { + address-group DT_VPN-18647 + } + } + source { + address 10.4.86.114 + } + } + rule 2865 { + action accept + description VPN-18647-ANY-ALLOW-10.4.87.114 + destination { + group { + address-group DT_VPN-18647 + } + } + source { + address 10.4.87.114 + } + } + rule 2867 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.107 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.107 + } + } + rule 2868 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.239 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.239 + } + } + rule 2869 { + action accept + description FWF699D_4-TCP-ALLOW-164.39.151.3 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 164.39.151.3 + } + } + rule 2870 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.245 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.245 + } + } + rule 2873 { + action accept + description FWEF92E_6-TCP-ALLOW-87.224.6.174 + destination { + group { + address-group DT_FWEF92E_6 + } + port 3389,445 + } + protocol tcp + source { + address 87.224.6.174 + } + } + rule 2874 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.130 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.130 + } + } + rule 2875 { + action accept + description FW44BF9_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW44BF9_1 + } + port 49160-49200 + } + protocol tcp + } + rule 2876 { + action accept + description VPN-24591-ANY-ALLOW-10.4.86.4 + destination { + group { + address-group DT_VPN-24591 + } + } + source { + address 10.4.86.4 + } + } + rule 2877 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.60 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.60 + } + } + rule 2879 { + action accept + description FWEF92E_6-UDP-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_6 + } + port 500 + } + protocol udp + source { + address 77.68.77.57 + } + } + rule 2880 { + action accept + description FWF699D_4-TCP-ALLOW-185.132.38.110 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 185.132.38.110 + } + } + rule 2881 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.216 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.216 + } + } + rule 2882 { + action accept + description FWEF92E_5-UDP-ALLOW-77.68.77.149 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 77.68.77.149 + } + } + rule 2883 { + action accept + description FWA2FF8_4-TCP-ALLOW-80.229.18.102 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 3306,21,22 + } + protocol tcp + source { + address 80.229.18.102 + } + } + rule 2884 { + action accept + description FWA2FF8_4-TCP-ALLOW-109.169.33.69 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 3306,21,22 + } + protocol tcp + source { + address 109.169.33.69 + } + } + rule 2885 { + action accept + description FWA2FF8_4-TCP-ALLOW-46.102.209.35 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 3306,21 + } + protocol tcp + source { + address 46.102.209.35 + } + } + rule 2886 { + action accept + description FWA2FF8_4-TCP-ALLOW-90.213.48.16 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 3306,21 + } + protocol tcp + source { + address 90.213.48.16 + } + } + rule 2887 { + action accept + description FWA2FF8_4-TCP-ALLOW-77.68.76.129 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 22 + } + protocol tcp + source { + address 77.68.76.129 + } + } + rule 2888 { + action accept + description FWA2FF8_4-TCP-ALLOW-109.228.50.145 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 22 + } + protocol tcp + source { + address 109.228.50.145 + } + } + rule 2889 { + action accept + description FWA2FF8_4-TCP-ALLOW-77.68.76.231 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 22 + } + protocol tcp + source { + address 77.68.76.231 + } + } + rule 2890 { + action accept + description FW4513E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4513E_1 + } + port 50000-50020,990 + } + protocol tcp + } + rule 2893 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.40.7 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.40.7 + } + } + rule 2894 { + action accept + description VPN-21876-ANY-ALLOW-10.4.88.96 + destination { + group { + address-group DT_VPN-21876 + } + } + source { + address 10.4.88.96 + } + } + rule 2895 { + action accept + description VPN-21876-ANY-ALLOW-10.4.89.96 + destination { + group { + address-group DT_VPN-21876 + } + } + source { + address 10.4.89.96 + } + } + rule 2896 { + action accept + description VPN-26124-ANY-ALLOW-10.4.54.75 + destination { + group { + address-group DT_VPN-26124 + } + } + source { + address 10.4.54.75 + } + } + rule 2897 { + action accept + description VPN-26124-ANY-ALLOW-10.4.55.76 + destination { + group { + address-group DT_VPN-26124 + } + } + source { + address 10.4.55.76 + } + } + rule 2898 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.21 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.210.21 + } + } + rule 2899 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.213 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.213 + } + } + rule 2901 { + action accept + description FWC6301_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC6301_1 + } + port 5555 + } + protocol udp + } + rule 2902 { + action accept + description VPN-13261-ANY-ALLOW-10.4.56.173 + destination { + group { + address-group DT_VPN-13261 + } + } + source { + address 10.4.56.173 + } + } + rule 2903 { + action accept + description VPN-13261-ANY-ALLOW-10.4.57.173 + destination { + group { + address-group DT_VPN-13261 + } + } + source { + address 10.4.57.173 + } + } + rule 2909 { + action accept + description VPN-24591-ANY-ALLOW-10.4.87.4 + destination { + group { + address-group DT_VPN-24591 + } + } + source { + address 10.4.87.4 + } + } + rule 2911 { + action accept + description FWE7180_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE7180_1 + } + port 40110-40210,8090 + } + protocol tcp + } + rule 2914 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.247 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.247 + } + } + rule 2915 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.129 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.129 + } + } + rule 2916 { + action accept + description FWCB29D_1-TCP-ALLOW-51.146.16.162 + destination { + group { + address-group DT_FWCB29D_1 + } + port 8447,8443,22 + } + protocol tcp + source { + address 51.146.16.162 + } + } + rule 2917 { + action accept + description FW4E399_1-TCP-ALLOW-51.155.19.77 + destination { + group { + address-group DT_FW4E399_1 + } + port 3306 + } + protocol tcp + source { + address 51.155.19.77 + } + } + rule 2919 { + action accept + description FWC72E5_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC72E5_1 + } + port 9000-9100,6667 + } + protocol tcp + } + rule 2922 { + action accept + description FW21A75_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW21A75_2 + } + port 3000 + } + protocol tcp + } + rule 2923 { + action accept + description FW3B068_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW3B068_2 + } + port 990,60000-65000 + } + protocol tcp + } + rule 2924 { + action accept + description FW48814_3-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW48814_3 + } + port 3306 + } + protocol tcp_udp + } + rule 2925 { + action accept + description FW48814_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW48814_3 + } + port 49152-65534 + } + protocol tcp + } + rule 2926 { + action accept + description FW2B279_4-TCP-ALLOW-178.128.39.210 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443 + } + protocol tcp + source { + address 178.128.39.210 + } + } + rule 2927 { + action accept + description FW2B279_4-TCP-ALLOW-82.165.232.19 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443 + } + protocol tcp + source { + address 82.165.232.19 + } + } + rule 2928 { + action accept + description FW2B279_4-TCP-ALLOW-84.64.186.31 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443 + } + protocol tcp + source { + address 84.64.186.31 + } + } + rule 2929 { + action accept + description FW1C8F2_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW1C8F2_1 + } + port 5000-65000 + } + protocol udp + } + rule 2930 { + action accept + description FW2B279_4-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2B279_4 + } + port 49152-65535 + } + protocol tcp + } + rule 2931 { + action accept + description FW608FA_1-TCP-ALLOW-195.10.106.114 + destination { + group { + address-group DT_FW608FA_1 + } + port 22 + } + protocol tcp + source { + address 195.10.106.114 + } + } + rule 2932 { + action accept + description FW608FA_1-TCP-ALLOW-213.137.25.134 + destination { + group { + address-group DT_FW608FA_1 + } + port 22 + } + protocol tcp + source { + address 213.137.25.134 + } + } + rule 2933 { + action accept + description FW608FA_1-TCP-ALLOW-92.39.202.189 + destination { + group { + address-group DT_FW608FA_1 + } + port 22 + } + protocol tcp + source { + address 92.39.202.189 + } + } + rule 2935 { + action accept + description FWC37B9_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC37B9_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2936 { + action accept + description FW15C99_6-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW15C99_6 + } + port 32410-32414,1900 + } + protocol udp + } + rule 2937 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.244.146 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 116.206.244.146 + } + } + rule 2938 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.158 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.211.158 + } + } + rule 2939 { + action accept + description FW15C99_6-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW15C99_6 + } + port 32469,32400 + } + protocol tcp + } + rule 2940 { + action accept + description FW0192C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0192C_1 + } + port 2053 + } + protocol tcp + } + rule 2941 { + action accept + description FW27949_2-TCP-ALLOW-86.179.23.119 + destination { + group { + address-group DT_FW27949_2 + } + port 443,80 + } + protocol tcp + source { + address 86.179.23.119 + } + } + rule 2942 { + action accept + description FW27949_2-TCP-ALLOW-92.15.208.193 + destination { + group { + address-group DT_FW27949_2 + } + port 443,80 + } + protocol tcp + source { + address 92.15.208.193 + } + } + rule 2943 { + action accept + description VPN-34122-ANY-ALLOW-10.4.56.122 + destination { + group { + address-group DT_VPN-34122 + } + } + source { + address 10.4.56.122 + } + } + rule 2944 { + action accept + description VPN-34122-ANY-ALLOW-10.4.57.122 + destination { + group { + address-group DT_VPN-34122 + } + } + source { + address 10.4.57.122 + } + } + rule 2945 { + action accept + description FWF323F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF323F_1 + } + port 25565,9999,8080,5001,3306 + } + protocol tcp_udp + } + rule 2946 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.132 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.132 + } + } + rule 2948 { + action accept + description VPN-30261-ANY-ALLOW-10.4.86.110 + destination { + group { + address-group DT_VPN-30261 + } + } + source { + address 10.4.86.110 + } + } + rule 2949 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.246 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.246 + } + } + rule 2951 { + action accept + description FWC2D30_1-TCP-ALLOW-157.231.100.222 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 157.231.100.222 + } + } + rule 2952 { + action accept + description FWC2D30_1-TCP-ALLOW-164.39.131.31 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 164.39.131.31 + } + } + rule 2953 { + action accept + description FWC2D30_1-TCP-ALLOW-185.199.108.0_22 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 185.199.108.0/22 + } + } + rule 2954 { + action accept + description FWC2D30_1-TCP-ALLOW-192.30.252.0_22 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 192.30.252.0/22 + } + } + rule 2955 { + action accept + description FWC2D30_1-TCP-ALLOW-80.252.78.202 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 80.252.78.202 + } + } + rule 2956 { + action accept + description FWC2D30_1-TCP-ALLOW-86.15.158.234 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 86.15.158.234 + } + } + rule 2957 { + action accept + description VPN-30261-ANY-ALLOW-10.4.87.110 + destination { + group { + address-group DT_VPN-30261 + } + } + source { + address 10.4.87.110 + } + } + rule 2958 { + action accept + description VPN-30262-ANY-ALLOW-10.4.88.36 + destination { + group { + address-group DT_VPN-30262 + } + } + source { + address 10.4.88.36 + } + } + rule 2961 { + action accept + description VPN-15950-ANY-ALLOW-10.4.88.89 + destination { + group { + address-group DT_VPN-15950 + } + } + source { + address 10.4.88.89 + } + } + rule 2962 { + action accept + description FWBFDED_1-TCP-ALLOW-78.141.24.164 + destination { + group { + address-group DT_FWBFDED_1 + } + port 3389 + } + protocol tcp + source { + address 78.141.24.164 + } + } + rule 2963 { + action accept + description VPN-30262-ANY-ALLOW-10.4.89.36 + destination { + group { + address-group DT_VPN-30262 + } + } + source { + address 10.4.89.36 + } + } + rule 2964 { + action accept + description FW1F126_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1F126_1 + } + port 2087,2083 + } + protocol tcp + } + rule 2965 { + action accept + description FWA7A50_1-ANY-ALLOW-40.120.53.80 + destination { + group { + address-group DT_FWA7A50_1 + } + } + source { + address 40.120.53.80 + } + } + rule 2967 { + action accept + description VPN-23729-ANY-ALLOW-10.4.54.10 + destination { + group { + address-group DT_VPN-23729 + } + } + source { + address 10.4.54.10 + } + } + rule 2968 { + action accept + description VPN-23729-ANY-ALLOW-10.4.55.10 + destination { + group { + address-group DT_VPN-23729 + } + } + source { + address 10.4.55.10 + } + } + rule 2969 { + action accept + description VPN-23733-ANY-ALLOW-10.4.58.12 + destination { + group { + address-group DT_VPN-23733 + } + } + source { + address 10.4.58.12 + } + } + rule 2970 { + action accept + description VPN-23733-ANY-ALLOW-10.4.59.12 + destination { + group { + address-group DT_VPN-23733 + } + } + source { + address 10.4.59.12 + } + } + rule 2971 { + action accept + description VPN-23734-ANY-ALLOW-10.4.56.29 + destination { + group { + address-group DT_VPN-23734 + } + } + source { + address 10.4.56.29 + } + } + rule 2972 { + action accept + description VPN-23734-ANY-ALLOW-10.4.57.29 + destination { + group { + address-group DT_VPN-23734 + } + } + source { + address 10.4.57.29 + } + } + rule 2975 { + action accept + description VPN-23738-ANY-ALLOW-10.4.57.13 + destination { + group { + address-group DT_VPN-23738 + } + } + source { + address 10.4.57.13 + } + } + rule 2976 { + action accept + description FWD8DD1_2-TCP-ALLOW-77.153.164.226 + destination { + group { + address-group DT_FWD8DD1_2 + } + port 3306,22 + } + protocol tcp + source { + address 77.153.164.226 + } + } + rule 2977 { + action accept + description FWE012D_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWE012D_1 + } + port 143,25 + } + protocol tcp_udp + } + rule 2978 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.120.196 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.120.196 + } + } + rule 2981 { + action accept + description FW24AB7_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW24AB7_1 + } + port 40110-40210 + } + protocol tcp_udp + } + rule 2985 { + action accept + description FW2379F_14-TCP-ALLOW-194.72.140.178 + destination { + group { + address-group DT_FW2379F_14 + } + port 3389,21 + } + protocol tcp + source { + address 194.72.140.178 + } + } + rule 2986 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.97 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.97 + } + } + rule 2988 { + action accept + description FW883EB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW883EB_1 + } + port 5005,5004,5003,5002,5001 + } + protocol tcp + } + rule 2992 { + action accept + description FW310C6_3-ANY-ALLOW-62.30.207.232 + destination { + group { + address-group DT_FW310C6_3 + } + } + source { + address 62.30.207.232 + } + } + rule 2993 { + action accept + description VPN-15950-ANY-ALLOW-10.4.89.89 + destination { + group { + address-group DT_VPN-15950 + } + } + source { + address 10.4.89.89 + } + } + rule 2994 { + action accept + description VPN-15960-ANY-ALLOW-10.4.88.90 + destination { + group { + address-group DT_VPN-15960 + } + } + source { + address 10.4.88.90 + } + } + rule 2995 { + action accept + description FWEF92E_7-UDP-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_7 + } + port 500 + } + protocol udp + source { + address 77.68.77.57 + } + } + rule 2996 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.135 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.135 + } + } + rule 2998 { + action accept + description VPN-31002-ANY-ALLOW-10.4.88.126 + destination { + group { + address-group DT_VPN-31002 + } + } + source { + address 10.4.88.126 + } + } + rule 2999 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.246.110 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 116.206.246.110 + } + } + rule 3000 { + action accept + description FW08061_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW08061_1 + } + port 49152-65535 + } + protocol tcp + } + rule 3001 { + action accept + description VPN-15960-ANY-ALLOW-10.4.89.90 + destination { + group { + address-group DT_VPN-15960 + } + } + source { + address 10.4.89.90 + } + } + rule 3003 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.56 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.56 + } + } + rule 3004 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.47.47 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 175.157.47.47 + } + } + rule 3005 { + action accept + description FW10C3D_19-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW10C3D_19 + } + port 49152-65535,14147 + } + protocol tcp + } + rule 3006 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.136 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.210.136 + } + } + rule 3009 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.44.109 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.44.109 + } + } + rule 3010 { + action accept + description VPN-24592-ANY-ALLOW-10.4.88.9 + destination { + group { + address-group DT_VPN-24592 + } + } + source { + address 10.4.88.9 + } + } + rule 3011 { + action accept + description FW05AD0_2-TCP-ALLOW-213.171.209.161 + destination { + group { + address-group DT_FW05AD0_2 + } + port 3389,1433,21 + } + protocol tcp + source { + address 213.171.209.161 + } + } + rule 3012 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.86.254 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.86.254 + } + } + rule 3014 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.16 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.16 + } + } + rule 3018 { + action accept + description VPN-24592-ANY-ALLOW-10.4.89.9 + destination { + group { + address-group DT_VPN-24592 + } + } + source { + address 10.4.89.9 + } + } + rule 3019 { + action accept + description VPN-24593-ANY-ALLOW-10.4.54.6 + destination { + group { + address-group DT_VPN-24593 + } + } + source { + address 10.4.54.6 + } + } + rule 3020 { + action accept + description VPN-24593-ANY-ALLOW-10.4.55.6 + destination { + group { + address-group DT_VPN-24593 + } + } + source { + address 10.4.55.6 + } + } + rule 3021 { + action accept + description VPN-24594-ANY-ALLOW-10.4.58.6 + destination { + group { + address-group DT_VPN-24594 + } + } + source { + address 10.4.58.6 + } + } + rule 3022 { + action accept + description VPN-24594-ANY-ALLOW-10.4.59.6 + destination { + group { + address-group DT_VPN-24594 + } + } + source { + address 10.4.59.6 + } + } + rule 3023 { + action accept + description VPN-24595-ANY-ALLOW-10.4.56.14 + destination { + group { + address-group DT_VPN-24595 + } + } + source { + address 10.4.56.14 + } + } + rule 3024 { + action accept + description VPN-24595-ANY-ALLOW-10.4.57.14 + destination { + group { + address-group DT_VPN-24595 + } + } + source { + address 10.4.57.14 + } + } + rule 3025 { + action accept + description VPN-32528-ANY-ALLOW-10.4.58.67 + destination { + group { + address-group DT_VPN-32528 + } + } + source { + address 10.4.58.67 + } + } + rule 3026 { + action accept + description VPN-32528-ANY-ALLOW-10.4.59.67 + destination { + group { + address-group DT_VPN-32528 + } + } + source { + address 10.4.59.67 + } + } + rule 3027 { + action accept + description FW6187E_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6187E_1 + } + port 51195 + } + protocol udp + } + rule 3028 { + action accept + description FW406AB_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW406AB_1 + } + port 37013,25461,8881,8080,2095,2082,1992 + } + protocol tcp_udp + } + rule 3029 { + action accept + description FWA86A4_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA86A4_1 + } + port 30333,5666 + } + protocol tcp + } + rule 3032 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.52 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.52 + } + } + rule 3033 { + action accept + description FWC055A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC055A_1 + } + port 2195 + } + protocol tcp + } + rule 3035 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.81 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.81 + } + } + rule 3039 { + action accept + description FW42BC7_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW42BC7_1 + } + port 53 + } + protocol tcp_udp + } + rule 3040 { + action accept + description FW42BC7_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW42BC7_1 + } + port 49152-65535 + } + protocol tcp + } + rule 3041 { + action accept + description FW310C6_3-ANY-ALLOW-88.208.198.39 + destination { + group { + address-group DT_FW310C6_3 + } + } + source { + address 88.208.198.39 + } + } + rule 3042 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.235 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.235 + } + } + rule 3043 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.205 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.212.205 + } + } + rule 3044 { + action accept + description FWBE878_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWBE878_1 + } + port 8989,5003,3000 + } + protocol tcp_udp + } + rule 3045 { + action accept + description VPN-30679-ANY-ALLOW-10.4.58.195 + destination { + group { + address-group DT_VPN-30679 + } + } + source { + address 10.4.58.195 + } + } + rule 3046 { + action accept + description FW6B9B9_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6B9B9_1 + } + port 30006-65000,27017,7101,4200,2990-3009 + } + protocol tcp + } + rule 3047 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.212 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.212 + } + } + rule 3049 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.125.4 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 123.231.125.4 + } + } + rule 3050 { + action accept + description FW49C3D_4-TCP-ALLOW-83.100.136.74 + destination { + group { + address-group DT_FW49C3D_4 + } + port 3389,445 + } + protocol tcp + source { + address 83.100.136.74 + } + } + rule 3051 { + action accept + description FW49C3D_6-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FW49C3D_6 + } + port 3389,445 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 3053 { + action accept + description FW89619_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW89619_1 + } + port 9000-10999 + } + protocol udp + } + rule 3054 { + action accept + description FWBD9D0_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBD9D0_1 + } + port 9090 + } + protocol tcp + } + rule 3055 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.47.236 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 175.157.47.236 + } + } + rule 3056 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.46.226 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.46.226 + } + } + rule 3058 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.205 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.211.205 + } + } + rule 3060 { + action accept + description FWF7B68_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF7B68_1 + } + port 49152-65535 + } + protocol tcp + } + rule 3061 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.253 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.253 + } + } + rule 3063 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.0 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.210.0 + } + } + rule 3065 { + action accept + description FW85619_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW85619_1 + } + port 6433 + } + protocol tcp + } + rule 3066 { + action accept + description FW5A5D7_3-TCP-ALLOW-188.66.79.94 + destination { + group { + address-group DT_FW5A5D7_3 + } + port 8172,3389 + } + protocol tcp + source { + address 188.66.79.94 + } + } + rule 3067 { + action accept + description FWF30BD_1-TCP-ALLOW-81.133.80.114 + destination { + group { + address-group DT_FWF30BD_1 + } + port 22 + } + protocol tcp + source { + address 81.133.80.114 + } + } + rule 3068 { + action accept + description FWF30BD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF30BD_1 + } + port 5061,5015,5001 + } + protocol tcp + } + rule 3069 { + action accept + description FWBD9D0_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWBD9D0_1 + } + port 51820 + } + protocol udp + } + rule 3070 { + action accept + description FW7C4D9_14-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW7C4D9_14 + } + port 25565,2456-2458 + } + protocol tcp_udp + } + rule 3071 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.23 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.23 + } + } + rule 3072 { + action accept + description FWEEC75_1-TCP-ALLOW-81.96.100.32 + destination { + group { + address-group DT_FWEEC75_1 + } + port 8447 + } + protocol tcp + source { + address 81.96.100.32 + } + } + rule 3073 { + action accept + description FW8A3FC_3-TCP-ALLOW-95.168.164.208 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 95.168.164.208 + } + } + rule 3074 { + action accept + description VPN-19992-ANY-ALLOW-10.4.86.158 + destination { + group { + address-group DT_VPN-19992 + } + } + source { + address 10.4.86.158 + } + } + rule 3075 { + action accept + description FWF30BD_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF30BD_1 + } + port 5090,5060 + } + protocol tcp_udp + } + rule 3076 { + action accept + description VPN-30679-ANY-ALLOW-10.4.59.195 + destination { + group { + address-group DT_VPN-30679 + } + } + source { + address 10.4.59.195 + } + } + rule 3077 { + action accept + description FW930F3_3-ANY-ALLOW-77.68.112.254 + destination { + group { + address-group DT_FW930F3_3 + } + } + source { + address 77.68.112.254 + } + } + rule 3078 { + action accept + description FW672AB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW672AB_1 + } + port 5432 + } + protocol tcp + } + rule 3079 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.252 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.211.252 + } + } + rule 3080 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.86.192 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.86.192 + } + } + rule 3081 { + action accept + description VPN-33204-ANY-ALLOW-10.4.56.176 + destination { + group { + address-group DT_VPN-33204 + } + } + source { + address 10.4.56.176 + } + } + rule 3083 { + action accept + description FW1FA8E_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW1FA8E_1 + } + port 33434 + } + protocol udp + } + rule 3084 { + action accept + description FWD2440_1-ESP-ALLOW-ANY + destination { + group { + address-group DT_FWD2440_1 + } + } + protocol esp + } + rule 3085 { + action accept + description FWA0531_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA0531_1 + } + port 53 + } + protocol tcp_udp + } + rule 3090 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.70 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.70 + } + } + rule 3091 { + action accept + description FWF7BFA_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF7BFA_1 + } + port 8000,5901,5479,5478 + } + protocol tcp + } + rule 3092 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.212 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.212 + } + } + rule 3094 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.125 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.212.125 + } + } + rule 3096 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.89 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.89 + } + } + rule 3097 { + action accept + description FWD56A2_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD56A2_1 + } + port 8001,8000 + } + protocol tcp + } + rule 3098 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.109 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.109 + } + } + rule 3099 { + action accept + description FW36425_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW36425_1 + } + port 44445,7770-7800 + } + protocol tcp + } + rule 3100 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.238 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.238 + } + } + rule 3102 { + action accept + description FW6B39D_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6B39D_1 + } + port 49216,49215 + } + protocol tcp_udp + } + rule 3103 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.121 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.121 + } + } + rule 3105 { + action accept + description FW2379F_14-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2379F_14 + } + port 443 + } + protocol tcp_udp + } + rule 3107 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.38 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.38 + } + } + rule 3109 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.191 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.191 + } + } + rule 3111 { + action accept + description FW27947_1-TCP-ALLOW-213.229.100.148 + destination { + group { + address-group DT_FW27947_1 + } + port 3306 + } + protocol tcp + source { + address 213.229.100.148 + } + } + rule 3112 { + action accept + description FWD42CF_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD42CF_1 + } + port 5432,5001,5000 + } + protocol tcp + } + rule 3114 { + action accept + description FW3A12F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW3A12F_1 + } + port 53 + } + protocol tcp_udp + } + rule 3116 { + action accept + description FW5A5D7_3-TCP-ALLOW-194.62.184.87 + destination { + group { + address-group DT_FW5A5D7_3 + } + port 3389 + } + protocol tcp + source { + address 194.62.184.87 + } + } + rule 3117 { + action accept + description FW5A5D7_3-TCP-ALLOW-51.219.31.78 + destination { + group { + address-group DT_FW5A5D7_3 + } + port 8172,3389 + } + protocol tcp + source { + address 51.219.31.78 + } + } + rule 3118 { + action accept + description VPN-26157-ANY-ALLOW-10.4.86.57 + destination { + group { + address-group DT_VPN-26157 + } + } + source { + address 10.4.86.57 + } + } + rule 3119 { + action accept + description VPN-26157-ANY-ALLOW-10.4.87.57 + destination { + group { + address-group DT_VPN-26157 + } + } + source { + address 10.4.87.57 + } + } + rule 3120 { + action accept + description FWA7625_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA7625_1 + } + port 943 + } + protocol tcp + } + rule 3121 { + action accept + description FWC96A1_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC96A1_1 + } + port 1194 + } + protocol udp + } + rule 3122 { + action accept + description FWA7625_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA7625_1 + } + port 1194 + } + protocol udp + } + rule 3123 { + action accept + description FWA7625_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA7625_1 + } + port 32400,10108 + } + protocol tcp_udp + } + rule 3125 { + action accept + description FW8A3FC_3-TCP-ALLOW-185.173.161.154 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 185.173.161.154 + } + } + rule 3127 { + action accept + description FW05339_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW05339_1 + } + port 46961 + } + protocol udp + } + rule 3130 { + action accept + description FWA0AA0_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA0AA0_1 + } + port 1194 + } + protocol udp + } + rule 3132 { + action accept + description FWD8DD1_2-TCP_UDP-ALLOW-77.153.164.226 + destination { + group { + address-group DT_FWD8DD1_2 + } + port 443,80 + } + protocol tcp_udp + source { + address 77.153.164.226 + } + } + rule 3134 { + action accept + description FW19987_4-TCP-ALLOW-87.224.6.174 + destination { + group { + address-group DT_FW19987_4 + } + port 3389,445,443 + } + protocol tcp + source { + address 87.224.6.174 + } + } + rule 3135 { + action accept + description FW40AE4_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW40AE4_1 + } + port 53 + } + protocol tcp_udp + } + rule 3136 { + action accept + description VPN-33204-ANY-ALLOW-10.4.57.176 + destination { + group { + address-group DT_VPN-33204 + } + } + source { + address 10.4.57.176 + } + } + rule 3137 { + action accept + description FWF3A1B_1-TCP_UDP-ALLOW-86.132.125.4 + destination { + group { + address-group DT_FWF3A1B_1 + } + port 2222 + } + protocol tcp_udp + source { + address 86.132.125.4 + } + } + rule 3138 { + action accept + description FWF3A1B_1-TCP_UDP-ALLOW-91.205.173.51 + destination { + group { + address-group DT_FWF3A1B_1 + } + port 2222 + } + protocol tcp_udp + source { + address 91.205.173.51 + } + } + rule 3143 { + action accept + description FWA86ED_101-TCP-ALLOW-109.149.121.73 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 109.149.121.73 + } + } + rule 3144 { + action accept + description FWA0AA0_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA0AA0_1 + } + port 28083,28015-28016,1935 + } + protocol tcp_udp + } + rule 3146 { + action accept + description FWF3A1B_1-TCP_UDP-ALLOW-92.233.27.144 + destination { + group { + address-group DT_FWF3A1B_1 + } + port 2222 + } + protocol tcp_udp + source { + address 92.233.27.144 + } + } + rule 3148 { + action accept + description FWA86ED_101-TCP-ALLOW-151.228.194.190 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 151.228.194.190 + } + } + rule 3149 { + action accept + description FW9B6FB_1-ICMP-ALLOW-77.68.89.115_32 + destination { + group { + address-group DT_FW9B6FB_1 + } + } + protocol icmp + source { + address 77.68.89.115/32 + } + } + rule 3153 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.199 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.199 + } + } + rule 3155 { + action accept + description FW45F3D_1-ANY-ALLOW-195.224.110.168 + destination { + group { + address-group DT_FW45F3D_1 + } + } + source { + address 195.224.110.168 + } + } + rule 3156 { + action accept + description FWF8E67_1-TCP-ALLOW-82.14.188.35 + destination { + group { + address-group DT_FWF8E67_1 + } + port 22 + } + protocol tcp + source { + address 82.14.188.35 + } + } + rule 3157 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.58 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.58 + } + } + rule 3158 { + action accept + description VPN-19992-ANY-ALLOW-10.4.87.158 + destination { + group { + address-group DT_VPN-19992 + } + } + source { + address 10.4.87.158 + } + } + rule 3159 { + action accept + description FWA86ED_101-TCP-ALLOW-5.66.24.185 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 5.66.24.185 + } + } + rule 3160 { + action accept + description FWF8E67_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF8E67_1 + } + port 3001 + } + protocol tcp + } + rule 3161 { + action accept + description FWD2440_1-AH-ALLOW-ANY + destination { + group { + address-group DT_FWD2440_1 + } + } + protocol ah + } + rule 3166 { + action accept + description FW3EBC8_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW3EBC8_1 + } + port 9001-9900,9000 + } + protocol tcp + } + rule 3167 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.244 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.244 + } + } + rule 3168 { + action accept + description FWA0531_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA0531_1 + } + port 3000 + } + protocol tcp + } + rule 3170 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.137 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.137 + } + } + rule 3173 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.104 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.104 + } + } + rule 3176 { + action accept + description FW6906B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6906B_1 + } + port 4190 + } + protocol tcp + } + rule 3177 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.246.230 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 116.206.246.230 + } + } + rule 3178 { + action accept + description FW444AF_1-TCP-ALLOW-91.135.10.140 + destination { + group { + address-group DT_FW444AF_1 + } + port 27017 + } + protocol tcp + source { + address 91.135.10.140 + } + } + rule 3180 { + action accept + description FWA86ED_101-TCP-ALLOW-81.150.13.34 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 81.150.13.34 + } + } + rule 3181 { + action accept + description FWA86ED_101-TCP-ALLOW-82.10.14.73 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 82.10.14.73 + } + } + rule 3183 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.25 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.25 + } + } + rule 3184 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.224 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.224 + } + } + rule 3185 { + action accept + description FW9B6FB_1-TCP-ALLOW-77.68.89.115_32 + destination { + group { + address-group DT_FW9B6FB_1 + } + port 10050 + } + protocol tcp + source { + address 77.68.89.115/32 + } + } + rule 3186 { + action accept + description VPN-14673-ANY-ALLOW-10.4.89.44 + destination { + group { + address-group DT_VPN-14673 + } + } + source { + address 10.4.89.44 + } + } + rule 3187 { + action accept + description FWCA628_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWCA628_1 + } + port 2096,2095,2087,2086,2083,2082 + } + protocol tcp + } + rule 3189 { + action accept + description VPN-28484-ANY-ALLOW-10.4.58.159 + destination { + group { + address-group DT_VPN-28484 + } + } + source { + address 10.4.58.159 + } + } + rule 3190 { + action accept + description FW028C0_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW028C0_2 + } + port 44491-44498,44474 + } + protocol tcp + } + rule 3191 { + action accept + description VPN-28484-ANY-ALLOW-10.4.59.159 + destination { + group { + address-group DT_VPN-28484 + } + } + source { + address 10.4.59.159 + } + } + rule 3192 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.119 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.119 + } + } + rule 3194 { + action accept + description FWF699D_4-TCP-ALLOW-195.74.108.130 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 195.74.108.130 + } + } + rule 3195 { + action accept + description FWF699D_4-TCP-ALLOW-31.54.149.143 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 31.54.149.143 + } + } + rule 3196 { + action accept + description FWF699D_4-TCP-ALLOW-35.204.243.120 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 35.204.243.120 + } + } + rule 3197 { + action accept + description FWF699D_4-TCP-ALLOW-81.150.55.65 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 81.150.55.65 + } + } + rule 3198 { + action accept + description FWF699D_4-TCP-ALLOW-81.150.55.70 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 81.150.55.70 + } + } + rule 3199 { + action accept + description FWF699D_4-TCP-ALLOW-86.142.112.4 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 86.142.112.4 + } + } + rule 3200 { + action accept + description FWF699D_4-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF699D_4 + } + port 8983 + } + protocol tcp_udp + } + rule 3201 { + action accept + description FWF699D_4-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF699D_4 + } + port 11009,10009 + } + protocol tcp + } + rule 3202 { + action accept + description VPN-2661-ANY-ALLOW-10.4.54.24 + destination { + group { + address-group DT_VPN-2661 + } + } + source { + address 10.4.54.24 + } + } + rule 3203 { + action accept + description VPN-2661-ANY-ALLOW-10.4.55.24 + destination { + group { + address-group DT_VPN-2661 + } + } + source { + address 10.4.55.24 + } + } + rule 3204 { + action accept + description VPN-9727-ANY-ALLOW-10.4.54.118 + destination { + group { + address-group DT_VPN-9727 + } + } + source { + address 10.4.54.118 + } + } + rule 3205 { + action accept + description VPN-9727-ANY-ALLOW-10.4.55.119 + destination { + group { + address-group DT_VPN-9727 + } + } + source { + address 10.4.55.119 + } + } + rule 3207 { + action accept + description FWF0221_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF0221_1 + } + port 65000,8099,8080 + } + protocol tcp_udp + } + rule 3208 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.180 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.180 + } + } + rule 3209 { + action accept + description FWA86ED_101-TCP-ALLOW-82.5.189.5 + destination { + group { + address-group DT_FWA86ED_101 + } + port 443 + } + protocol tcp + source { + address 82.5.189.5 + } + } + rule 3210 { + action accept + description FW60FD6_5-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW60FD6_5 + } + port 1194 + } + protocol udp + } + rule 3211 { + action accept + description FW60FD6_5-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW60FD6_5 + } + port 9500,9191,9090,8090,2222 + } + protocol tcp + } + rule 3212 { + action accept + description FWA86ED_101-TCP-ALLOW-84.65.217.114 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 84.65.217.114 + } + } + rule 3213 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.43.21 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.43.21 + } + } + rule 3214 { + action accept + description FW45F3D_1-ANY-ALLOW-77.68.126.251 + destination { + group { + address-group DT_FW45F3D_1 + } + } + source { + address 77.68.126.251 + } + } + rule 3215 { + action accept + description FWA86ED_101-TCP-ALLOW-86.14.23.23 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 86.14.23.23 + } + } + rule 3217 { + action accept + description FW85E02_11-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW85E02_11 + } + port 9000-10999 + } + protocol udp + } + rule 3218 { + action accept + description FW5D0FA_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW5D0FA_1 + } + port 53 + } + protocol tcp_udp + } + rule 3222 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.141 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.141 + } + } + rule 3223 { + action accept + description FWCDD8B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWCDD8B_1 + } + port 2222 + } + protocol tcp + } + rule 3224 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.185 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.185 + } + } + rule 3225 { + action accept + description FW06940_3-TCP_UDP-ALLOW-213.171.210.153 + destination { + group { + address-group DT_FW06940_3 + } + port 1-65535 + } + protocol tcp_udp + source { + address 213.171.210.153 + } + } + rule 3226 { + action accept + description FW06940_3-TCP_UDP-ALLOW-70.29.113.102 + destination { + group { + address-group DT_FW06940_3 + } + port 1-65535 + } + protocol tcp_udp + source { + address 70.29.113.102 + } + } + rule 3227 { + action accept + description FWC32BE_1-ANY-ALLOW-3.127.0.177 + destination { + group { + address-group DT_FWC32BE_1 + } + } + source { + address 3.127.0.177 + } + } + rule 3228 { + action accept + description FWA86ED_101-TCP-ALLOW-93.115.195.58 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 93.115.195.58 + } + } + rule 3229 { + action accept + description FWE32F2_8-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE32F2_8 + } + port 40120,30120,30110 + } + protocol tcp + } + rule 3230 { + action accept + description VPN-28515-ANY-ALLOW-10.4.56.162 + destination { + group { + address-group DT_VPN-28515 + } + } + source { + address 10.4.56.162 + } + } + rule 3231 { + action accept + description FW06940_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW06940_3 + } + port 30000-30400,8443-8447,445,80-110,21-25 + } + protocol tcp + } + rule 3232 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.134 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.211.134 + } + } + rule 3236 { + action accept + description VPN-28515-ANY-ALLOW-10.4.57.162 + destination { + group { + address-group DT_VPN-28515 + } + } + source { + address 10.4.57.162 + } + } + rule 3237 { + action accept + description FWF4063_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF4063_1 + } + port 3000 + } + protocol tcp + } + rule 3240 { + action accept + description FW06940_3-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW06940_3 + } + port 49152-65535,6379,5666,5432-5454 + } + protocol tcp_udp + } + rule 3242 { + action accept + description FW2E8D4_1-TCP-ALLOW-63.35.92.185 + destination { + group { + address-group DT_FW2E8D4_1 + } + port 3389 + } + protocol tcp + source { + address 63.35.92.185 + } + } + rule 3244 { + action accept + description FWF30BD_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF30BD_1 + } + port 9000-10999 + } + protocol udp + } + rule 3245 { + action accept + description FWE30A1_4-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWE30A1_4 + } + port 65057 + } + protocol tcp_udp + } + rule 3246 { + action accept + description VPN-26772-ANY-ALLOW-10.4.54.123 + destination { + group { + address-group DT_VPN-26772 + } + } + source { + address 10.4.54.123 + } + } + rule 3249 { + action accept + description FW56496_1-ANY-ALLOW-77.68.82.49 + destination { + group { + address-group DT_FW56496_1 + } + } + source { + address 77.68.82.49 + } + } + rule 3251 { + action accept + description FWDA443_6-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDA443_6 + } + port 30175,12050 + } + protocol tcp + } + rule 3253 { + action accept + description FW5A521_3-TCP-ALLOW-88.98.75.17 + destination { + group { + address-group DT_FW5A521_3 + } + port 22 + } + protocol tcp + source { + address 88.98.75.17 + } + } + rule 3254 { + action accept + description FW5A521_3-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW5A521_3 + } + port 161-162 + } + protocol udp + } + rule 3255 { + action accept + description FW5A521_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW5A521_3 + } + port 5900 + } + protocol tcp + } + rule 3259 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.178 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.214.178 + } + } + rule 3260 { + action accept + description VPN-26772-ANY-ALLOW-10.4.55.124 + destination { + group { + address-group DT_VPN-26772 + } + } + source { + address 10.4.55.124 + } + } + rule 3262 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.114 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.114 + } + } + rule 3272 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.246.30 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 116.206.246.30 + } + } + rule 3273 { + action accept + description FW2B4BA_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2B4BA_1 + } + port 30000-31000 + } + protocol tcp + } + rule 3284 { + action accept + description FW06940_3-TCP-ALLOW-213.171.217.107 + destination { + group { + address-group DT_FW06940_3 + } + port 8443 + } + protocol tcp + source { + address 213.171.217.107 + } + } + rule 3285 { + action accept + description FW0952B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0952B_1 + } + port 9030,9001 + } + protocol tcp + } + rule 3286 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.85.35 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.85.35 + } + } + rule 3290 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.232 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.232 + } + } + rule 3294 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.21 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.21 + } + } + rule 3295 { + action accept + description FW0EA3F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0EA3F_1 + } + port 1-65535 + } + protocol tcp_udp + } + rule 3296 { + action accept + description FW9D5C7_1-TCP-ALLOW-209.97.176.108 + destination { + group { + address-group DT_FW9D5C7_1 + } + port 8447,8443,22 + } + protocol tcp + source { + address 209.97.176.108 + } + } + rule 3297 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.188 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.188 + } + } + rule 3298 { + action accept + description FW9D5C7_1-TCP-ALLOW-165.227.231.227 + destination { + group { + address-group DT_FW9D5C7_1 + } + port 9117,9113,9104,9100 + } + protocol tcp + source { + address 165.227.231.227 + } + } + rule 3299 { + action accept + description FW4DB0A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4DB0A_1 + } + port 953 + } + protocol tcp + } + rule 3300 { + action accept + description FW4DB0A_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW4DB0A_1 + } + port 953 + } + protocol udp + } + rule 3301 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.91 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.91 + } + } + rule 3303 { + action accept + description FW56496_1-TCP-ALLOW-176.255.93.149 + destination { + group { + address-group DT_FW56496_1 + } + port 3389 + } + protocol tcp + source { + address 176.255.93.149 + } + } + rule 3304 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.79 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.79 + } + } + rule 3305 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.43 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.43 + } + } + rule 3306 { + action accept + description FW310C6_3-ANY-ALLOW-88.208.198.40 + destination { + group { + address-group DT_FW310C6_3 + } + } + source { + address 88.208.198.40 + } + } + rule 3307 { + action accept + description FW597A6_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW597A6_1 + } + port 49152-65535,990 + } + protocol tcp + } + rule 3308 { + action accept + description FW597A6_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW597A6_1 + } + port 3306 + } + protocol tcp_udp + } + rule 3309 { + action accept + description FWBC280_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBC280_1 + } + port 49152-65535,20-21 + } + protocol tcp + } + rule 3310 { + action accept + description VPN-31301-ANY-ALLOW-10.4.87.223 + destination { + group { + address-group DT_VPN-31301 + } + } + source { + address 10.4.87.223 + } + } + rule 3311 { + action accept + description FW18E6E_3-TCP-ALLOW-148.253.173.243 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306 + } + protocol tcp + source { + address 148.253.173.243 + } + } + rule 3312 { + action accept + description FW9EEDD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW9EEDD_1 + } + port 990,197,20-23 + } + protocol tcp + } + rule 3313 { + action accept + description FW9EEDD_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW9EEDD_1 + } + port 49152-65535 + } + protocol tcp_udp + } + rule 3314 { + action accept + description VPN-31002-ANY-ALLOW-10.4.89.126 + destination { + group { + address-group DT_VPN-31002 + } + } + source { + address 10.4.89.126 + } + } + rule 3316 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.11 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.11 + } + } + rule 3317 { + action accept + description FW32EFF_49-TCP-ALLOW-195.59.191.128_25 + destination { + group { + address-group DT_FW32EFF_49 + } + port 5589 + } + protocol tcp + source { + address 195.59.191.128/25 + } + } + rule 3318 { + action accept + description FW32EFF_49-TCP-ALLOW-213.71.130.0_26 + destination { + group { + address-group DT_FW32EFF_49 + } + port 5589 + } + protocol tcp + source { + address 213.71.130.0/26 + } + } + rule 3319 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.88 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.88 + } + } + rule 3320 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.173 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.173 + } + } + rule 3321 { + action accept + description FW32EFF_49-TCP-ALLOW-84.19.45.82 + destination { + group { + address-group DT_FW32EFF_49 + } + port 5589 + } + protocol tcp + source { + address 84.19.45.82 + } + } + rule 3322 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.43.122 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.43.122 + } + } + rule 3323 { + action accept + description FWC1ACD_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC1ACD_1 + } + port 28061,28060,8080 + } + protocol tcp_udp + } + rule 3324 { + action accept + description FWA5D67_1-TCP_UDP-ALLOW-84.74.32.74 + destination { + group { + address-group DT_FWA5D67_1 + } + port 3389 + } + protocol tcp_udp + source { + address 84.74.32.74 + } + } + rule 3325 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.169 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.169 + } + } + rule 3326 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.89 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.89 + } + } + rule 3329 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.35 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.35 + } + } + rule 3330 { + action accept + description FWCE020_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWCE020_1 + } + port 48402 + } + protocol udp + } + rule 3333 { + action accept + description FWF3574_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF3574_1 + } + port 8060,445,139 + } + protocol tcp + } + rule 3334 { + action accept + description FWE6AB2_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE6AB2_1 + } + port 44158,945,943 + } + protocol tcp + } + rule 3335 { + action accept + description FWBFC02_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBFC02_1 + } + port 44158,945,943 + } + protocol tcp + } + rule 3336 { + action accept + description FWBFC02_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWBFC02_1 + } + port 1194 + } + protocol udp + } + rule 3337 { + action accept + description FWE6AB2_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWE6AB2_1 + } + port 1194 + } + protocol udp + } + rule 3338 { + action accept + description FWBC8A6_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBC8A6_1 + } + port 44158,945,943 + } + protocol tcp + } + rule 3339 { + action accept + description FWBC8A6_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWBC8A6_1 + } + port 1194 + } + protocol udp + } + rule 3340 { + action accept + description FWA0AA0_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA0AA0_1 + } + port 2302 + } + protocol tcp + } + rule 3342 { + action accept + description FW56496_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW56496_1 + } + port 22 + } + protocol tcp_udp + } + rule 3343 { + action accept + description FW56496_1-TCP-ALLOW-157.231.178.162 + destination { + group { + address-group DT_FW56496_1 + } + port 21 + } + protocol tcp + source { + address 157.231.178.162 + } + } + rule 3344 { + action accept + description FW56496_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW56496_1 + } + port 2443,1022 + } + protocol tcp + } + rule 3345 { + action accept + description FW56496_1-TCP_UDP-ALLOW-46.16.211.142 + destination { + group { + address-group DT_FW56496_1 + } + port 3389,21 + } + protocol tcp_udp + source { + address 46.16.211.142 + } + } + rule 3347 { + action accept + description FW2379F_14-GRE-ALLOW-ANY + destination { + group { + address-group DT_FW2379F_14 + } + } + protocol gre + } + rule 3348 { + action accept + description FW0E383_9-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0E383_9 + } + port 52000 + } + protocol tcp + } + rule 3350 { + action accept + description FWB4438_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWB4438_2 + } + port 993-995,7 + } + protocol tcp + } + rule 3351 { + action accept + description FW1F3D0_6-TCP_UDP-ALLOW-82.165.207.109 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4567-4568 + } + protocol tcp_udp + source { + address 82.165.207.109 + } + } + rule 3352 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.77 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.77 + } + } + rule 3358 { + action accept + description FW46F4A_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW46F4A_1 + } + port 51820 + } + protocol udp + } + rule 3359 { + action accept + description FW53C72_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW53C72_1 + } + port 48402 + } + protocol udp + } + rule 3360 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.251 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.251 + } + } + rule 3362 { + action accept + description FWAA38E_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWAA38E_1 + } + port 1001-65535 + } + protocol tcp_udp + } + rule 3363 { + action accept + description FW138F8_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW138F8_1 + } + port 21,20 + } + protocol tcp_udp + } + rule 3364 { + action accept + description FW0BD92_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0BD92_3 + } + port 18081,18080 + } + protocol tcp + } + rule 3365 { + action accept + description FWFEF05_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWFEF05_1 + } + port 1935 + } + protocol tcp_udp + } + rule 3367 { + action accept + description FW26846_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW26846_1 + } + port 8000 + } + protocol tcp + } + rule 3368 { + action accept + description FWB4438_2-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWB4438_2 + } + port 53 + } + protocol tcp_udp + } + rule 3369 { + action accept + description FWA884B_5-TCP-ALLOW-51.146.16.162 + destination { + group { + address-group DT_FWA884B_5 + } + port 8447,8443,22 + } + protocol tcp + source { + address 51.146.16.162 + } + } + rule 3370 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.22 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.22 + } + } + rule 3371 { + action accept + description FWFDE34_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWFDE34_1 + } + port 18081,18080 + } + protocol tcp + } + rule 3373 { + action accept + description FWB6101_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWB6101_1 + } + port 2280 + } + protocol tcp + } + rule 3377 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.84.203 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.84.203 + } + } + rule 3378 { + action accept + description FW1D511_2-TCP-ALLOW-92.29.46.47 + destination { + group { + address-group DT_FW1D511_2 + } + port 9090 + } + protocol tcp + source { + address 92.29.46.47 + } + } + rule 3386 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.175 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.208.175 + } + } + rule 3387 { + action accept + description FW1ACD9_2-TCP-ALLOW-89.197.148.38 + destination { + group { + address-group DT_FW1ACD9_2 + } + port 5015,22 + } + protocol tcp + source { + address 89.197.148.38 + } + } + rule 3388 { + action accept + description FW1ACD9_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW1ACD9_2 + } + port 9000-10999,5090,5060 + } + protocol udp + } + rule 3389 { + action accept + description FW1ACD9_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1ACD9_2 + } + port 5090,5060-5062 + } + protocol tcp + } + rule 3391 { + action accept + description FWA0B7F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA0B7F_1 + } + port 53 + } + protocol tcp_udp + } + rule 3392 { + action accept + description FW56335_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW56335_2 + } + port 18081,18080 + } + protocol tcp + } + rule 3395 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.90 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.212.90 + } + } + rule 3396 { + action accept + description FW4D3E6_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4D3E6_1 + } + port 18081,18080 + } + protocol tcp + } + rule 3397 { + action accept + description FWB118A_1-TCP-ALLOW-188.65.177.58 + destination { + group { + address-group DT_FWB118A_1 + } + port 49152-65534,8447,8443,22,21,20 + } + protocol tcp + source { + address 188.65.177.58 + } + } + rule 3398 { + action accept + description FWB118A_1-TCP-ALLOW-77.68.103.13 + destination { + group { + address-group DT_FWB118A_1 + } + port 49152-65534,8447,8443,22,21,20 + } + protocol tcp + source { + address 77.68.103.13 + } + } + rule 3399 { + action accept + description FWB118A_1-TCP-ALLOW-80.5.71.130 + destination { + group { + address-group DT_FWB118A_1 + } + port 49152-65534,8447,8443,22,21,20 + } + protocol tcp + source { + address 80.5.71.130 + } + } + rule 3402 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.205 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.205 + } + } + rule 3408 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.31 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.31 + } + } + rule 3409 { + action accept + description FW539FB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW539FB_1 + } + port 389 + } + protocol tcp + } + rule 3411 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.185 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.185 + } + } + rule 3415 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.245.124 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 116.206.245.124 + } + } + rule 3416 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.75 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.75 + } + } + rule 3417 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.34 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.214.34 + } + } + rule 3418 { + action accept + description FWEF92E_5-UDP-ALLOW-77.68.77.70 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 77.68.77.70 + } + } + rule 3419 { + action accept + description FWEF92E_5-UDP-ALLOW-77.68.92.33 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 77.68.92.33 + } + } + rule 3420 { + action accept + description FWEF92E_5-UDP-ALLOW-77.68.93.82 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 77.68.93.82 + } + } + rule 3421 { + action accept + description FWEF92E_5-UDP-ALLOW-88.208.198.93 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 88.208.198.93 + } + } + rule 3422 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.94 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.94 + } + } + rule 3424 { + action accept + description FW18E6E_3-TCP-ALLOW-148.253.173.244 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306 + } + protocol tcp + source { + address 148.253.173.244 + } + } + rule 3425 { + action accept + description FW18E6E_3-TCP-ALLOW-148.253.173.246 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306 + } + protocol tcp + source { + address 148.253.173.246 + } + } + rule 3426 { + action accept + description FW18E6E_3-TCP-ALLOW-195.97.222.122 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306 + } + protocol tcp + source { + address 195.97.222.122 + } + } + rule 3431 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.111 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.111 + } + } + rule 3432 { + action accept + description FW06940_3-TCP_UDP-ALLOW-74.208.41.119 + destination { + group { + address-group DT_FW06940_3 + } + port 1-65535 + } + protocol tcp_udp + source { + address 74.208.41.119 + } + } + rule 3438 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.252 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.252 + } + } + rule 3440 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.118 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.118 + } + } + rule 3442 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.15 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.15 + } + } + rule 3446 { + action accept + description FWC32BE_1-ANY-ALLOW-3.65.3.75 + destination { + group { + address-group DT_FWC32BE_1 + } + } + source { + address 3.65.3.75 + } + } + rule 3447 { + action accept + description FWC32BE_1-TCP-ALLOW-217.155.2.52 + destination { + group { + address-group DT_FWC32BE_1 + } + port 22 + } + protocol tcp + source { + address 217.155.2.52 + } + } + rule 3448 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.243 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.243 + } + } + rule 3449 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.117 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.214.117 + } + } + rule 3450 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.4 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.210.4 + } + } + rule 3452 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.177 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.210.177 + } + } + rule 3454 { + action accept + description FWD498E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD498E_1 + } + port 44158 + } + protocol tcp + } + rule 3455 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.147 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.147 + } + } + rule 8500 { + action drop + description "Deny traffic to any private address" + destination { + group { + network-group RFC1918 + } + } + source { + group { + address-group CLUSTER_ADDRESSES + } + } + } + rule 8510 { + action accept + description "Default allow rule" + destination { + group { + address-group !CLUSTER_ADDRESSES + } + } + source { + group { + address-group CLUSTER_ADDRESSES + } + } + } + } + name LOCAL-LAN { + default-action drop + rule 2 { + action accept + destination { + address 10.255.255.1 + } + protocol icmp + source { + group { + address-group CLUSTER_ADDRESSES + } + } + } + rule 4 { + action accept + destination { + group { + address-group LAN_ADDRESSES + } + } + source { + group { + address-group LAN_ADDRESSES + } + } + } + rule 10 { + action accept + description "Multicast para VRRP" + destination { + address 224.0.0.18 + } + source { + group { + address-group LAN_ADDRESSES + } + } + } + } + name LOCAL-SYNC { + default-action drop + rule 5 { + action accept + description "Permitir trafico sync entre nodos" + destination { + address 10.4.51.132/30 + } + source { + address 10.4.51.132/30 + } + } + } + name LOCAL-WAN { + default-action drop + description "External connections from VLAN2701 to this system" + rule 10 { + action accept + description "Allow intra-vlan connections" + destination { + address 109.228.63.128/25 + } + source { + address 109.228.63.128/25 + } + } + rule 20 { + action accept + description "Allow Arsys desktops to contact this system" + source { + group { + address-group MANAGEMENT_ADDRESSES + } + } + } + } + name WAN-INBOUND { + default-action drop + rule 10 { + action accept + description "Management from HN-ES" + source { + group { + address-group MANAGEMENT_ADDRESSES + } + } + } + rule 20 { + action accept + description "Connections from Load Balancer to Frontends - TCP Proxy" + destination { + group { + address-group CLUSTER_ADDRESSES + } + } + source { + group { + address-group NLB_ADDRESSES + } + } + } + rule 30 { + action accept + description "Allow external probes" + destination { + group { + address-group NAGIOS_PROBES + } + } + protocol icmp + } + rule 40 { + action accept + description "Allow Centreon servers traffic to VMs" + destination { + group { + address-group CLUSTER_ADDRESSES + } + } + source { + group { + address-group CENTREON_SERVERS + } + } + } + rule 50 { + action accept + description "Allow CMK to check dnscache servers - TCP" + destination { + group { + address-group DNSCACHE_SERVERS + } + port 22,53,6556 + } + protocol tcp + source { + group { + address-group CMK_SATELLITES + } + } + } + rule 65 { + action accept + description "Allow CMK to check dnscache servers - UDP" + destination { + group { + address-group DNSCACHE_SERVERS + } + port 53 + } + protocol udp + source { + group { + address-group CMK_SATELLITES + } + } + } + rule 70 { + action accept + description "Allow CMK to check dnscache servers - ICMP" + destination { + group { + address-group DNSCACHE_SERVERS + } + } + protocol icmp + source { + group { + address-group CMK_SATELLITES + } + } + } + rule 80 { + action accept + description "Allow CMK to check monitoring sensors - TCP" + destination { + group { + address-group NAGIOS_PROBES + } + port 6556 + } + protocol tcp + source { + group { + address-group CMK_SATELLITES + } + } + } + rule 90 { + action accept + description "Allow CMK to check monitoring sensors - ICMP" + destination { + group { + address-group NAGIOS_PROBES + } + } + protocol icmp + source { + group { + address-group CMK_SATELLITES + } + } + } + rule 2000 { + action accept + description "TOP port - SSH" + destination { + group { + address-group G-22-TCP + } + port ssh + } + protocol tcp + } + rule 2001 { + action accept + description "TOP port - RDESKTOP" + destination { + group { + address-group G-3389-TCP + } + port 3389 + } + protocol tcp + } + rule 2002 { + action accept + description "TOP port - HTTP" + destination { + group { + address-group G-80-TCP + } + port http + } + protocol tcp + } + rule 2003 { + action accept + description "TOP port - HTTPS" + destination { + group { + address-group G-443-TCP + } + port https + } + protocol tcp + } + rule 2004 { + action accept + description "TOP port - DOMAIN TCP" + destination { + group { + address-group G-53-TCP + } + port domain + } + protocol tcp + } + rule 2005 { + action accept + description "TOP port - DOMAIN UDP" + destination { + group { + address-group G-53-UDP + } + port domain + } + protocol udp + } + rule 2006 { + action accept + description "TOP port - SMTP" + destination { + group { + address-group G-25-TCP + } + port smtp + } + protocol tcp + } + rule 2007 { + action accept + description "TOP port - IMAP" + destination { + group { + address-group G-143-TCP + } + port imap2 + } + protocol tcp + } + rule 2008 { + action accept + description "TOP port - POP3" + destination { + group { + address-group G-110-TCP + } + port pop3 + } + protocol tcp + } + rule 2009 { + action accept + description "TOP port - MSSQL TCP" + destination { + group { + address-group G-1433-TCP + } + port ms-sql-s + } + protocol tcp + } + rule 2010 { + action accept + description "TOP port - MYSQL TCP" + destination { + group { + address-group G-3306-TCP + } + port mysql + } + protocol tcp + } + rule 2011 { + action accept + description "TOP port - FTPDATA" + destination { + group { + address-group G-20-TCP + } + port ftp-data + } + protocol tcp + } + rule 2012 { + action accept + description "TOP port - FTP" + destination { + group { + address-group G-21-TCP + } + port ftp + } + protocol tcp + } + rule 2013 { + action accept + description "TOP port - SSMTP" + destination { + group { + address-group G-465-TCP + } + port ssmtp + } + protocol tcp + } + rule 2014 { + action accept + description "TOP port - SMTPS" + destination { + group { + address-group G-587-TCP + } + port 587 + } + protocol tcp + } + rule 2015 { + action accept + description "TOP port - IMAPS" + destination { + group { + address-group G-993-TCP + } + port imaps + } + protocol tcp + } + rule 2016 { + action accept + description "TOP port - POP3S" + destination { + group { + address-group G-995-TCP + } + port pop3s + } + protocol tcp + } + rule 2017 { + action accept + description "TOP port - TOMCAT" + destination { + group { + address-group G-8080-TCP + } + port 8080 + } + protocol tcp + } + rule 2018 { + action accept + description "TOP port - Alternative HTTPS" + destination { + group { + address-group G-8443-TCP + } + port 8443 + } + protocol tcp + } + rule 2019 { + action accept + description "TOP port - 10000/TCP" + destination { + group { + address-group G-10000-TCP + } + port 10000 + } + protocol tcp + } + rule 2020 { + action accept + description "TOP port - 8447/TCP" + destination { + group { + address-group G-8447-TCP + } + port 8447 + } + protocol tcp + } + rule 2040 { + action accept + description "TOP port - All ports open" + destination { + group { + address-group G-ALL_OPEN + } + } + } + rule 2050 { + action accept + description "ICMP group" + destination { + group { + address-group G-ICMP + } + } + protocol icmp + } + rule 2100 { + action accept + description FW2BB8D_1-TCP-ALLOW-104.192.143.2 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 7999,22 + } + protocol tcp + source { + address 104.192.143.2 + } + } + rule 2101 { + action accept + description FW19987_4-TCP-ALLOW-77.68.74.54 + destination { + group { + address-group DT_FW19987_4 + } + port 443 + } + protocol tcp + source { + address 77.68.74.54 + } + } + rule 2102 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-109.72.210.46 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 109.72.210.46 + } + } + rule 2103 { + action accept + description FW5A77C_16-TCP-ALLOW-213.171.217.107 + destination { + group { + address-group DT_FW5A77C_16 + } + port 22 + } + protocol tcp + source { + address 213.171.217.107 + } + } + rule 2104 { + action accept + description FW826BA_3-TCP-ALLOW-164.177.156.192 + destination { + group { + address-group DT_FW826BA_3 + } + port 3389,1433,21 + } + protocol tcp + source { + address 164.177.156.192 + } + } + rule 2105 { + action accept + description FWDAA4F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDAA4F_1 + } + port 22335 + } + protocol tcp + } + rule 2106 { + action accept + description FW6D0CD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6D0CD_1 + } + port 6900,7000 + } + protocol tcp + } + rule 2107 { + action accept + description FW6D0CD_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6D0CD_1 + } + port 9001 + } + protocol tcp_udp + } + rule 2108 { + action accept + description FW06176_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW06176_1 + } + port 5900 + } + protocol tcp + } + rule 2109 { + action accept + description FW19987_4-TCP-ALLOW-77.68.77.70 + destination { + group { + address-group DT_FW19987_4 + } + port 443 + } + protocol tcp + source { + address 77.68.77.70 + } + } + rule 2110 { + action accept + description FWF7B68_1-TCP-ALLOW-54.221.251.224 + destination { + group { + address-group DT_FWF7B68_1 + } + port 8443,3306,22,21,20 + } + protocol tcp + source { + address 54.221.251.224 + } + } + rule 2111 { + action accept + description FW05AD0_2-TCP-ALLOW-178.251.181.41 + destination { + group { + address-group DT_FW05AD0_2 + } + port 3389,1433,21 + } + protocol tcp + source { + address 178.251.181.41 + } + } + rule 2112 { + action accept + description FW05AD0_2-TCP-ALLOW-178.251.181.6 + destination { + group { + address-group DT_FW05AD0_2 + } + port 3389,1433,21 + } + protocol tcp + source { + address 178.251.181.6 + } + } + rule 2113 { + action accept + description VPN-7030-ANY-ALLOW-10.4.58.119 + destination { + group { + address-group DT_VPN-7030 + } + } + source { + address 10.4.58.119 + } + } + rule 2114 { + action accept + description FW58C69_4-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW58C69_4 + } + port 5666 + } + protocol tcp + } + rule 2115 { + action accept + description FW2BB8D_1-TCP-ALLOW-185.201.180.35 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000,22 + } + protocol tcp + source { + address 185.201.180.35 + } + } + rule 2116 { + action accept + description FW19987_4-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FW19987_4 + } + port 3389,445,443 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2117 { + action accept + description FW19987_4-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FW19987_4 + } + port 3389,445,443 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 2118 { + action accept + description FW5658C_1-TCP-ALLOW-212.159.160.65 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443,3389,3306,22,21 + } + protocol tcp + source { + address 212.159.160.65 + } + } + rule 2119 { + action accept + description FW5658C_1-TCP-ALLOW-79.78.20.149 + destination { + group { + address-group DT_FW5658C_1 + } + port 8447,8443,3389,3306,993,143,22,21 + } + protocol tcp + source { + address 79.78.20.149 + } + } + rule 2120 { + action accept + description FW5658C_1-TCP-ALLOW-77.68.77.185 + destination { + group { + address-group DT_FW5658C_1 + } + port 3306 + } + protocol tcp + source { + address 77.68.77.185 + } + } + rule 2121 { + action accept + description FW5658C_1-TCP-ALLOW-82.165.232.19 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443,3389 + } + protocol tcp + source { + address 82.165.232.19 + } + } + rule 2122 { + action accept + description FW2C5AE_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2C5AE_1 + } + port 30303,5717 + } + protocol tcp_udp + } + rule 2123 { + action accept + description VPN-12899-ANY-ALLOW-10.4.58.207 + destination { + group { + address-group DT_VPN-12899 + } + } + source { + address 10.4.58.207 + } + } + rule 2124 { + action accept + description FW7648D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW7648D_1 + } + port 8501,8050,7801,4444,1443 + } + protocol tcp + } + rule 2125 { + action accept + description FW0C2E6_4-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0C2E6_4 + } + port 1194 + } + protocol udp + } + rule 2126 { + action accept + description FW5658C_1-TCP-ALLOW-39.37.175.132 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 39.37.175.132 + } + } + rule 2127 { + action accept + description FW826BA_3-TCP-ALLOW-165.255.242.223 + destination { + group { + address-group DT_FW826BA_3 + } + port 3389,1433,21 + } + protocol tcp + source { + address 165.255.242.223 + } + } + rule 2128 { + action accept + description VPN-10131-ANY-ALLOW-10.4.56.51 + destination { + group { + address-group DT_VPN-10131 + } + } + source { + address 10.4.56.51 + } + } + rule 2129 { + action accept + description FW2BB8D_1-TCP-ALLOW-212.227.84.142 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 22 + } + protocol tcp + source { + address 212.227.84.142 + } + } + rule 2130 { + action accept + description FW2BB8D_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2BB8D_1 + } + port 53 + } + protocol tcp_udp + } + rule 2131 { + action accept + description FWFDD94_15-TCP-ALLOW-90.29.180.234 + destination { + group { + address-group DT_FWFDD94_15 + } + port 5683,1883 + } + protocol tcp + source { + address 90.29.180.234 + } + } + rule 2132 { + action accept + description VPN-10131-ANY-ALLOW-10.4.57.51 + destination { + group { + address-group DT_VPN-10131 + } + } + source { + address 10.4.57.51 + } + } + rule 2133 { + action accept + description FW2BB8D_1-TCP-ALLOW-109.228.49.193 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 5000 + } + protocol tcp + source { + address 109.228.49.193 + } + } + rule 2134 { + action accept + description FW81138_1-ICMP-ALLOW-3.10.221.168 + destination { + group { + address-group DT_FW81138_1 + } + } + protocol icmp + source { + address 3.10.221.168 + } + } + rule 2135 { + action accept + description FWB28B6_5-AH-ALLOW-77.68.36.46 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol ah + source { + address 77.68.36.46 + } + } + rule 2136 { + action accept + description FWB28B6_5-ESP-ALLOW-77.68.36.46 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol esp + source { + address 77.68.36.46 + } + } + rule 2137 { + action accept + description FW825C8_24-TCP-ALLOW-77.68.87.201 + destination { + group { + address-group DT_FW825C8_24 + } + port 1433 + } + protocol tcp + source { + address 77.68.87.201 + } + } + rule 2138 { + action accept + description FWB28B6_5-AH-ALLOW-213.171.196.146 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol ah + source { + address 213.171.196.146 + } + } + rule 2139 { + action accept + description FWB28B6_5-ESP-ALLOW-213.171.196.146 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol esp + source { + address 213.171.196.146 + } + } + rule 2140 { + action accept + description FWB28B6_5-UDP-ALLOW-213.171.196.146 + destination { + group { + address-group DT_FWB28B6_5 + } + port 500,4500 + } + protocol udp + source { + address 213.171.196.146 + } + } + rule 2141 { + action accept + description FWB28B6_5-TCP_UDP-ALLOW-213.171.196.146 + destination { + group { + address-group DT_FWB28B6_5 + } + port 1701 + } + protocol tcp_udp + source { + address 213.171.196.146 + } + } + rule 2142 { + action accept + description FWB28B6_5-TCP_UDP-ALLOW-77.68.36.46 + destination { + group { + address-group DT_FWB28B6_5 + } + port 1701 + } + protocol tcp_udp + source { + address 77.68.36.46 + } + } + rule 2143 { + action accept + description FWB28B6_5-UDP-ALLOW-77.68.36.46 + destination { + group { + address-group DT_FWB28B6_5 + } + port 500,4500 + } + protocol udp + source { + address 77.68.36.46 + } + } + rule 2144 { + action accept + description VPN-12899-ANY-ALLOW-10.4.59.207 + destination { + group { + address-group DT_VPN-12899 + } + } + source { + address 10.4.59.207 + } + } + rule 2145 { + action accept + description FWB28B6_5-TCP-ALLOW-81.130.141.175 + destination { + group { + address-group DT_FWB28B6_5 + } + port 3389 + } + protocol tcp + source { + address 81.130.141.175 + } + } + rule 2146 { + action accept + description FWB28B6_5-UDP-ALLOW-77.68.38.195 + destination { + group { + address-group DT_FWB28B6_5 + } + port 4500,500 + } + protocol udp + source { + address 77.68.38.195 + } + } + rule 2147 { + action accept + description FWB28B6_5-AH-ALLOW-77.68.38.195 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol ah + source { + address 77.68.38.195 + } + } + rule 2148 { + action accept + description FWB28B6_5-ESP-ALLOW-77.68.38.195 + destination { + group { + address-group DT_FWB28B6_5 + } + } + protocol esp + source { + address 77.68.38.195 + } + } + rule 2149 { + action accept + description FWB28B6_5-TCP_UDP-ALLOW-77.68.38.195 + destination { + group { + address-group DT_FWB28B6_5 + } + port 1701 + } + protocol tcp_udp + source { + address 77.68.38.195 + } + } + rule 2150 { + action accept + description FW5658C_1-TCP-ALLOW-39.37.178.77 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 39.37.178.77 + } + } + rule 2151 { + action accept + description FW5A77C_16-TCP-ALLOW-51.241.139.56 + destination { + group { + address-group DT_FW5A77C_16 + } + port 22 + } + protocol tcp + source { + address 51.241.139.56 + } + } + rule 2152 { + action accept + description FWA86ED_101-TCP-ALLOW-150.143.57.138 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389 + } + protocol tcp + source { + address 150.143.57.138 + } + } + rule 2153 { + action accept + description FW6ECA4_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6ECA4_1 + } + port 3939,3335,3334,3333,3000,999,444 + } + protocol tcp_udp + } + rule 2154 { + action accept + description FW5658C_1-TCP-ALLOW-39.45.13.20 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 39.45.13.20 + } + } + rule 2155 { + action accept + description FW481D7_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW481D7_1 + } + port 3478 + } + protocol tcp_udp + } + rule 2156 { + action accept + description FW5A5D7_3-GRE-ALLOW-51.219.222.28 + destination { + group { + address-group DT_FW5A5D7_3 + } + } + protocol gre + source { + address 51.219.222.28 + } + } + rule 2157 { + action accept + description FWA86ED_101-TCP-ALLOW-94.195.127.217 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 94.195.127.217 + } + } + rule 2158 { + action accept + description FW2E060_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2E060_1 + } + port 49152-65535,8443-8447 + } + protocol tcp + } + rule 2159 { + action accept + description FWFDD94_15-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWFDD94_15 + } + port 9090,5080,1935 + } + protocol tcp + } + rule 2160 { + action accept + description FW5658C_1-TCP-ALLOW-39.45.190.224 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 39.45.190.224 + } + } + rule 2161 { + action accept + description FW9E550_1-TCP-ALLOW-109.249.187.56 + destination { + group { + address-group DT_FW9E550_1 + } + port 3389 + } + protocol tcp + source { + address 109.249.187.56 + } + } + rule 2162 { + action accept + description FW89619_1-TCP-ALLOW-81.133.80.114 + destination { + group { + address-group DT_FW89619_1 + } + port 22 + } + protocol tcp + source { + address 81.133.80.114 + } + } + rule 2163 { + action accept + description FW8A3FC_3-TCP-ALLOW-212.227.72.218 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 212.227.72.218 + } + } + rule 2164 { + action accept + description FW0E383_9-TCP-ALLOW-151.229.59.51 + destination { + group { + address-group DT_FW0E383_9 + } + port 1433 + } + protocol tcp + source { + address 151.229.59.51 + } + } + rule 2165 { + action accept + description FW8AFF1_7-TCP-ALLOW-178.251.181.41 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433,21 + } + protocol tcp + source { + address 178.251.181.41 + } + } + rule 2166 { + action accept + description FW3CAAB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW3CAAB_1 + } + port 49152-65535,30000-30400,8443-8447,5432,80-110,21-25 + } + protocol tcp + } + rule 2167 { + action accept + description FW91B7A_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW91B7A_1 + } + port 3389,80 + } + protocol tcp_udp + } + rule 2168 { + action accept + description FW40416_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW40416_1 + } + port 1-65535 + } + protocol tcp + } + rule 2169 { + action accept + description FW5A77C_16-TCP-ALLOW-81.151.24.216 + destination { + group { + address-group DT_FW5A77C_16 + } + port 10000,22 + } + protocol tcp + source { + address 81.151.24.216 + } + } + rule 2170 { + action accept + description VPN-7030-ANY-ALLOW-10.4.59.119 + destination { + group { + address-group DT_VPN-7030 + } + } + source { + address 10.4.59.119 + } + } + rule 2171 { + action accept + description FW0E383_9-TCP-ALLOW-62.252.94.138 + destination { + group { + address-group DT_FW0E383_9 + } + port 3389,1433 + } + protocol tcp + source { + address 62.252.94.138 + } + } + rule 2172 { + action accept + description FW89619_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW89619_1 + } + port 5015,5001,5000 + } + protocol tcp + } + rule 2173 { + action accept + description FW89619_1-TCP_UDP-ALLOW-167.98.162.142 + destination { + group { + address-group DT_FW89619_1 + } + port 5060 + } + protocol tcp_udp + source { + address 167.98.162.142 + } + } + rule 2174 { + action accept + description FW013EF_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW013EF_2 + } + port 44445,7770-7800,5090,5060-5070,5015,5001,2000-2500 + } + protocol tcp + } + rule 2175 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.12 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.12 + } + } + rule 2176 { + action accept + description VPN-15625-ANY-ALLOW-10.4.88.79 + destination { + group { + address-group DT_VPN-15625 + } + } + source { + address 10.4.88.79 + } + } + rule 2177 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.228.53.128 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306,22 + } + protocol tcp + source { + address 109.228.53.128 + } + } + rule 2178 { + action accept + description FW8AFF1_7-TCP-ALLOW-178.251.181.6 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 3389,1433,21 + } + protocol tcp + source { + address 178.251.181.6 + } + } + rule 2179 { + action accept + description FW578BE_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW578BE_1 + } + port 23,1521,1522 + } + protocol tcp + } + rule 2180 { + action accept + description FWE012D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE012D_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2181 { + action accept + description FW8AFF1_7-TCP-ALLOW-213.171.209.161 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 3389,1433,21 + } + protocol tcp + source { + address 213.171.209.161 + } + } + rule 2182 { + action accept + description VPN-8203-ANY-ALLOW-10.4.58.109 + destination { + group { + address-group DT_VPN-8203 + } + } + source { + address 10.4.58.109 + } + } + rule 2183 { + action accept + description VPN-9415-ANY-ALLOW-10.4.58.168 + destination { + group { + address-group DT_VPN-9415 + } + } + source { + address 10.4.58.168 + } + } + rule 2184 { + action accept + description VPN-9415-ANY-ALLOW-10.4.59.168 + destination { + group { + address-group DT_VPN-9415 + } + } + source { + address 10.4.59.168 + } + } + rule 2185 { + action accept + description FW27A8F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW27A8F_1 + } + port 9990,8458,8090,6543,5432 + } + protocol tcp + } + rule 2186 { + action accept + description FW2BB8D_1-TCP-ALLOW-77.68.11.224 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 5000 + } + protocol tcp + source { + address 77.68.11.224 + } + } + rule 2187 { + action accept + description VPN-15625-ANY-ALLOW-10.4.89.79 + destination { + group { + address-group DT_VPN-15625 + } + } + source { + address 10.4.89.79 + } + } + rule 2188 { + action accept + description VPN-14649-ANY-ALLOW-10.4.86.35 + destination { + group { + address-group DT_VPN-14649 + } + } + source { + address 10.4.86.35 + } + } + rule 2189 { + action accept + description VPN-14649-ANY-ALLOW-10.4.87.35 + destination { + group { + address-group DT_VPN-14649 + } + } + source { + address 10.4.87.35 + } + } + rule 2190 { + action accept + description VPN-14657-ANY-ALLOW-10.4.86.38 + destination { + group { + address-group DT_VPN-14657 + } + } + source { + address 10.4.86.38 + } + } + rule 2191 { + action accept + description VPN-14657-ANY-ALLOW-10.4.87.38 + destination { + group { + address-group DT_VPN-14657 + } + } + source { + address 10.4.87.38 + } + } + rule 2192 { + action accept + description VPN-14658-ANY-ALLOW-10.4.88.38 + destination { + group { + address-group DT_VPN-14658 + } + } + source { + address 10.4.88.38 + } + } + rule 2193 { + action accept + description VPN-14658-ANY-ALLOW-10.4.89.38 + destination { + group { + address-group DT_VPN-14658 + } + } + source { + address 10.4.89.38 + } + } + rule 2194 { + action accept + description FW0BB22_1-GRE-ALLOW-ANY + destination { + group { + address-group DT_FW0BB22_1 + } + } + protocol gre + } + rule 2195 { + action accept + description FW0BB22_1-ESP-ALLOW-ANY + destination { + group { + address-group DT_FW0BB22_1 + } + } + protocol esp + } + rule 2196 { + action accept + description FW1CC15_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1CC15_2 + } + port 8089,8085,990,81 + } + protocol tcp + } + rule 2197 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.0.124 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.0.124 + } + } + rule 2198 { + action accept + description FW5A5D7_3-TCP-ALLOW-51.219.222.28 + destination { + group { + address-group DT_FW5A5D7_3 + } + port 8172,3389,1723,1701,47 + } + protocol tcp + source { + address 51.219.222.28 + } + } + rule 2199 { + action accept + description FW1CB16_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW1CB16_1 + } + port 3306,27017,53 + } + protocol tcp_udp + } + rule 2200 { + action accept + description FWE47DA_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE47DA_1 + } + port 7770-7800,44445 + } + protocol tcp + } + rule 2201 { + action accept + description FW37E59_5-TCP-ALLOW-77.68.20.244 + destination { + group { + address-group DT_FW37E59_5 + } + port 30303 + } + protocol tcp + source { + address 77.68.20.244 + } + } + rule 2202 { + action accept + description FW274FD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW274FD_1 + } + port 49152-65534 + } + protocol tcp + } + rule 2203 { + action accept + description FW6CD7E_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6CD7E_2 + } + port 49152-65535 + } + protocol tcp + } + rule 2204 { + action accept + description FW826BA_3-TCP-ALLOW-178.17.252.59 + destination { + group { + address-group DT_FW826BA_3 + } + port 21 + } + protocol tcp + source { + address 178.17.252.59 + } + } + rule 2205 { + action accept + description FW89619_1-TCP_UDP-ALLOW-185.83.64.108 + destination { + group { + address-group DT_FW89619_1 + } + port 5060 + } + protocol tcp_udp + source { + address 185.83.64.108 + } + } + rule 2206 { + action accept + description FW0937A_1-TCP-ALLOW-83.135.134.13 + destination { + group { + address-group DT_FW0937A_1 + } + port 22 + } + protocol tcp + source { + address 83.135.134.13 + } + } + rule 2207 { + action accept + description FW2BB8D_1-TCP-ALLOW-77.68.112.64 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000 + } + protocol tcp + source { + address 77.68.112.64 + } + } + rule 2208 { + action accept + description FW6CD7E_2-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6CD7E_2 + } + port 53 + } + protocol tcp_udp + } + rule 2209 { + action accept + description FW1F3D0_6-TCP-ALLOW-194.73.17.47 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306,22 + } + protocol tcp + source { + address 194.73.17.47 + } + } + rule 2210 { + action accept + description FW0E383_9-TCP-ALLOW-77.68.115.33 + destination { + group { + address-group DT_FW0E383_9 + } + port 1433 + } + protocol tcp + source { + address 77.68.115.33 + } + } + rule 2211 { + action accept + description FWA3EA3_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA3EA3_1 + } + port 943 + } + protocol tcp + } + rule 2212 { + action accept + description FW6863A_4-TCP-ALLOW-82.165.100.25 + destination { + group { + address-group DT_FW6863A_4 + } + port 21-10000 + } + protocol tcp + source { + address 82.165.100.25 + } + } + rule 2213 { + action accept + description FWECBFB_14-TCP-ALLOW-109.228.59.50 + destination { + group { + address-group DT_FWECBFB_14 + } + port 22 + } + protocol tcp + source { + address 109.228.59.50 + } + } + rule 2214 { + action accept + description FW2F868_6-TCP-ALLOW-213.171.217.100 + destination { + group { + address-group DT_FW2F868_6 + } + port 22 + } + protocol tcp + source { + address 213.171.217.100 + } + } + rule 2215 { + action accept + description FWD7EAB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD7EAB_1 + } + port 60000-60100 + } + protocol tcp + } + rule 2216 { + action accept + description FWEB321_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWEB321_1 + } + port 113,4190 + } + protocol tcp + } + rule 2217 { + action accept + description FW9C682_3-TCP-ALLOW-195.206.180.132 + destination { + group { + address-group DT_FW9C682_3 + } + port 8443,22 + } + protocol tcp + source { + address 195.206.180.132 + } + } + rule 2218 { + action accept + description VPN-8159-ANY-ALLOW-10.4.58.91 + destination { + group { + address-group DT_VPN-8159 + } + } + source { + address 10.4.58.91 + } + } + rule 2219 { + action accept + description VPN-21673-ANY-ALLOW-10.4.88.187 + destination { + group { + address-group DT_VPN-21673 + } + } + source { + address 10.4.88.187 + } + } + rule 2220 { + action accept + description VPN-21673-ANY-ALLOW-10.4.89.187 + destination { + group { + address-group DT_VPN-21673 + } + } + source { + address 10.4.89.187 + } + } + rule 2221 { + action accept + description VPN-21821-ANY-ALLOW-10.4.88.49 + destination { + group { + address-group DT_VPN-21821 + } + } + source { + address 10.4.88.49 + } + } + rule 2222 { + action accept + description VPN-21821-ANY-ALLOW-10.4.89.49 + destination { + group { + address-group DT_VPN-21821 + } + } + source { + address 10.4.89.49 + } + } + rule 2223 { + action accept + description FWECBFB_14-TCP-ALLOW-81.133.80.58 + destination { + group { + address-group DT_FWECBFB_14 + } + port 22 + } + protocol tcp + source { + address 81.133.80.58 + } + } + rule 2224 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.238 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.238 + } + } + rule 2225 { + action accept + description FW826BA_3-TCP-ALLOW-185.212.168.51 + destination { + group { + address-group DT_FW826BA_3 + } + port 3389,1433,21 + } + protocol tcp + source { + address 185.212.168.51 + } + } + rule 2226 { + action accept + description FW8B21D_1-ANY-ALLOW-212.187.250.2 + destination { + group { + address-group DT_FW8B21D_1 + } + } + source { + address 212.187.250.2 + } + } + rule 2227 { + action accept + description FW35F7B_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW35F7B_1 + } + port 1434 + } + protocol tcp_udp + } + rule 2228 { + action accept + description FWD338A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD338A_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2229 { + action accept + description FW35F7B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW35F7B_1 + } + port 56791 + } + protocol tcp + } + rule 2230 { + action accept + description FW0E383_9-TCP-ALLOW-77.68.77.114 + destination { + group { + address-group DT_FW0E383_9 + } + port 1433 + } + protocol tcp + source { + address 77.68.77.114 + } + } + rule 2231 { + action accept + description FW90AE3_1-TCP-ALLOW-194.74.137.17 + destination { + group { + address-group DT_FW90AE3_1 + } + port 22 + } + protocol tcp + source { + address 194.74.137.17 + } + } + rule 2232 { + action accept + description FW52F6F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW52F6F_1 + } + port 53 + } + protocol tcp_udp + } + rule 2233 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.23.109 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306,22 + } + protocol tcp + source { + address 77.68.23.109 + } + } + rule 2234 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.247 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.247 + } + } + rule 2235 { + action accept + description FW4E314_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW4E314_1 + } + port 53 + } + protocol tcp_udp + } + rule 2236 { + action accept + description FW73573_2-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW73573_2 + } + port 25 + } + protocol tcp_udp + } + rule 2237 { + action accept + description FW0E383_9-TCP-ALLOW-77.68.93.89 + destination { + group { + address-group DT_FW0E383_9 + } + port 1433 + } + protocol tcp + source { + address 77.68.93.89 + } + } + rule 2238 { + action accept + description FW856FA_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW856FA_1 + } + port 6003 + } + protocol tcp + } + rule 2239 { + action accept + description FWECBFB_14-TCP-ALLOW-81.19.214.155 + destination { + group { + address-group DT_FWECBFB_14 + } + port 22 + } + protocol tcp + source { + address 81.19.214.155 + } + } + rule 2240 { + action accept + description FW826BA_3-TCP-ALLOW-51.219.168.170 + destination { + group { + address-group DT_FW826BA_3 + } + port 3389,1433,21 + } + protocol tcp + source { + address 51.219.168.170 + } + } + rule 2241 { + action accept + description FW30D21_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW30D21_1 + } + port 2083-2087,53,2812,2096,25,993,587 + } + protocol tcp_udp + } + rule 2242 { + action accept + description FWA076E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA076E_1 + } + port 2199,2197 + } + protocol tcp + } + rule 2243 { + action accept + description FWA076E_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA076E_1 + } + port 8000-8010 + } + protocol tcp_udp + } + rule 2244 { + action accept + description FW8A3FC_3-TCP-ALLOW-82.165.166.41 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 8447,8443,443,80,22 + } + protocol tcp + source { + address 82.165.166.41 + } + } + rule 2245 { + action accept + description FW2F868_6-TCP-ALLOW-213.171.217.180 + destination { + group { + address-group DT_FW2F868_6 + } + port 22,80 + } + protocol tcp + source { + address 213.171.217.180 + } + } + rule 2246 { + action accept + description FW2F868_6-TCP-ALLOW-213.171.217.184 + destination { + group { + address-group DT_FW2F868_6 + } + port 22 + } + protocol tcp + source { + address 213.171.217.184 + } + } + rule 2247 { + action accept + description FW2F868_6-TCP-ALLOW-213.171.217.185 + destination { + group { + address-group DT_FW2F868_6 + } + port 22 + } + protocol tcp + source { + address 213.171.217.185 + } + } + rule 2248 { + action accept + description FW2F868_6-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2F868_6 + } + port 161 + } + protocol udp + } + rule 2249 { + action accept + description FW2F868_6-TCP-ALLOW-213.171.217.102 + destination { + group { + address-group DT_FW2F868_6 + } + port 22,24 + } + protocol tcp + source { + address 213.171.217.102 + } + } + rule 2250 { + action accept + description FW9C682_3-TCP-ALLOW-80.194.78.162 + destination { + group { + address-group DT_FW9C682_3 + } + port 8443,22 + } + protocol tcp + source { + address 80.194.78.162 + } + } + rule 2251 { + action accept + description VPN-21822-ANY-ALLOW-10.4.54.47 + destination { + group { + address-group DT_VPN-21822 + } + } + source { + address 10.4.54.47 + } + } + rule 2252 { + action accept + description FW825C8_19-TCP-ALLOW-77.68.75.244 + destination { + group { + address-group DT_FW825C8_19 + } + port 1433 + } + protocol tcp + source { + address 77.68.75.244 + } + } + rule 2253 { + action accept + description FW2B279_4-TCP-ALLOW-195.147.173.92 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,22 + } + protocol tcp + source { + address 195.147.173.92 + } + } + rule 2254 { + action accept + description FW1D511_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1D511_2 + } + port 8090 + } + protocol tcp + } + rule 2255 { + action accept + description FW8A3FC_3-TCP-ALLOW-85.17.25.47 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 85.17.25.47 + } + } + rule 2256 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.89.209 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306,22 + } + protocol tcp + source { + address 77.68.89.209 + } + } + rule 2257 { + action accept + description FWE2AB5_8-TCP-ALLOW-213.171.217.184 + destination { + group { + address-group DT_FWE2AB5_8 + } + port 7000 + } + protocol tcp + source { + address 213.171.217.184 + } + } + rule 2258 { + action accept + description FW0E383_9-TCP-ALLOW-77.68.94.177 + destination { + group { + address-group DT_FW0E383_9 + } + port 1433 + } + protocol tcp + source { + address 77.68.94.177 + } + } + rule 2259 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.95.129 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306,22 + } + protocol tcp + source { + address 77.68.95.129 + } + } + rule 2260 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.104.118.136 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 109.104.118.136 + } + } + rule 2261 { + action accept + description FW1FA9E_1-TCP-ALLOW-78.88.254.99 + destination { + group { + address-group DT_FW1FA9E_1 + } + port 9000,8200,5601,4444 + } + protocol tcp + source { + address 78.88.254.99 + } + } + rule 2262 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.46.27 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.46.27 + } + } + rule 2263 { + action accept + description FWA7A50_1-TCP-ALLOW-81.110.192.198 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp + source { + address 81.110.192.198 + } + } + rule 2264 { + action accept + description VPN-21822-ANY-ALLOW-10.4.55.47 + destination { + group { + address-group DT_VPN-21822 + } + } + source { + address 10.4.55.47 + } + } + rule 2265 { + action accept + description FW2BB8D_1-TCP-ALLOW-77.68.31.195 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000 + } + protocol tcp + source { + address 77.68.31.195 + } + } + rule 2266 { + action accept + description FW45BEB_1-TCP-ALLOW-62.3.71.238 + destination { + group { + address-group DT_FW45BEB_1 + } + port 3389 + } + protocol tcp + source { + address 62.3.71.238 + } + } + rule 2267 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.113 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.113 + } + } + rule 2268 { + action accept + description VPN-23946-ANY-ALLOW-10.4.58.13 + destination { + group { + address-group DT_VPN-23946 + } + } + source { + address 10.4.58.13 + } + } + rule 2269 { + action accept + description FW98818_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW98818_1 + } + port 27015 + } + protocol tcp + } + rule 2270 { + action accept + description VPN-23946-ANY-ALLOW-10.4.59.13 + destination { + group { + address-group DT_VPN-23946 + } + } + source { + address 10.4.59.13 + } + } + rule 2271 { + action accept + description VPN-28031-ANY-ALLOW-10.4.88.197 + destination { + group { + address-group DT_VPN-28031 + } + } + source { + address 10.4.88.197 + } + } + rule 2272 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.104.118.231 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 109.104.118.231 + } + } + rule 2273 { + action accept + description FW5A5D7_3-TCP_UDP-ALLOW-51.219.222.28 + destination { + group { + address-group DT_FW5A5D7_3 + } + port 500 + } + protocol tcp_udp + source { + address 51.219.222.28 + } + } + rule 2274 { + action accept + description FW32EFF_25-TCP-ALLOW-185.106.220.231 + destination { + group { + address-group DT_FW32EFF_25 + } + port 443 + } + protocol tcp + source { + address 185.106.220.231 + } + } + rule 2275 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.104.118.66 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 109.104.118.66 + } + } + rule 2276 { + action accept + description FW934AE_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW934AE_1 + } + port 1194 + } + protocol udp + } + rule 2277 { + action accept + description VPN-28031-ANY-ALLOW-10.4.89.197 + destination { + group { + address-group DT_VPN-28031 + } + } + source { + address 10.4.89.197 + } + } + rule 2278 { + action accept + description FW6863A_4-TCP_UDP-ALLOW-82.165.166.41 + destination { + group { + address-group DT_FW6863A_4 + } + port 21-10000 + } + protocol tcp_udp + source { + address 82.165.166.41 + } + } + rule 2279 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.104.119.162 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 109.104.119.162 + } + } + rule 2280 { + action accept + description FW1F3D0_6-TCP-ALLOW-109.74.199.143 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 109.74.199.143 + } + } + rule 2281 { + action accept + description FW1F3D0_6-TCP-ALLOW-185.92.25.48 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 185.92.25.48 + } + } + rule 2282 { + action accept + description FW1F3D0_6-TCP-ALLOW-207.148.2.40 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 207.148.2.40 + } + } + rule 2283 { + action accept + description FW1F3D0_6-TCP-ALLOW-45.76.235.62 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 45.76.235.62 + } + } + rule 2284 { + action accept + description FW1F3D0_6-TCP-ALLOW-45.76.236.93 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 45.76.236.93 + } + } + rule 2285 { + action accept + description FW1F3D0_6-TCP-ALLOW-45.76.59.5 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 45.76.59.5 + } + } + rule 2286 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.15.134 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4444,3306 + } + protocol tcp + source { + address 77.68.15.134 + } + } + rule 2287 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.22.208 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4444,3306 + } + protocol tcp + source { + address 77.68.22.208 + } + } + rule 2288 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.23.108 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 77.68.23.108 + } + } + rule 2289 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.23.54 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 77.68.23.54 + } + } + rule 2290 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.30.45 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 77.68.30.45 + } + } + rule 2291 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.7.198 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 77.68.7.198 + } + } + rule 2292 { + action accept + description VPN-29631-ANY-ALLOW-10.4.54.76 + destination { + group { + address-group DT_VPN-29631 + } + } + source { + address 10.4.54.76 + } + } + rule 2293 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.89.200 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4444,3306 + } + protocol tcp + source { + address 77.68.89.200 + } + } + rule 2294 { + action accept + description FW1F3D0_6-TCP-ALLOW-77.68.91.50 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 77.68.91.50 + } + } + rule 2295 { + action accept + description FW1F3D0_6-TCP-ALLOW-82.165.206.230 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 82.165.206.230 + } + } + rule 2296 { + action accept + description FW1F3D0_6-TCP-ALLOW-82.165.207.109 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4444,3306 + } + protocol tcp + source { + address 82.165.207.109 + } + } + rule 2297 { + action accept + description FW1F3D0_6-TCP-ALLOW-94.196.156.5 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 3306 + } + protocol tcp + source { + address 94.196.156.5 + } + } + rule 2298 { + action accept + description FW1F3D0_6-TCP_UDP-ALLOW-77.68.15.134 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4567-4568 + } + protocol tcp_udp + source { + address 77.68.15.134 + } + } + rule 2299 { + action accept + description FW1F3D0_6-TCP_UDP-ALLOW-77.68.22.208 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4567-4568 + } + protocol tcp_udp + source { + address 77.68.22.208 + } + } + rule 2300 { + action accept + description FW1F3D0_6-TCP_UDP-ALLOW-77.68.23.109 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4567-4568 + } + protocol tcp_udp + source { + address 77.68.23.109 + } + } + rule 2301 { + action accept + description FW1F3D0_6-TCP_UDP-ALLOW-77.68.89.200 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4567-4568 + } + protocol tcp_udp + source { + address 77.68.89.200 + } + } + rule 2302 { + action accept + description FW05339_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW05339_1 + } + port 8085,5055,5013,5005,444 + } + protocol tcp + } + rule 2303 { + action accept + description FW32EFF_25-TCP-ALLOW-217.169.61.164 + destination { + group { + address-group DT_FW32EFF_25 + } + port 443 + } + protocol tcp + source { + address 217.169.61.164 + } + } + rule 2304 { + action accept + description FW89619_1-TCP_UDP-ALLOW-185.83.65.45 + destination { + group { + address-group DT_FW89619_1 + } + port 5060 + } + protocol tcp_udp + source { + address 185.83.65.45 + } + } + rule 2305 { + action accept + description VPN-13983-ANY-ALLOW-10.4.58.176 + destination { + group { + address-group DT_VPN-13983 + } + } + source { + address 10.4.58.176 + } + } + rule 2306 { + action accept + description FWDAF47_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWDAF47_1 + } + port 8090,7080,443,53 + } + protocol tcp_udp + } + rule 2307 { + action accept + description VPN-29631-ANY-ALLOW-10.4.55.77 + destination { + group { + address-group DT_VPN-29631 + } + } + source { + address 10.4.55.77 + } + } + rule 2308 { + action accept + description VPN-34309-ANY-ALLOW-10.4.58.142 + destination { + group { + address-group DT_VPN-34309 + } + } + source { + address 10.4.58.142 + } + } + rule 2309 { + action accept + description FW27949_2-TCP-ALLOW-138.124.142.180 + destination { + group { + address-group DT_FW27949_2 + } + port 443,80 + } + protocol tcp + source { + address 138.124.142.180 + } + } + rule 2310 { + action accept + description FWF8F85_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF8F85_1 + } + port 3306 + } + protocol tcp_udp + } + rule 2311 { + action accept + description FWDAF47_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDAF47_1 + } + port 40110-40210 + } + protocol tcp + } + rule 2312 { + action accept + description VPN-34309-ANY-ALLOW-10.4.59.142 + destination { + group { + address-group DT_VPN-34309 + } + } + source { + address 10.4.59.142 + } + } + rule 2313 { + action accept + description FWA0531_1-TCP-ALLOW-87.224.39.220 + destination { + group { + address-group DT_FWA0531_1 + } + port 22 + } + protocol tcp + source { + address 87.224.39.220 + } + } + rule 2314 { + action accept + description FW5A5D7_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW5A5D7_3 + } + port 1334 + } + protocol tcp + } + rule 2315 { + action accept + description FW8C927_1-TCP_UDP-ALLOW-84.92.125.78 + destination { + group { + address-group DT_FW8C927_1 + } + port 3306,22 + } + protocol tcp_udp + source { + address 84.92.125.78 + } + } + rule 2316 { + action accept + description FW8C927_1-TCP_UDP-ALLOW-88.208.238.152 + destination { + group { + address-group DT_FW8C927_1 + } + port 3306,22 + } + protocol tcp_udp + source { + address 88.208.238.152 + } + } + rule 2317 { + action accept + description FW81138_1-ICMP-ALLOW-82.165.232.19 + destination { + group { + address-group DT_FW81138_1 + } + } + protocol icmp + source { + address 82.165.232.19 + } + } + rule 2318 { + action accept + description FW28892_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW28892_1 + } + port 7000 + } + protocol tcp + } + rule 2319 { + action accept + description FWC96A1_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC96A1_1 + } + port 222 + } + protocol tcp + } + rule 2320 { + action accept + description VPN-13983-ANY-ALLOW-10.4.59.176 + destination { + group { + address-group DT_VPN-13983 + } + } + source { + address 10.4.59.176 + } + } + rule 2321 { + action accept + description FW2FB61_1-TCP-ALLOW-5.183.104.15 + destination { + group { + address-group DT_FW2FB61_1 + } + port 22 + } + protocol tcp + source { + address 5.183.104.15 + } + } + rule 2322 { + action accept + description FW81138_1-ICMP-ALLOW-82.20.69.137 + destination { + group { + address-group DT_FW81138_1 + } + } + protocol icmp + source { + address 82.20.69.137 + } + } + rule 2323 { + action accept + description FW72F37_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW72F37_1 + } + port 7770-7800,44445 + } + protocol tcp + } + rule 2324 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-81.111.155.34 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 81.111.155.34 + } + } + rule 2325 { + action accept + description VPN-20306-ANY-ALLOW-10.4.88.173 + destination { + group { + address-group DT_VPN-20306 + } + } + source { + address 10.4.88.173 + } + } + rule 2326 { + action accept + description FW6C992_1-TCP-ALLOW-89.33.185.0_24 + destination { + group { + address-group DT_FW6C992_1 + } + port 8447,8443,22 + } + protocol tcp + source { + address 89.33.185.0/24 + } + } + rule 2327 { + action accept + description FW2FB61_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2FB61_1 + } + port 45000 + } + protocol tcp + } + rule 2328 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.46.202 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 175.157.46.202 + } + } + rule 2329 { + action accept + description FWF9C28_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF9C28_2 + } + port 7770-7800,44445 + } + protocol tcp + } + rule 2330 { + action accept + description FW3DBF8_9-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW3DBF8_9 + } + port 8088,8080,5090,5060,3478,1935 + } + protocol tcp_udp + } + rule 2331 { + action accept + description FW3DBF8_9-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW3DBF8_9 + } + port 5062,5061,5015,5001 + } + protocol tcp + } + rule 2332 { + action accept + description VPN-16402-ANY-ALLOW-10.4.88.60 + destination { + group { + address-group DT_VPN-16402 + } + } + source { + address 10.4.88.60 + } + } + rule 2333 { + action accept + description FWC1315_1-TCP-ALLOW-62.3.71.238 + destination { + group { + address-group DT_FWC1315_1 + } + port 3389 + } + protocol tcp + source { + address 62.3.71.238 + } + } + rule 2334 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA7A50_1 + } + port 8001,80 + } + protocol tcp_udp + } + rule 2335 { + action accept + description FWAFF0A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWAFF0A_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2336 { + action accept + description FW2B279_4-TCP-ALLOW-195.20.253.19 + destination { + group { + address-group DT_FW2B279_4 + } + port 22 + } + protocol tcp + source { + address 195.20.253.19 + } + } + rule 2337 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.73 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.73 + } + } + rule 2338 { + action accept + description VPN-16402-ANY-ALLOW-10.4.89.60 + destination { + group { + address-group DT_VPN-16402 + } + } + source { + address 10.4.89.60 + } + } + rule 2339 { + action accept + description VPN-15951-ANY-ALLOW-10.4.86.90 + destination { + group { + address-group DT_VPN-15951 + } + } + source { + address 10.4.86.90 + } + } + rule 2340 { + action accept + description FW2BB8D_1-TCP-ALLOW-77.68.77.181 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000 + } + protocol tcp + source { + address 77.68.77.181 + } + } + rule 2341 { + action accept + description FWE9F7D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE9F7D_1 + } + port 4035 + } + protocol tcp + } + rule 2342 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.131 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.131 + } + } + rule 2343 { + action accept + description VPN-15951-ANY-ALLOW-10.4.87.90 + destination { + group { + address-group DT_VPN-15951 + } + } + source { + address 10.4.87.90 + } + } + rule 2344 { + action accept + description FW2BB8D_1-TCP-ALLOW-77.68.93.190 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000 + } + protocol tcp + source { + address 77.68.93.190 + } + } + rule 2345 { + action accept + description VPN-8159-ANY-ALLOW-10.4.59.91 + destination { + group { + address-group DT_VPN-8159 + } + } + source { + address 10.4.59.91 + } + } + rule 2346 { + action accept + description VPN-12870-ANY-ALLOW-10.4.54.67 + destination { + group { + address-group DT_VPN-12870 + } + } + source { + address 10.4.54.67 + } + } + rule 2347 { + action accept + description FW930F3_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW930F3_1 + } + port 53 + } + protocol tcp_udp + } + rule 2348 { + action accept + description FW12C32_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW12C32_1 + } + port 465,53,25 + } + protocol tcp_udp + } + rule 2349 { + action accept + description FW28EC8_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW28EC8_1 + } + port 20443 + } + protocol tcp + } + rule 2350 { + action accept + description VPN-12870-ANY-ALLOW-10.4.55.68 + destination { + group { + address-group DT_VPN-12870 + } + } + source { + address 10.4.55.68 + } + } + rule 2351 { + action accept + description FW934AE_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW934AE_1 + } + port 32401,32400,8081 + } + protocol tcp_udp + } + rule 2352 { + action accept + description FW6863A_4-TCP-ALLOW-185.173.161.154 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 185.173.161.154 + } + } + rule 2353 { + action accept + description FW013EF_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW013EF_2 + } + port 10600-10998,9000-9398,5090,5060-5070 + } + protocol udp + } + rule 2354 { + action accept + description FW85040_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW85040_1 + } + port 3210 + } + protocol tcp_udp + } + rule 2355 { + action accept + description FW8B21D_1-TCP_UDP-ALLOW-131.153.100.98 + destination { + group { + address-group DT_FW8B21D_1 + } + port 22 + } + protocol tcp_udp + source { + address 131.153.100.98 + } + } + rule 2356 { + action accept + description FW8B21D_1-TCP_UDP-ALLOW-213.133.99.176 + destination { + group { + address-group DT_FW8B21D_1 + } + port 22 + } + protocol tcp_udp + source { + address 213.133.99.176 + } + } + rule 2357 { + action accept + description FW6EFD7_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6EFD7_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2358 { + action accept + description FW8B21D_1-TCP_UDP-ALLOW-62.253.153.163 + destination { + group { + address-group DT_FW8B21D_1 + } + port 8443,22 + } + protocol tcp_udp + source { + address 62.253.153.163 + } + } + rule 2359 { + action accept + description FWCB0CF_7-TCP-ALLOW-212.159.153.201 + destination { + group { + address-group DT_FWCB0CF_7 + } + port 6443,5432-5434,5000-5100,3306-3308,990,989,22,21 + } + protocol tcp + source { + address 212.159.153.201 + } + } + rule 2360 { + action accept + description FW75CA4_6-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW75CA4_6 + } + port 51472,3747,3420 + } + protocol tcp + } + rule 2361 { + action accept + description FWF9C28_4-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF9C28_4 + } + port 23,7770-7800,44445,6109 + } + protocol tcp + } + rule 2362 { + action accept + description FW6B39D_1-TCP-ALLOW-120.72.95.88_29 + destination { + group { + address-group DT_FW6B39D_1 + } + port 3306 + } + protocol tcp + source { + address 120.72.95.88/29 + } + } + rule 2363 { + action accept + description FW934AE_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW934AE_1 + } + port 20000 + } + protocol tcp + } + rule 2364 { + action accept + description FW12C32_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW12C32_1 + } + port 2323,953 + } + protocol tcp + } + rule 2365 { + action accept + description FW49897_1-TCP-ALLOW-2.121.90.207 + destination { + group { + address-group DT_FW49897_1 + } + port 22 + } + protocol tcp + source { + address 2.121.90.207 + } + } + rule 2366 { + action accept + description FW6B39D_1-TCP-ALLOW-120.72.91.104_29 + destination { + group { + address-group DT_FW6B39D_1 + } + port 3306 + } + protocol tcp + source { + address 120.72.91.104/29 + } + } + rule 2367 { + action accept + description FW4F5EE_10-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4F5EE_10 + } + port 83,86,82 + } + protocol tcp + } + rule 2368 { + action accept + description FWF791C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF791C_1 + } + port 6001 + } + protocol tcp + } + rule 2369 { + action accept + description FWEF92E_5-ESP-ALLOW-109.228.37.19 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 109.228.37.19 + } + } + rule 2370 { + action accept + description FWE57AD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE57AD_1 + } + port 57000-58000 + } + protocol tcp + } + rule 2371 { + action accept + description FWC0CE0_1-TCP-ALLOW-62.232.209.221 + destination { + group { + address-group DT_FWC0CE0_1 + } + port 49152-65535,8447,8443,22,21 + } + protocol tcp + source { + address 62.232.209.221 + } + } + rule 2372 { + action accept + description FW0192C_1-TCP-ALLOW-41.140.242.86 + destination { + group { + address-group DT_FW0192C_1 + } + port 3306,22 + } + protocol tcp + source { + address 41.140.242.86 + } + } + rule 2373 { + action accept + description FWEEC75_1-TCP-ALLOW-54.171.71.110 + destination { + group { + address-group DT_FWEEC75_1 + } + port 21 + } + protocol tcp + source { + address 54.171.71.110 + } + } + rule 2374 { + action accept + description FW8B21D_1-TCP_UDP-ALLOW-95.149.182.69 + destination { + group { + address-group DT_FW8B21D_1 + } + port 22 + } + protocol tcp_udp + source { + address 95.149.182.69 + } + } + rule 2375 { + action accept + description FW8B21D_1-TCP-ALLOW-185.201.16.0_22 + destination { + group { + address-group DT_FW8B21D_1 + } + port 25 + } + protocol tcp + source { + address 185.201.16.0/22 + } + } + rule 2376 { + action accept + description FW8B21D_1-TCP-ALLOW-213.133.99.176 + destination { + group { + address-group DT_FW8B21D_1 + } + port 25 + } + protocol tcp + source { + address 213.133.99.176 + } + } + rule 2377 { + action accept + description FW8B21D_1-TCP-ALLOW-95.211.160.147 + destination { + group { + address-group DT_FW8B21D_1 + } + port 25 + } + protocol tcp + source { + address 95.211.160.147 + } + } + rule 2378 { + action accept + description FW6863A_4-TCP-ALLOW-212.227.9.72 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 212.227.9.72 + } + } + rule 2379 { + action accept + description FW8B21D_1-ESP-ALLOW-ANY + destination { + group { + address-group DT_FW8B21D_1 + } + } + protocol esp + } + rule 2380 { + action accept + description FW8B21D_1-AH-ALLOW-ANY + destination { + group { + address-group DT_FW8B21D_1 + } + } + protocol ah + } + rule 2381 { + action accept + description FW8B21D_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW8B21D_1 + } + port 8181,4500,1194,993,941,500,53 + } + protocol tcp_udp + } + rule 2382 { + action accept + description FW6863A_4-TCP-ALLOW-85.17.25.47 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 85.17.25.47 + } + } + rule 2383 { + action accept + description FW6863A_4-TCP-ALLOW-91.232.105.39 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 91.232.105.39 + } + } + rule 2384 { + action accept + description FW6863A_4-TCP-ALLOW-93.190.142.120 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 93.190.142.120 + } + } + rule 2385 { + action accept + description FW6863A_4-TCP-ALLOW-95.168.171.130 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 95.168.171.130 + } + } + rule 2386 { + action accept + description FW6863A_4-TCP-ALLOW-95.168.171.157 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 95.168.171.157 + } + } + rule 2387 { + action accept + description FWD4A27_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD4A27_1 + } + port 32400 + } + protocol tcp + } + rule 2388 { + action accept + description FW2ACFF_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2ACFF_1 + } + port 10299,60050-60055 + } + protocol tcp_udp + } + rule 2389 { + action accept + description FWCB0CF_7-TCP-ALLOW-193.248.62.45 + destination { + group { + address-group DT_FWCB0CF_7 + } + port 22 + } + protocol tcp + source { + address 193.248.62.45 + } + } + rule 2390 { + action accept + description FWCB0CF_7-TCP-ALLOW-78.249.208.17 + destination { + group { + address-group DT_FWCB0CF_7 + } + port 22 + } + protocol tcp + source { + address 78.249.208.17 + } + } + rule 2391 { + action accept + description FWC8E8E_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC8E8E_1 + } + port 6000 + } + protocol tcp_udp + } + rule 2392 { + action accept + description FW30D21_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW30D21_1 + } + port 2476 + } + protocol tcp + } + rule 2393 { + action accept + description FW0192C_1-TCP-ALLOW-41.140.242.94 + destination { + group { + address-group DT_FW0192C_1 + } + port 3306,22 + } + protocol tcp + source { + address 41.140.242.94 + } + } + rule 2394 { + action accept + description FW59F39_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW59F39_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2395 { + action accept + description FWEF92E_7-ESP-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_7 + } + } + protocol esp + source { + address 77.68.77.57 + } + } + rule 2396 { + action accept + description FW826BA_3-TCP-ALLOW-51.219.47.177 + destination { + group { + address-group DT_FW826BA_3 + } + port 3389,21 + } + protocol tcp + source { + address 51.219.47.177 + } + } + rule 2397 { + action accept + description FW826BA_3-TCP-ALLOW-86.172.128.50 + destination { + group { + address-group DT_FW826BA_3 + } + port 1433,21 + } + protocol tcp + source { + address 86.172.128.50 + } + } + rule 2398 { + action accept + description FW826BA_3-TCP-ALLOW-88.105.1.20 + destination { + group { + address-group DT_FW826BA_3 + } + port 21 + } + protocol tcp + source { + address 88.105.1.20 + } + } + rule 2399 { + action accept + description FW6863A_4-TCP-ALLOW-95.211.243.198 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 95.211.243.198 + } + } + rule 2400 { + action accept + description FW25843_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW25843_1 + } + port 9001,7070,5500,5488,5000,4500,4000,3500,3000,1883,1880 + } + protocol tcp + } + rule 2401 { + action accept + description FW89619_1-TCP_UDP-ALLOW-185.83.65.46 + destination { + group { + address-group DT_FW89619_1 + } + port 5060 + } + protocol tcp_udp + source { + address 185.83.65.46 + } + } + rule 2402 { + action accept + description FW5858F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW5858F_1 + } + port 1883 + } + protocol tcp + } + rule 2403 { + action accept + description FW826BA_3-TCP-ALLOW-95.147.108.173 + destination { + group { + address-group DT_FW826BA_3 + } + port 21 + } + protocol tcp + source { + address 95.147.108.173 + } + } + rule 2404 { + action accept + description FW9C682_3-TCP-ALLOW-52.56.193.88 + destination { + group { + address-group DT_FW9C682_3 + } + port 3306 + } + protocol tcp + source { + address 52.56.193.88 + } + } + rule 2405 { + action accept + description FW0745F_5-TCP-ALLOW-109.228.63.82 + destination { + group { + address-group DT_FW0745F_5 + } + port 5666 + } + protocol tcp + source { + address 109.228.63.82 + } + } + rule 2406 { + action accept + description FWC0CE0_1-TCP-ALLOW-90.255.228.213 + destination { + group { + address-group DT_FWC0CE0_1 + } + port 49152-65535,8443,21 + } + protocol tcp + source { + address 90.255.228.213 + } + } + rule 2407 { + action accept + description FW210E2_8-AH-ALLOW-ANY + destination { + group { + address-group DT_FW210E2_8 + } + } + protocol ah + } + rule 2408 { + action accept + description FW210E2_8-ESP-ALLOW-ANY + destination { + group { + address-group DT_FW210E2_8 + } + } + protocol esp + } + rule 2409 { + action accept + description FW210E2_8-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW210E2_8 + } + port 41,62000,23,4500,50,9876,3391,88,135 + } + protocol tcp + } + rule 2410 { + action accept + description FW210E2_8-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW210E2_8 + } + port 500 + } + protocol udp + } + rule 2411 { + action accept + description VPN-8625-ANY-ALLOW-10.4.54.103 + destination { + group { + address-group DT_VPN-8625 + } + } + source { + address 10.4.54.103 + } + } + rule 2412 { + action accept + description VPN-8625-ANY-ALLOW-10.4.55.104 + destination { + group { + address-group DT_VPN-8625 + } + } + source { + address 10.4.55.104 + } + } + rule 2413 { + action accept + description FW73A64_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW73A64_1 + } + port 61616,8181,8161,8082,4244,4243,4242,4241 + } + protocol tcp + } + rule 2414 { + action accept + description VPN-19135-ANY-ALLOW-10.4.86.165 + destination { + group { + address-group DT_VPN-19135 + } + } + source { + address 10.4.86.165 + } + } + rule 2415 { + action accept + description FWCB0CF_7-TCP-ALLOW-82.65.107.3 + destination { + group { + address-group DT_FWCB0CF_7 + } + port 22 + } + protocol tcp + source { + address 82.65.107.3 + } + } + rule 2416 { + action accept + description FWCB0CF_7-TCP-ALLOW-195.2.139.221 + destination { + group { + address-group DT_FWCB0CF_7 + } + port 5432-5434,3306-3308 + } + protocol tcp + source { + address 195.2.139.221 + } + } + rule 2417 { + action accept + description VPN-19135-ANY-ALLOW-10.4.87.165 + destination { + group { + address-group DT_VPN-19135 + } + } + source { + address 10.4.87.165 + } + } + rule 2418 { + action accept + description FW2BB8D_1-TCP-ALLOW-87.75.109.83 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 27017,5000 + } + protocol tcp + source { + address 87.75.109.83 + } + } + rule 2419 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.83 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.83 + } + } + rule 2420 { + action accept + description FW2ED4D_2-TCP-ALLOW-84.92.65.192 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 22 + } + protocol tcp + source { + address 84.92.65.192 + } + } + rule 2421 { + action accept + description FW73A64_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW73A64_1 + } + port 9200,5601,4247,4246,4245 + } + protocol tcp_udp + } + rule 2422 { + action accept + description FW4735F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4735F_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2423 { + action accept + description FW2ED4D_2-TCP-ALLOW-109.176.154.238 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 7990,3389 + } + protocol tcp + source { + address 109.176.154.238 + } + } + rule 2424 { + action accept + description FW6863A_4-TCP-ALLOW-95.211.243.206 + destination { + group { + address-group DT_FW6863A_4 + } + port 465 + } + protocol tcp + source { + address 95.211.243.206 + } + } + rule 2425 { + action accept + description FW89619_1-TCP_UDP-ALLOW-81.133.80.114 + destination { + group { + address-group DT_FW89619_1 + } + port 5060 + } + protocol tcp_udp + source { + address 81.133.80.114 + } + } + rule 2426 { + action accept + description FW89619_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW89619_1 + } + port 5090 + } + protocol tcp_udp + } + rule 2427 { + action accept + description FW8A57A_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW8A57A_1 + } + port 49155,49154,7700,53,43 + } + protocol tcp_udp + } + rule 2428 { + action accept + description FW8C72E_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW8C72E_1 + } + port 500,4500 + } + protocol udp + } + rule 2429 { + action accept + description FW2ED4D_2-TCP-ALLOW-18.135.66.162 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 18.135.66.162 + } + } + rule 2430 { + action accept + description FW2C5AE_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2C5AE_1 + } + port 58080,58008,8545,7175 + } + protocol tcp + } + rule 2431 { + action accept + description FW2ED4D_2-TCP-ALLOW-80.209.144.52 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 80.209.144.52 + } + } + rule 2432 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.153.21.103 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 7990,3389 + } + protocol tcp + source { + address 82.153.21.103 + } + } + rule 2433 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.41 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.41 + } + } + rule 2434 { + action accept + description FW0745F_5-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0745F_5 + } + port 32770,8001,7801 + } + protocol tcp + } + rule 2435 { + action accept + description FW85E02_11-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW85E02_11 + } + port 5090,5060 + } + protocol tcp_udp + } + rule 2436 { + action accept + description VPN-21982-ANY-ALLOW-10.4.58.43 + destination { + group { + address-group DT_VPN-21982 + } + } + source { + address 10.4.58.43 + } + } + rule 2437 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.17.52.191 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.17.52.191 + } + } + rule 2438 { + action accept + description FW66347_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW66347_1 + } + port 53 + } + protocol tcp_udp + } + rule 2439 { + action accept + description FW11082_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW11082_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2440 { + action accept + description VPN-21982-ANY-ALLOW-10.4.59.43 + destination { + group { + address-group DT_VPN-21982 + } + } + source { + address 10.4.59.43 + } + } + rule 2441 { + action accept + description FW2BB8D_1-TCP-ALLOW-92.207.193.203 + destination { + group { + address-group DT_FW2BB8D_1 + } + port 5000 + } + protocol tcp + source { + address 92.207.193.203 + } + } + rule 2442 { + action accept + description FWC2D30_1-TCP-ALLOW-77.99.253.161 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,22,21 + } + protocol tcp + source { + address 77.99.253.161 + } + } + rule 2443 { + action accept + description FW0E383_9-TCP-ALLOW-77.99.245.103 + destination { + group { + address-group DT_FW0E383_9 + } + port 3389 + } + protocol tcp + source { + address 77.99.245.103 + } + } + rule 2444 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.19.19.52 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 7990,3389 + } + protocol tcp + source { + address 82.19.19.52 + } + } + rule 2445 { + action accept + description FWEF92E_7-AH-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_7 + } + } + protocol ah + source { + address 77.68.77.57 + } + } + rule 2446 { + action accept + description VPN-16450-ANY-ALLOW-10.4.88.99 + destination { + group { + address-group DT_VPN-16450 + } + } + source { + address 10.4.88.99 + } + } + rule 2447 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.2.186.129 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.2.186.129 + } + } + rule 2448 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.157 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.215.157 + } + } + rule 2449 { + action accept + description FW8EA04_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW8EA04_1 + } + port 1194 + } + protocol udp + } + rule 2450 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.21.59.207 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.21.59.207 + } + } + rule 2451 { + action accept + description FWC2D30_1-TCP-ALLOW-82.9.22.158 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,21 + } + protocol tcp + source { + address 82.9.22.158 + } + } + rule 2452 { + action accept + description FWF3A1B_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF3A1B_1 + } + port 1981,53 + } + protocol tcp_udp + } + rule 2453 { + action accept + description FWEF92E_5-ESP-ALLOW-77.68.11.54 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 77.68.11.54 + } + } + rule 2454 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.40.177.186 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.40.177.186 + } + } + rule 2455 { + action accept + description FW0C25B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0C25B_1 + } + port 49152-65535,5224 + } + protocol tcp + } + rule 2456 { + action accept + description FW85A7C_1-TCP-ALLOW-82.24.242.137 + destination { + group { + address-group DT_FW85A7C_1 + } + port 22 + } + protocol tcp + source { + address 82.24.242.137 + } + } + rule 2457 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.68.25.66 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.68.25.66 + } + } + rule 2458 { + action accept + description FW826BA_3-TCP-ALLOW-51.89.148.173 + destination { + group { + address-group DT_FW826BA_3 + } + port 1433 + } + protocol tcp + source { + address 51.89.148.173 + } + } + rule 2459 { + action accept + description FWA69A0_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA69A0_1 + } + port 48402 + } + protocol udp + } + rule 2460 { + action accept + description FW2ED4D_2-TCP-ALLOW-82.69.79.85 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 82.69.79.85 + } + } + rule 2461 { + action accept + description FWEF92E_5-ESP-ALLOW-77.68.77.149 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 77.68.77.149 + } + } + rule 2462 { + action accept + description FWEF92E_6-ESP-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_6 + } + } + protocol esp + source { + address 77.68.77.57 + } + } + rule 2463 { + action accept + description FWEF92E_7-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FWEF92E_7 + } + port 3389,445 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2464 { + action accept + description FW49C3D_4-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FW49C3D_4 + } + port 3389,445,443,80 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2465 { + action accept + description FW49C3D_6-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FW49C3D_6 + } + port 3389,445 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2466 { + action accept + description FW34C91_3-TCP-ALLOW-77.68.121.4 + destination { + group { + address-group DT_FW34C91_3 + } + port 1433 + } + protocol tcp + source { + address 77.68.121.4 + } + } + rule 2467 { + action accept + description VPN-16450-ANY-ALLOW-10.4.89.99 + destination { + group { + address-group DT_VPN-16450 + } + } + source { + address 10.4.89.99 + } + } + rule 2468 { + action accept + description FW0BB22_1-AH-ALLOW-ANY + destination { + group { + address-group DT_FW0BB22_1 + } + } + protocol ah + } + rule 2469 { + action accept + description FW2ED4D_2-TCP-ALLOW-86.139.57.116 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 86.139.57.116 + } + } + rule 2470 { + action accept + description FW9E550_1-TCP-ALLOW-86.142.67.13 + destination { + group { + address-group DT_FW9E550_1 + } + port 3389 + } + protocol tcp + source { + address 86.142.67.13 + } + } + rule 2471 { + action accept + description FW8B21D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW8B21D_1 + } + port 2096,2095,2087,2086,2083,2082 + } + protocol tcp + } + rule 2472 { + action accept + description FW050AC_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW050AC_1 + } + port 2087 + } + protocol tcp + } + rule 2473 { + action accept + description FW1FA9E_1-TCP-ALLOW-109.228.50.206 + destination { + group { + address-group DT_FW1FA9E_1 + } + port 5432 + } + protocol tcp + source { + address 109.228.50.206 + } + } + rule 2474 { + action accept + description FW8A3FC_3-TCP-ALLOW-217.23.11.155 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 217.23.11.155 + } + } + rule 2475 { + action accept + description FW2ED4D_2-TCP-ALLOW-88.96.110.198 + destination { + group { + address-group DT_FW2ED4D_2 + } + port 3389 + } + protocol tcp + source { + address 88.96.110.198 + } + } + rule 2476 { + action accept + description FWEAE53_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWEAE53_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2477 { + action accept + description VPN-19474-ANY-ALLOW-10.4.88.161 + destination { + group { + address-group DT_VPN-19474 + } + } + source { + address 10.4.88.161 + } + } + rule 2478 { + action accept + description VPN-19474-ANY-ALLOW-10.4.89.161 + destination { + group { + address-group DT_VPN-19474 + } + } + source { + address 10.4.89.161 + } + } + rule 2479 { + action accept + description FW90AE3_1-TCP-ALLOW-68.33.220.233 + destination { + group { + address-group DT_FW90AE3_1 + } + port 22 + } + protocol tcp + source { + address 68.33.220.233 + } + } + rule 2480 { + action accept + description FWC2D30_1-TCP-ALLOW-86.10.163.127 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,21 + } + protocol tcp + source { + address 86.10.163.127 + } + } + rule 2481 { + action accept + description FW2FB61_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2FB61_1 + } + port 60182 + } + protocol udp + } + rule 2482 { + action accept + description FW85A7C_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW85A7C_1 + } + port 2457,2456 + } + protocol tcp_udp + } + rule 2483 { + action accept + description FWBED52_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBED52_1 + } + port 1221,9000 + } + protocol tcp + } + rule 2484 { + action accept + description FWA86ED_101-TCP-ALLOW-90.250.2.109 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 90.250.2.109 + } + } + rule 2485 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.49 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.213.49 + } + } + rule 2486 { + action accept + description FWEF92E_5-ESP-ALLOW-77.68.77.70 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 77.68.77.70 + } + } + rule 2487 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.250 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.250 + } + } + rule 2488 { + action accept + description FW8A3FC_3-TCP-ALLOW-95.168.171.131 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 95.168.171.131 + } + } + rule 2489 { + action accept + description FW2379F_14-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2379F_14 + } + port 48030,10997,10993,10992,10991,10902,1723,1701 + } + protocol tcp + } + rule 2490 { + action accept + description FW8C927_1-TCP-ALLOW-84.92.125.78 + destination { + group { + address-group DT_FW8C927_1 + } + port 80 + } + protocol tcp + source { + address 84.92.125.78 + } + } + rule 2491 { + action accept + description FWC2D30_1-TCP-ALLOW-86.146.220.229 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,21 + } + protocol tcp + source { + address 86.146.220.229 + } + } + rule 2492 { + action accept + description FW2B279_4-TCP-ALLOW-2.218.5.59 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,22 + } + protocol tcp + source { + address 2.218.5.59 + } + } + rule 2493 { + action accept + description VPN-18830-ANY-ALLOW-10.4.86.156 + destination { + group { + address-group DT_VPN-18830 + } + } + source { + address 10.4.86.156 + } + } + rule 2494 { + action accept + description VPN-18830-ANY-ALLOW-10.4.87.156 + destination { + group { + address-group DT_VPN-18830 + } + } + source { + address 10.4.87.156 + } + } + rule 2495 { + action accept + description FWEF92E_5-ESP-ALLOW-77.68.92.33 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 77.68.92.33 + } + } + rule 2496 { + action accept + description FWA86ED_101-TCP-ALLOW-146.198.100.105 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 146.198.100.105 + } + } + rule 2497 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.55 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.211.55 + } + } + rule 2498 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.84.113 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 123.231.84.113 + } + } + rule 2499 { + action accept + description FW8C72E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW8C72E_1 + } + port 60134,60135 + } + protocol tcp + } + rule 2500 { + action accept + description FWAB44B_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWAB44B_1 + } + port 3306 + } + protocol tcp_udp + } + rule 2501 { + action accept + description FW2379F_14-TCP-ALLOW-51.148.87.29 + destination { + group { + address-group DT_FW2379F_14 + } + port 3389,21 + } + protocol tcp + source { + address 51.148.87.29 + } + } + rule 2502 { + action accept + description VPN-23738-ANY-ALLOW-10.4.56.13 + destination { + group { + address-group DT_VPN-23738 + } + } + source { + address 10.4.56.13 + } + } + rule 2503 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.100 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.210.100 + } + } + rule 2504 { + action accept + description FW996B4_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW996B4_2 + } + port 43595,30160 + } + protocol tcp + } + rule 2505 { + action accept + description FW8871B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW8871B_1 + } + port 15672,8083,8082,8081,5672 + } + protocol tcp + } + rule 2506 { + action accept + description FWAB44B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWAB44B_1 + } + port 9090,8069,5432 + } + protocol tcp + } + rule 2507 { + action accept + description FW6187E_1-ICMP-ALLOW-85.214.201.250 + destination { + group { + address-group DT_FW6187E_1 + } + } + protocol icmp + source { + address 85.214.201.250 + } + } + rule 2508 { + action accept + description FW8A3FC_3-TCP-ALLOW-217.23.11.126 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 217.23.11.126 + } + } + rule 2509 { + action accept + description FW78137_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW78137_1 + } + port 1-65535 + } + protocol tcp + } + rule 2510 { + action accept + description FW32EFF_25-TCP-ALLOW-46.252.65.10 + destination { + group { + address-group DT_FW32EFF_25 + } + port 443 + } + protocol tcp + source { + address 46.252.65.10 + } + } + rule 2511 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.50 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.50 + } + } + rule 2512 { + action accept + description FW6A684_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6A684_1 + } + port 53 + } + protocol tcp_udp + } + rule 2513 { + action accept + description FWF48EB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF48EB_1 + } + port 9204,9202,3395 + } + protocol tcp + } + rule 2514 { + action accept + description FW44217_2-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW44217_2 + } + port 443,80 + } + protocol tcp_udp + } + rule 2515 { + action accept + description FW6187E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6187E_1 + } + port 2282 + } + protocol tcp + } + rule 2516 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.0.58 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.0.58 + } + } + rule 2517 { + action accept + description VPN-34501-ANY-ALLOW-10.4.86.235 + destination { + group { + address-group DT_VPN-34501 + } + } + source { + address 10.4.86.235 + } + } + rule 2518 { + action accept + description FW1271A_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1271A_2 + } + port 5090,5061,5060,5015,5001 + } + protocol tcp + } + rule 2519 { + action accept + description FW1271A_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW1271A_2 + } + port 9000-10999,5090,5060 + } + protocol udp + } + rule 2520 { + action accept + description FW1226C_3-TCP-ALLOW-216.113.160.71 + destination { + group { + address-group DT_FW1226C_3 + } + port 80,22 + } + protocol tcp + source { + address 216.113.160.71 + } + } + rule 2521 { + action accept + description FW32EFF_16-TCP-ALLOW-84.19.45.82 + destination { + group { + address-group DT_FW32EFF_16 + } + port 33888 + } + protocol tcp + source { + address 84.19.45.82 + } + } + rule 2522 { + action accept + description FW03F2E_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW03F2E_1 + } + port 1194 + } + protocol udp + } + rule 2523 { + action accept + description FW03F2E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW03F2E_1 + } + port 4432,4431,4430 + } + protocol tcp + } + rule 2524 { + action accept + description FW1226C_3-TCP-ALLOW-216.113.162.65 + destination { + group { + address-group DT_FW1226C_3 + } + port 80,22 + } + protocol tcp + source { + address 216.113.162.65 + } + } + rule 2525 { + action accept + description VPN-20306-ANY-ALLOW-10.4.89.173 + destination { + group { + address-group DT_VPN-20306 + } + } + source { + address 10.4.89.173 + } + } + rule 2526 { + action accept + description FW8A49A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW8A49A_1 + } + port 2525,8448-65535 + } + protocol tcp + } + rule 2527 { + action accept + description FWD3431_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD3431_2 + } + port 43595,30377,30289 + } + protocol tcp + } + rule 2528 { + action accept + description FW1226C_3-TCP-ALLOW-66.135.200.200 + destination { + group { + address-group DT_FW1226C_3 + } + port 80,22 + } + protocol tcp + source { + address 66.135.200.200 + } + } + rule 2529 { + action accept + description FW1226C_3-TCP-ALLOW-193.28.178.38 + destination { + group { + address-group DT_FW1226C_3 + } + port 80 + } + protocol tcp + source { + address 193.28.178.38 + } + } + rule 2530 { + action accept + description FWAE88B_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWAE88B_1 + } + port 65432,8080,7300,1195,1194,993,587,465,443,442,143,110,80,53,22 + } + protocol tcp_udp + } + rule 2531 { + action accept + description FW1226C_3-TCP-ALLOW-195.234.136.80 + destination { + group { + address-group DT_FW1226C_3 + } + port 80 + } + protocol tcp + source { + address 195.234.136.80 + } + } + rule 2532 { + action accept + description FW1226C_3-TCP-ALLOW-93.94.41.83 + destination { + group { + address-group DT_FW1226C_3 + } + port 80 + } + protocol tcp + source { + address 93.94.41.83 + } + } + rule 2533 { + action accept + description VPN-6103-ANY-ALLOW-10.4.56.102 + destination { + group { + address-group DT_VPN-6103 + } + } + source { + address 10.4.56.102 + } + } + rule 2534 { + action accept + description VPN-6103-ANY-ALLOW-10.4.57.102 + destination { + group { + address-group DT_VPN-6103 + } + } + source { + address 10.4.57.102 + } + } + rule 2535 { + action accept + description FW9E550_1-TCP-ALLOW-86.198.190.104 + destination { + group { + address-group DT_FW9E550_1 + } + port 3389 + } + protocol tcp + source { + address 86.198.190.104 + } + } + rule 2536 { + action accept + description FW34C91_3-TCP-ALLOW-81.149.71.244 + destination { + group { + address-group DT_FW34C91_3 + } + port 1433 + } + protocol tcp + source { + address 81.149.71.244 + } + } + rule 2537 { + action accept + description FW0BB22_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0BB22_1 + } + port 27917,27017,9592,9092,1080,587 + } + protocol tcp_udp + } + rule 2538 { + action accept + description FWC2D30_1-TCP-ALLOW-89.213.26.156 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,21 + } + protocol tcp + source { + address 89.213.26.156 + } + } + rule 2539 { + action accept + description FW34C91_3-UDP-ALLOW-81.149.71.244 + destination { + group { + address-group DT_FW34C91_3 + } + port 1434 + } + protocol udp + source { + address 81.149.71.244 + } + } + rule 2540 { + action accept + description VPN-17207-ANY-ALLOW-10.4.86.121 + destination { + group { + address-group DT_VPN-17207 + } + } + source { + address 10.4.86.121 + } + } + rule 2541 { + action accept + description FW0B352_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0B352_1 + } + port 4500,500 + } + protocol udp + } + rule 2542 { + action accept + description FW85E02_11-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW85E02_11 + } + port 5854,5853,5061 + } + protocol tcp + } + rule 2543 { + action accept + description FW0BB22_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0BB22_1 + } + port 9200,8082 + } + protocol tcp + } + rule 2544 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.140 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.140 + } + } + rule 2545 { + action accept + description FWC2D30_1-TCP-ALLOW-91.125.244.28 + destination { + group { + address-group DT_FWC2D30_1 + } + port 21 + } + protocol tcp + source { + address 91.125.244.28 + } + } + rule 2546 { + action accept + description FWA86ED_101-TCP-ALLOW-86.172.252.221 + destination { + group { + address-group DT_FWA86ED_101 + } + port 80-3389 + } + protocol tcp + source { + address 86.172.252.221 + } + } + rule 2547 { + action accept + description FWC2D30_1-TCP-ALLOW-92.207.184.106 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,21 + } + protocol tcp + source { + address 92.207.184.106 + } + } + rule 2548 { + action accept + description FW45F3D_1-ANY-ALLOW-146.255.0.198 + destination { + group { + address-group DT_FW45F3D_1 + } + } + source { + address 146.255.0.198 + } + } + rule 2549 { + action accept + description FWBFDED_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBFDED_1 + } + port 1723,445 + } + protocol tcp + } + rule 2550 { + action accept + description FW8A3FC_3-TCP-ALLOW-212.227.9.72 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 212.227.9.72 + } + } + rule 2551 { + action accept + description FWE928F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE928F_1 + } + port 2082,2083,2086,2087,2096 + } + protocol tcp + } + rule 2552 { + action accept + description FW5CBB2_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW5CBB2_1 + } + port 2082,2083,2086,2087 + } + protocol tcp + } + rule 2553 { + action accept + description FW63230_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW63230_1 + } + port 445,139 + } + protocol tcp_udp + } + rule 2554 { + action accept + description FW90AE3_1-TCP-ALLOW-71.244.176.5 + destination { + group { + address-group DT_FW90AE3_1 + } + port 22 + } + protocol tcp + source { + address 71.244.176.5 + } + } + rule 2555 { + action accept + description FWA4BC8_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA4BC8_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2556 { + action accept + description VPN-17207-ANY-ALLOW-10.4.87.121 + destination { + group { + address-group DT_VPN-17207 + } + } + source { + address 10.4.87.121 + } + } + rule 2557 { + action accept + description VPN-17558-ANY-ALLOW-10.4.86.143 + destination { + group { + address-group DT_VPN-17558 + } + } + source { + address 10.4.86.143 + } + } + rule 2558 { + action accept + description FWB2CD2_1-TCP-ALLOW-86.167.68.241 + destination { + group { + address-group DT_FWB2CD2_1 + } + port 21 + } + protocol tcp + source { + address 86.167.68.241 + } + } + rule 2559 { + action accept + description FW32EFF_25-TCP-ALLOW-84.19.45.82 + destination { + group { + address-group DT_FW32EFF_25 + } + port 33888,443 + } + protocol tcp + source { + address 84.19.45.82 + } + } + rule 2560 { + action accept + description FW44217_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW44217_2 + } + port 9001,7946,2376 + } + protocol tcp + } + rule 2561 { + action accept + description FW7DAE2_3-TCP-ALLOW-212.227.253.11 + destination { + group { + address-group DT_FW7DAE2_3 + } + port 25,22 + } + protocol tcp + source { + address 212.227.253.11 + } + } + rule 2562 { + action accept + description FW7DAE2_3-TCP-ALLOW-217.160.126.118 + destination { + group { + address-group DT_FW7DAE2_3 + } + port 25,22 + } + protocol tcp + source { + address 217.160.126.118 + } + } + rule 2563 { + action accept + description FWAF6E8_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWAF6E8_1 + } + port 2082,2083,2086,2087,2096 + } + protocol tcp + } + rule 2564 { + action accept + description FWCD7CE_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWCD7CE_1 + } + port 49152-65534 + } + protocol tcp + } + rule 2565 { + action accept + description FW32EFF_16-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW32EFF_16 + } + port 47779,47778,47777,47776 + } + protocol tcp + } + rule 2566 { + action accept + description FW0745F_5-TCP-ALLOW-77.68.117.222 + destination { + group { + address-group DT_FW0745F_5 + } + port 49170 + } + protocol tcp + source { + address 77.68.117.222 + } + } + rule 2567 { + action accept + description FWC2D30_1-TCP-ALLOW-92.207.199.107 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,22,21 + } + protocol tcp + source { + address 92.207.199.107 + } + } + rule 2568 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.0.89 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.0.89 + } + } + rule 2569 { + action accept + description FW8A3FC_3-TCP-ALLOW-190.2.130.41 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 190.2.130.41 + } + } + rule 2570 { + action accept + description FWFDCC7_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWFDCC7_1 + } + port 10000 + } + protocol tcp_udp + } + rule 2571 { + action accept + description FWF19FB_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF19FB_2 + } + port 43595,40001,30616-30631,30531,30204-30435 + } + protocol tcp + } + rule 2572 { + action accept + description FW2B279_4-TCP-ALLOW-213.171.217.107 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,22 + } + protocol tcp + source { + address 213.171.217.107 + } + } + rule 2573 { + action accept + description FW4E314_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4E314_1 + } + port 21543,888 + } + protocol tcp + } + rule 2574 { + action accept + description FW73215_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW73215_1 + } + port 4380 + } + protocol udp + } + rule 2575 { + action accept + description VPN-31301-ANY-ALLOW-10.4.86.223 + destination { + group { + address-group DT_VPN-31301 + } + } + source { + address 10.4.86.223 + } + } + rule 2576 { + action accept + description FW8428B_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW8428B_1 + } + port 48402 + } + protocol udp + } + rule 2577 { + action accept + description FWF3A1B_1-TCP_UDP-ALLOW-185.195.124.169 + destination { + group { + address-group DT_FWF3A1B_1 + } + port 2222 + } + protocol tcp_udp + source { + address 185.195.124.169 + } + } + rule 2578 { + action accept + description FW34C91_3-UDP-ALLOW-77.68.121.4 + destination { + group { + address-group DT_FW34C91_3 + } + port 1434 + } + protocol udp + source { + address 77.68.121.4 + } + } + rule 2579 { + action accept + description FW73215_1-TCP-ALLOW-82.38.58.135 + destination { + group { + address-group DT_FW73215_1 + } + port 10685 + } + protocol tcp + source { + address 82.38.58.135 + } + } + rule 2580 { + action accept + description FW52F6F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW52F6F_1 + } + port 8888 + } + protocol tcp + } + rule 2581 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.86 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.86 + } + } + rule 2582 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.125.13 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.125.13 + } + } + rule 2583 { + action accept + description FWEE03C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWEE03C_1 + } + port 2087,2083 + } + protocol tcp + } + rule 2584 { + action accept + description FW748B7_1-TCP-ALLOW-157.231.123.154 + destination { + group { + address-group DT_FW748B7_1 + } + port 22 + } + protocol tcp + source { + address 157.231.123.154 + } + } + rule 2585 { + action accept + description VPN-34501-ANY-ALLOW-10.4.87.235 + destination { + group { + address-group DT_VPN-34501 + } + } + source { + address 10.4.87.235 + } + } + rule 2586 { + action accept + description FWE47DA_1-TCP-ALLOW-81.134.85.245 + destination { + group { + address-group DT_FWE47DA_1 + } + port 22 + } + protocol tcp + source { + address 81.134.85.245 + } + } + rule 2587 { + action accept + description FWD61BF_1-ANY-ALLOW-193.237.81.213_32 + destination { + group { + address-group DT_FWD61BF_1 + } + } + source { + address 193.237.81.213/32 + } + } + rule 2588 { + action accept + description FW2B279_4-TCP-ALLOW-23.106.238.241 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,3306,22 + } + protocol tcp + source { + address 23.106.238.241 + } + } + rule 2589 { + action accept + description FW2B279_4-TCP-ALLOW-35.204.202.196 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,3306,22 + } + protocol tcp + source { + address 35.204.202.196 + } + } + rule 2590 { + action accept + description FW2B279_4-TCP-ALLOW-35.242.141.128 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,3306,22 + } + protocol tcp + source { + address 35.242.141.128 + } + } + rule 2591 { + action accept + description FWC2EF2_2-TCP-ALLOW-90.251.221.19 + destination { + group { + address-group DT_FWC2EF2_2 + } + port 995,993,587,465,143,110,25,22 + } + protocol tcp + source { + address 90.251.221.19 + } + } + rule 2592 { + action accept + description VPN-14673-ANY-ALLOW-10.4.88.44 + destination { + group { + address-group DT_VPN-14673 + } + } + source { + address 10.4.88.44 + } + } + rule 2593 { + action accept + description FWA83DF_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA83DF_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2594 { + action accept + description FW31525_6-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW31525_6 + } + port 35467 + } + protocol tcp + } + rule 2595 { + action accept + description FW4293B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4293B_1 + } + port 9080,8888,8881,7815,8419 + } + protocol tcp + } + rule 2596 { + action accept + description FW4AE7D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4AE7D_1 + } + port 8083,81 + } + protocol tcp + } + rule 2597 { + action accept + description FWC2D30_1-TCP-ALLOW-143.52.53.22 + destination { + group { + address-group DT_FWC2D30_1 + } + port 22 + } + protocol tcp + source { + address 143.52.53.22 + } + } + rule 2598 { + action accept + description FW44217_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW44217_2 + } + port 7946,4789 + } + protocol udp + } + rule 2599 { + action accept + description FW2B279_4-TCP-ALLOW-46.249.82.162 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,22 + } + protocol tcp + source { + address 46.249.82.162 + } + } + rule 2600 { + action accept + description FW27949_2-TCP-ALLOW-80.95.202.106 + destination { + group { + address-group DT_FW27949_2 + } + port 443,80 + } + protocol tcp + source { + address 80.95.202.106 + } + } + rule 2601 { + action accept + description FWEF92E_5-ESP-ALLOW-77.68.93.82 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 77.68.93.82 + } + } + rule 2602 { + action accept + description FW2ACFF_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2ACFF_1 + } + port 8082,5093 + } + protocol tcp + } + rule 2603 { + action accept + description FWC2EF2_2-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC2EF2_2 + } + port 10000,953,53 + } + protocol tcp_udp + } + rule 2604 { + action accept + description FW0C8E1_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0C8E1_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2605 { + action accept + description FWA86ED_101-TCP_UDP-ALLOW-82.5.189.5 + destination { + group { + address-group DT_FWA86ED_101 + } + port 1-65535 + } + protocol tcp_udp + source { + address 82.5.189.5 + } + } + rule 2606 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.179 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.179 + } + } + rule 2607 { + action accept + description FWEF92E_5-ESP-ALLOW-88.208.198.93 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol esp + source { + address 88.208.198.93 + } + } + rule 2608 { + action accept + description FW5658C_1-TCP-ALLOW-39.45.43.109 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 39.45.43.109 + } + } + rule 2609 { + action accept + description FW5658C_1-TCP-ALLOW-5.67.3.195 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 5.67.3.195 + } + } + rule 2610 { + action accept + description FWDCA36_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDCA36_3 + } + port 49152-65534,5901 + } + protocol tcp + } + rule 2611 { + action accept + description FWE928F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWE928F_1 + } + port 53 + } + protocol tcp_udp + } + rule 2612 { + action accept + description FW69D6D_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW69D6D_2 + } + port 5001,5090,5060,5015 + } + protocol tcp + } + rule 2613 { + action accept + description FW69D6D_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW69D6D_2 + } + port 5090,5060,9000-9500 + } + protocol udp + } + rule 2614 { + action accept + description VPN-9765-ANY-ALLOW-10.4.56.45 + destination { + group { + address-group DT_VPN-9765 + } + } + source { + address 10.4.56.45 + } + } + rule 2615 { + action accept + description VPN-9765-ANY-ALLOW-10.4.57.45 + destination { + group { + address-group DT_VPN-9765 + } + } + source { + address 10.4.57.45 + } + } + rule 2616 { + action accept + description FW4C136_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW4C136_1 + } + port 1194 + } + protocol tcp_udp + } + rule 2617 { + action accept + description FW6F539_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6F539_1 + } + port 49152-65534 + } + protocol tcp + } + rule 2618 { + action accept + description FWDD089_5-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWDD089_5 + } + port 5666-5667,12489 + } + protocol tcp_udp + } + rule 2619 { + action accept + description FWDD089_5-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDD089_5 + } + port 161-162 + } + protocol tcp + } + rule 2620 { + action accept + description FWEF92E_5-AH-ALLOW-109.228.37.19 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 109.228.37.19 + } + } + rule 2621 { + action accept + description FW0A5C4_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0A5C4_1 + } + port 9000,6697,6667,5000 + } + protocol tcp + } + rule 2622 { + action accept + description FWEF92E_5-AH-ALLOW-77.68.11.54 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 77.68.11.54 + } + } + rule 2623 { + action accept + description FW2BB8D_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2BB8D_1 + } + port 7990 + } + protocol tcp + } + rule 2624 { + action accept + description FWAF6E8_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWAF6E8_1 + } + port 7770-7800,44445,53 + } + protocol tcp_udp + } + rule 2625 { + action accept + description FW81286_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW81286_1 + } + port 2082,2083,2086,2087,2096 + } + protocol tcp + } + rule 2626 { + action accept + description FW05064_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW05064_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2627 { + action accept + description FWD7382_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWD7382_1 + } + port 4500,1701,500 + } + protocol udp + } + rule 2628 { + action accept + description FWD7382_1-TCP-ALLOW-174.91.7.198 + destination { + group { + address-group DT_FWD7382_1 + } + port 3389 + } + protocol tcp + source { + address 174.91.7.198 + } + } + rule 2629 { + action accept + description VPN-9484-ANY-ALLOW-10.4.56.164 + destination { + group { + address-group DT_VPN-9484 + } + } + source { + address 10.4.56.164 + } + } + rule 2630 { + action accept + description VPN-9484-ANY-ALLOW-10.4.57.164 + destination { + group { + address-group DT_VPN-9484 + } + } + source { + address 10.4.57.164 + } + } + rule 2631 { + action accept + description VPN-9749-ANY-ALLOW-10.4.58.144 + destination { + group { + address-group DT_VPN-9749 + } + } + source { + address 10.4.58.144 + } + } + rule 2632 { + action accept + description FWEF92E_5-AH-ALLOW-77.68.77.149 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 77.68.77.149 + } + } + rule 2633 { + action accept + description FW10FEE_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW10FEE_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2634 { + action accept + description FW5658C_1-TCP-ALLOW-5.71.30.141 + destination { + group { + address-group DT_FW5658C_1 + } + port 8443 + } + protocol tcp + source { + address 5.71.30.141 + } + } + rule 2635 { + action accept + description VPN-9749-ANY-ALLOW-10.4.59.144 + destination { + group { + address-group DT_VPN-9749 + } + } + source { + address 10.4.59.144 + } + } + rule 2636 { + action accept + description FWEF92E_5-AH-ALLOW-77.68.77.70 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 77.68.77.70 + } + } + rule 2637 { + action accept + description FWEF92E_5-AH-ALLOW-77.68.92.33 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 77.68.92.33 + } + } + rule 2638 { + action accept + description FWEF92E_5-AH-ALLOW-77.68.93.82 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 77.68.93.82 + } + } + rule 2639 { + action accept + description FWEF92E_6-AH-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_6 + } + } + protocol ah + source { + address 77.68.77.57 + } + } + rule 2640 { + action accept + description FWEF92E_6-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FWEF92E_6 + } + port 3389,445 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2641 { + action accept + description FWEF92E_5-AH-ALLOW-88.208.198.93 + destination { + group { + address-group DT_FWEF92E_5 + } + } + protocol ah + source { + address 88.208.198.93 + } + } + rule 2642 { + action accept + description FWEF92E_7-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FWEF92E_7 + } + port 3389,445 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 2643 { + action accept + description FWEF92E_7-TCP-ALLOW-87.224.6.174 + destination { + group { + address-group DT_FWEF92E_7 + } + port 3389,445 + } + protocol tcp + source { + address 87.224.6.174 + } + } + rule 2644 { + action accept + description FWEF92E_5-TCP-ALLOW-109.228.37.19 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 109.228.37.19 + } + } + rule 2645 { + action accept + description FW49C3D_4-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FW49C3D_4 + } + port 3389,445,80 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 2646 { + action accept + description FW49C3D_4-TCP-ALLOW-82.0.198.226 + destination { + group { + address-group DT_FW49C3D_4 + } + port 3389,445 + } + protocol tcp + source { + address 82.0.198.226 + } + } + rule 2647 { + action accept + description FW49C3D_6-TCP-ALLOW-82.0.198.226 + destination { + group { + address-group DT_FW49C3D_6 + } + port 3389,445 + } + protocol tcp + source { + address 82.0.198.226 + } + } + rule 2648 { + action accept + description FW49C3D_6-TCP-ALLOW-83.100.136.74 + destination { + group { + address-group DT_FW49C3D_6 + } + port 3389,445 + } + protocol tcp + source { + address 83.100.136.74 + } + } + rule 2649 { + action accept + description FWEF92E_6-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FWEF92E_6 + } + port 3389,445 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 2650 { + action accept + description FWEF92E_5-TCP-ALLOW-194.145.189.162 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 194.145.189.162 + } + } + rule 2651 { + action accept + description FW3DBF8_9-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW3DBF8_9 + } + port 9000-10999 + } + protocol udp + } + rule 2652 { + action accept + description VPN-19807-ANY-ALLOW-10.4.86.172 + destination { + group { + address-group DT_VPN-19807 + } + } + source { + address 10.4.86.172 + } + } + rule 2653 { + action accept + description FWEEC75_1-TCP-ALLOW-82.8.245.40 + destination { + group { + address-group DT_FWEEC75_1 + } + port 21 + } + protocol tcp + source { + address 82.8.245.40 + } + } + rule 2654 { + action accept + description FW3AD6F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW3AD6F_1 + } + port 53,465 + } + protocol tcp_udp + } + rule 2655 { + action accept + description FWCDBC7_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWCDBC7_1 + } + port 53 + } + protocol tcp_udp + } + rule 2656 { + action accept + description FWA373F_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA373F_1 + } + port 2087,2086,2083,2082 + } + protocol tcp + } + rule 2657 { + action accept + description FW2B279_4-TCP-ALLOW-94.155.221.50 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443,22 + } + protocol tcp + source { + address 94.155.221.50 + } + } + rule 2658 { + action accept + description FWC2D30_1-TCP-ALLOW-213.171.217.107 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443,22 + } + protocol tcp + source { + address 213.171.217.107 + } + } + rule 2659 { + action accept + description VPN-30791-ANY-ALLOW-10.4.88.215 + destination { + group { + address-group DT_VPN-30791 + } + } + source { + address 10.4.88.215 + } + } + rule 2660 { + action accept + description VPN-30791-ANY-ALLOW-10.4.89.215 + destination { + group { + address-group DT_VPN-30791 + } + } + source { + address 10.4.89.215 + } + } + rule 2661 { + action accept + description FW2EF2C_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2EF2C_1 + } + port 10000,3478 + } + protocol udp + } + rule 2662 { + action accept + description FW32EFF_49-TCP-ALLOW-195.217.232.0_26 + destination { + group { + address-group DT_FW32EFF_49 + } + port 5589 + } + protocol tcp + source { + address 195.217.232.0/26 + } + } + rule 2663 { + action accept + description FW4AE7D_1-TCP-ALLOW-81.136.8.24 + destination { + group { + address-group DT_FW4AE7D_1 + } + port 3389 + } + protocol tcp + source { + address 81.136.8.24 + } + } + rule 2664 { + action accept + description FW2EF2C_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2EF2C_1 + } + port 5222 + } + protocol tcp_udp + } + rule 2665 { + action accept + description FW48A55_2-TCP-ALLOW-86.29.225.60 + destination { + group { + address-group DT_FW48A55_2 + } + port 443,80,22 + } + protocol tcp + source { + address 86.29.225.60 + } + } + rule 2666 { + action accept + description FW48A55_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW48A55_2 + } + port 1337 + } + protocol udp + } + rule 2667 { + action accept + description VPN-11913-ANY-ALLOW-10.4.56.191 + destination { + group { + address-group DT_VPN-11913 + } + } + source { + address 10.4.56.191 + } + } + rule 2668 { + action accept + description FWEF92E_5-TCP-ALLOW-194.145.189.163 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 194.145.189.163 + } + } + rule 2669 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.0.90 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.0.90 + } + } + rule 2670 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.24.66 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.24.66 + } + } + rule 2671 { + action accept + description VPN-11913-ANY-ALLOW-10.4.57.191 + destination { + group { + address-group DT_VPN-11913 + } + } + source { + address 10.4.57.191 + } + } + rule 2672 { + action accept + description FW73573_2-TCP-ALLOW-86.9.185.195 + destination { + group { + address-group DT_FW73573_2 + } + port 22 + } + protocol tcp + source { + address 86.9.185.195 + } + } + rule 2673 { + action accept + description VPN-17558-ANY-ALLOW-10.4.87.143 + destination { + group { + address-group DT_VPN-17558 + } + } + source { + address 10.4.87.143 + } + } + rule 2674 { + action accept + description FW748B7_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW748B7_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2675 { + action accept + description FW16375_5-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW16375_5 + } + port 2082,2083,2086,2087 + } + protocol tcp + } + rule 2676 { + action accept + description FW5A77C_16-TCP-ALLOW-88.98.204.68 + destination { + group { + address-group DT_FW5A77C_16 + } + port 22 + } + protocol tcp + source { + address 88.98.204.68 + } + } + rule 2677 { + action accept + description FW73573_1-TCP-ALLOW-86.9.185.195 + destination { + group { + address-group DT_FW73573_1 + } + port 22 + } + protocol tcp + source { + address 86.9.185.195 + } + } + rule 2678 { + action accept + description FWEF92E_5-TCP-ALLOW-194.145.190.4 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 194.145.190.4 + } + } + rule 2679 { + action accept + description FWC2D30_1-TCP-ALLOW-140.82.112.0_20 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 140.82.112.0/20 + } + } + rule 2680 { + action accept + description FW62858_12-ICMP-ALLOW-77.68.122.41 + destination { + group { + address-group DT_FW62858_12 + } + } + protocol icmp + source { + address 77.68.122.41 + } + } + rule 2681 { + action accept + description FWB118A_1-TCP-ALLOW-147.148.96.136 + destination { + group { + address-group DT_FWB118A_1 + } + port 49152-65534,8447,8443,22,21,20 + } + protocol tcp + source { + address 147.148.96.136 + } + } + rule 2682 { + action accept + description FW5A77C_16-TCP-ALLOW-92.207.237.42 + destination { + group { + address-group DT_FW5A77C_16 + } + port 10000,22 + } + protocol tcp + source { + address 92.207.237.42 + } + } + rule 2683 { + action accept + description FW364CF_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW364CF_1 + } + port 4022,8099 + } + protocol tcp + } + rule 2684 { + action accept + description VPN-25822-ANY-ALLOW-10.4.54.42 + destination { + group { + address-group DT_VPN-25822 + } + } + source { + address 10.4.54.42 + } + } + rule 2685 { + action accept + description FW7F28A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW7F28A_1 + } + port 10051,10050 + } + protocol tcp + } + rule 2686 { + action accept + description FW8AFF1_7-TCP-ALLOW-109.228.53.159 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 109.228.53.159 + } + } + rule 2687 { + action accept + description FWE47DA_1-TCP-ALLOW-185.22.211.0_24 + destination { + group { + address-group DT_FWE47DA_1 + } + port 22 + } + protocol tcp + source { + address 185.22.211.0/24 + } + } + rule 2688 { + action accept + description FWC6301_1-TCP-ALLOW-95.34.208.4 + destination { + group { + address-group DT_FWC6301_1 + } + port 22 + } + protocol tcp + source { + address 95.34.208.4 + } + } + rule 2689 { + action accept + description FW45000_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW45000_1 + } + port 990 + } + protocol tcp + } + rule 2690 { + action accept + description FW481D7_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW481D7_1 + } + port 6789 + } + protocol tcp + } + rule 2691 { + action accept + description VPN-8203-ANY-ALLOW-10.4.59.109 + destination { + group { + address-group DT_VPN-8203 + } + } + source { + address 10.4.59.109 + } + } + rule 2692 { + action accept + description VPN-3575-ANY-ALLOW-10.4.54.124 + destination { + group { + address-group DT_VPN-3575 + } + } + source { + address 10.4.54.124 + } + } + rule 2693 { + action accept + description VPN-3575-ANY-ALLOW-10.4.55.125 + destination { + group { + address-group DT_VPN-3575 + } + } + source { + address 10.4.55.125 + } + } + rule 2694 { + action accept + description FW42661_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW42661_3 + } + port 44445,25672,15672,9876,7770-7800 + } + protocol tcp + } + rule 2695 { + action accept + description FWBF494_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBF494_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2696 { + action accept + description FWD0E22_4-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD0E22_4 + } + port 8000,19005 + } + protocol tcp + } + rule 2697 { + action accept + description FW98818_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW98818_1 + } + port 27015 + } + protocol udp + } + rule 2698 { + action accept + description FW62858_12-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW62858_12 + } + port 5001,5000 + } + protocol tcp + } + rule 2699 { + action accept + description VPN-34006-ANY-ALLOW-10.4.86.242 + destination { + group { + address-group DT_VPN-34006 + } + } + source { + address 10.4.86.242 + } + } + rule 2700 { + action accept + description VPN-34006-ANY-ALLOW-10.4.87.242 + destination { + group { + address-group DT_VPN-34006 + } + } + source { + address 10.4.87.242 + } + } + rule 2701 { + action accept + description FWF879C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF879C_1 + } + port 8888 + } + protocol tcp + } + rule 2702 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.11.54 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.11.54 + } + } + rule 2703 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.74.89 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.74.89 + } + } + rule 2704 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.77.149 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.77.149 + } + } + rule 2705 { + action accept + description FW8A57A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW8A57A_1 + } + port 49153,5666 + } + protocol tcp + } + rule 2706 { + action accept + description FW62858_12-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW62858_12 + } + port 5090,5061,5060 + } + protocol tcp_udp + } + rule 2707 { + action accept + description FW62858_12-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW62858_12 + } + port 9000-10999 + } + protocol udp + } + rule 2708 { + action accept + description FW0E2EE_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0E2EE_1 + } + port 1024-65535 + } + protocol tcp_udp + } + rule 2709 { + action accept + description FWEEC75_1-TCP-ALLOW-82.5.80.210 + destination { + group { + address-group DT_FWEEC75_1 + } + port 22 + } + protocol tcp + source { + address 82.5.80.210 + } + } + rule 2710 { + action accept + description FW4F81F_4-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW4F81F_4 + } + port 26900,27005,27015,51000,51005,51030 + } + protocol tcp_udp + } + rule 2711 { + action accept + description VPN-7902-ANY-ALLOW-10.4.56.78 + destination { + group { + address-group DT_VPN-7902 + } + } + source { + address 10.4.56.78 + } + } + rule 2712 { + action accept + description VPN-7902-ANY-ALLOW-10.4.57.78 + destination { + group { + address-group DT_VPN-7902 + } + } + source { + address 10.4.57.78 + } + } + rule 2713 { + action accept + description FWB36A0_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWB36A0_1 + } + port 20-21,990 + } + protocol tcp_udp + } + rule 2714 { + action accept + description FWD2082_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD2082_1 + } + port 8001,8002 + } + protocol tcp + } + rule 2715 { + action accept + description FW8A3FC_3-TCP-ALLOW-212.8.242.171 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 212.8.242.171 + } + } + rule 2716 { + action accept + description FWB9699_11-TCP-ALLOW-213.171.217.184 + destination { + group { + address-group DT_FWB9699_11 + } + port 443,80,8800,22 + } + protocol tcp + source { + address 213.171.217.184 + } + } + rule 2717 { + action accept + description VPN-11083-ANY-ALLOW-10.4.54.186 + destination { + group { + address-group DT_VPN-11083 + } + } + source { + address 10.4.54.186 + } + } + rule 2718 { + action accept + description VPN-11083-ANY-ALLOW-10.4.55.187 + destination { + group { + address-group DT_VPN-11083 + } + } + source { + address 10.4.55.187 + } + } + rule 2719 { + action accept + description VPN-34583-ANY-ALLOW-10.4.86.243 + destination { + group { + address-group DT_VPN-34583 + } + } + source { + address 10.4.86.243 + } + } + rule 2720 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.84.155 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.84.155 + } + } + rule 2721 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.117 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.117 + } + } + rule 2722 { + action accept + description FW7A9B0_9-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW7A9B0_9 + } + port 11112 + } + protocol tcp + } + rule 2723 { + action accept + description FW3F465_1-TCP-ALLOW-77.68.127.177 + destination { + group { + address-group DT_FW3F465_1 + } + port 3306 + } + protocol tcp + source { + address 77.68.127.177 + } + } + rule 2724 { + action accept + description VPN-34583-ANY-ALLOW-10.4.87.243 + destination { + group { + address-group DT_VPN-34583 + } + } + source { + address 10.4.87.243 + } + } + rule 2725 { + action accept + description FW930F3_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW930F3_1 + } + port 9089,5900,5666,5272 + } + protocol tcp + } + rule 2726 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.165 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.165 + } + } + rule 2727 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.140 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.140 + } + } + rule 2728 { + action accept + description FW90AE3_1-TCP-ALLOW-82.11.114.136 + destination { + group { + address-group DT_FW90AE3_1 + } + port 3306,22 + } + protocol tcp + source { + address 82.11.114.136 + } + } + rule 2729 { + action accept + description FW73215_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW73215_1 + } + port 27015 + } + protocol tcp_udp + } + rule 2730 { + action accept + description FWC2EF2_1-TCP-ALLOW-18.130.156.250 + destination { + group { + address-group DT_FWC2EF2_1 + } + port 22 + } + protocol tcp + source { + address 18.130.156.250 + } + } + rule 2731 { + action accept + description FWC2EF2_1-TCP-ALLOW-90.251.221.19 + destination { + group { + address-group DT_FWC2EF2_1 + } + port 22 + } + protocol tcp + source { + address 90.251.221.19 + } + } + rule 2732 { + action accept + description FW90AE3_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW90AE3_1 + } + port 8765,8001,8000 + } + protocol tcp + } + rule 2733 { + action accept + description FWC2EF2_1-TCP-ALLOW-87.74.110.191 + destination { + group { + address-group DT_FWC2EF2_1 + } + port 8443 + } + protocol tcp + source { + address 87.74.110.191 + } + } + rule 2734 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.77.70 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.77.70 + } + } + rule 2735 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.93 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.93 + } + } + rule 2736 { + action accept + description FW81138_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW81138_1 + } + port 123 + } + protocol udp + } + rule 2737 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.64 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.64 + } + } + rule 2738 { + action accept + description FW03B35_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW03B35_1 + } + port 1-65535 + } + protocol tcp_udp + } + rule 2739 { + action accept + description VPN-19807-ANY-ALLOW-10.4.87.172 + destination { + group { + address-group DT_VPN-19807 + } + } + source { + address 10.4.87.172 + } + } + rule 2740 { + action accept + description FW5658C_1-TCP-ALLOW-94.12.73.154 + destination { + group { + address-group DT_FW5658C_1 + } + port 8447 + } + protocol tcp + source { + address 94.12.73.154 + } + } + rule 2741 { + action accept + description FW5658C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW5658C_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2742 { + action accept + description FW0B352_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0B352_1 + } + port 3443 + } + protocol tcp_udp + } + rule 2743 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.8.74 + destination { + group { + address-group DT_FWEF92E_5 + } + port 3389,445,443 + } + protocol tcp + source { + address 77.68.8.74 + } + } + rule 2744 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.92.33 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.92.33 + } + } + rule 2745 { + action accept + description FWEF92E_5-TCP-ALLOW-77.68.93.82 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 77.68.93.82 + } + } + rule 2746 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.44 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.44 + } + } + rule 2747 { + action accept + description FW34C91_3-TCP-ALLOW-188.220.176.104 + destination { + group { + address-group DT_FW34C91_3 + } + port 1433 + } + protocol tcp + source { + address 188.220.176.104 + } + } + rule 2748 { + action accept + description FW3F465_1-TCP-ALLOW-77.68.16.101 + destination { + group { + address-group DT_FW3F465_1 + } + port 3306 + } + protocol tcp + source { + address 77.68.16.101 + } + } + rule 2749 { + action accept + description FWEF92E_5-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FWEF92E_5 + } + port 3389,445,443 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 2750 { + action accept + description FW34C91_3-UDP-ALLOW-188.220.176.104 + destination { + group { + address-group DT_FW34C91_3 + } + port 1434 + } + protocol udp + source { + address 188.220.176.104 + } + } + rule 2751 { + action accept + description FWE47DA_1-TCP-ALLOW-185.22.208.0_25 + destination { + group { + address-group DT_FWE47DA_1 + } + port 22 + } + protocol tcp + source { + address 185.22.208.0/25 + } + } + rule 2752 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.187 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.187 + } + } + rule 2753 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.84 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.84 + } + } + rule 2754 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.246.52 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 116.206.246.52 + } + } + rule 2755 { + action accept + description FW8AFF1_7-TCP-ALLOW-77.68.92.154 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 77.68.92.154 + } + } + rule 2756 { + action accept + description FW8AFF1_7-TCP-ALLOW-77.68.93.156 + destination { + group { + address-group DT_FW8AFF1_7 + } + port 1433 + } + protocol tcp + source { + address 77.68.93.156 + } + } + rule 2757 { + action accept + description VPN-24398-ANY-ALLOW-10.4.88.151 + destination { + group { + address-group DT_VPN-24398 + } + } + source { + address 10.4.88.151 + } + } + rule 2758 { + action accept + description VPN-24398-ANY-ALLOW-10.4.89.151 + destination { + group { + address-group DT_VPN-24398 + } + } + source { + address 10.4.89.151 + } + } + rule 2759 { + action accept + description VPN-24589-ANY-ALLOW-10.4.56.9 + destination { + group { + address-group DT_VPN-24589 + } + } + source { + address 10.4.56.9 + } + } + rule 2760 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.29 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.29 + } + } + rule 2761 { + action accept + description FWC7D36_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC7D36_1 + } + port 27017,11080 + } + protocol tcp + } + rule 2762 { + action accept + description FWBB718_1-TCP_UDP-ALLOW-77.68.73.116 + destination { + group { + address-group DT_FWBB718_1 + } + port 1433 + } + protocol tcp_udp + source { + address 77.68.73.116 + } + } + rule 2763 { + action accept + description FWBB718_1-UDP-ALLOW-77.68.73.116 + destination { + group { + address-group DT_FWBB718_1 + } + port 1434 + } + protocol udp + source { + address 77.68.73.116 + } + } + rule 2764 { + action accept + description FWB9699_11-TCP-ALLOW-213.171.217.102 + destination { + group { + address-group DT_FWB9699_11 + } + port 22,80,443,8800 + } + protocol tcp + source { + address 213.171.217.102 + } + } + rule 2765 { + action accept + description FW18E6E_3-TCP-ALLOW-103.8.164.5 + destination { + group { + address-group DT_FW18E6E_3 + } + port 22 + } + protocol tcp + source { + address 103.8.164.5 + } + } + rule 2766 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.193 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.193 + } + } + rule 2768 { + action accept + description FW26F0A_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW26F0A_1 + } + port 53 + } + protocol tcp_udp + } + rule 2769 { + action accept + description FWCC18F_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWCC18F_2 + } + port 8883,1883 + } + protocol tcp + } + rule 2771 { + action accept + description FW633DD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW633DD_1 + } + port 28967,14002,9984,9983,9982,9981,8888,8884 + } + protocol tcp + } + rule 2772 { + action accept + description FWDEDB9_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDEDB9_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2773 { + action accept + description VPN-18646-ANY-ALLOW-10.4.88.109 + destination { + group { + address-group DT_VPN-18646 + } + } + source { + address 10.4.88.109 + } + } + rule 2774 { + action accept + description VPN-18646-ANY-ALLOW-10.4.89.109 + destination { + group { + address-group DT_VPN-18646 + } + } + source { + address 10.4.89.109 + } + } + rule 2775 { + action accept + description FWA0531_1-TCP-ALLOW-87.224.39.221 + destination { + group { + address-group DT_FWA0531_1 + } + port 8082,3003,22 + } + protocol tcp + source { + address 87.224.39.221 + } + } + rule 2776 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.94 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.94 + } + } + rule 2777 { + action accept + description FWA0531_1-TCP-ALLOW-92.237.97.92 + destination { + group { + address-group DT_FWA0531_1 + } + port 8082,3003,22 + } + protocol tcp + source { + address 92.237.97.92 + } + } + rule 2778 { + action accept + description VPN-25822-ANY-ALLOW-10.4.55.42 + destination { + group { + address-group DT_VPN-25822 + } + } + source { + address 10.4.55.42 + } + } + rule 2779 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.88 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.211.88 + } + } + rule 2780 { + action accept + description FWC2D30_1-TCP-ALLOW-143.55.64.0_20 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 143.55.64.0/20 + } + } + rule 2781 { + action accept + description FW18E6E_3-TCP-ALLOW-194.176.78.206 + destination { + group { + address-group DT_FW18E6E_3 + } + port 22 + } + protocol tcp + source { + address 194.176.78.206 + } + } + rule 2782 { + action accept + description FW18E6E_3-TCP-ALLOW-195.243.221.50 + destination { + group { + address-group DT_FW18E6E_3 + } + port 22 + } + protocol tcp + source { + address 195.243.221.50 + } + } + rule 2783 { + action accept + description FW18E6E_3-TCP-ALLOW-213.171.217.107 + destination { + group { + address-group DT_FW18E6E_3 + } + port 22 + } + protocol tcp + source { + address 213.171.217.107 + } + } + rule 2784 { + action accept + description FW18E6E_3-TCP-ALLOW-81.150.168.54 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306,22 + } + protocol tcp + source { + address 81.150.168.54 + } + } + rule 2785 { + action accept + description FW18E6E_3-TCP-ALLOW-89.197.133.235 + destination { + group { + address-group DT_FW18E6E_3 + } + port 22 + } + protocol tcp + source { + address 89.197.133.235 + } + } + rule 2786 { + action accept + description FW18E6E_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW18E6E_3 + } + port 60000-60100,873 + } + protocol tcp + } + rule 2787 { + action accept + description FW2BF20_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2BF20_3 + } + port 49152-65534,990 + } + protocol tcp + } + rule 2788 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.98 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.98 + } + } + rule 2789 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.65 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.65 + } + } + rule 2791 { + action accept + description FW197DB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW197DB_1 + } + port 49152-65534 + } + protocol tcp + } + rule 2792 { + action accept + description FW1208C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1208C_1 + } + port 2087,2083,2096 + } + protocol tcp + } + rule 2793 { + action accept + description FW00D98_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW00D98_1 + } + port 4430 + } + protocol tcp + } + rule 2794 { + action accept + description FW03B35_1-ESP-ALLOW-ANY + destination { + group { + address-group DT_FW03B35_1 + } + } + protocol esp + } + rule 2795 { + action accept + description FW03B35_1-AH-ALLOW-ANY + destination { + group { + address-group DT_FW03B35_1 + } + } + protocol ah + } + rule 2796 { + action accept + description FWEF92E_5-TCP-ALLOW-87.224.6.174 + destination { + group { + address-group DT_FWEF92E_5 + } + port 3389,445,443 + } + protocol tcp + source { + address 87.224.6.174 + } + } + rule 2797 { + action accept + description FW825C8_19-TCP-ALLOW-159.253.51.74 + destination { + group { + address-group DT_FW825C8_19 + } + port 3389,1433,995 + } + protocol tcp + source { + address 159.253.51.74 + } + } + rule 2798 { + action accept + description FW825C8_19-TCP-ALLOW-77.68.76.111 + destination { + group { + address-group DT_FW825C8_19 + } + port 1433 + } + protocol tcp + source { + address 77.68.76.111 + } + } + rule 2799 { + action accept + description FW825C8_19-TCP-ALLOW-77.68.28.63 + destination { + group { + address-group DT_FW825C8_19 + } + port 995 + } + protocol tcp + source { + address 77.68.28.63 + } + } + rule 2801 { + action accept + description FW2EF2C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2EF2C_1 + } + port 5349 + } + protocol tcp + } + rule 2802 { + action accept + description FWEF92E_5-TCP-ALLOW-88.208.198.93 + destination { + group { + address-group DT_FWEF92E_5 + } + port 443 + } + protocol tcp + source { + address 88.208.198.93 + } + } + rule 2803 { + action accept + description FWC3921_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC3921_1 + } + port 25000,25001-25005,26000-26006 + } + protocol tcp + } + rule 2804 { + action accept + description FWEF92E_5-UDP-ALLOW-109.228.37.19 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 109.228.37.19 + } + } + rule 2805 { + action accept + description FWEF92E_5-UDP-ALLOW-77.68.11.54 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 77.68.11.54 + } + } + rule 2806 { + action accept + description FW5AE10_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW5AE10_1 + } + port 53 + } + protocol tcp_udp + } + rule 2810 { + action accept + description FW45F87_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW45F87_1 + } + port 60000-60100 + } + protocol tcp + } + rule 2811 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.108.158 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 123.231.108.158 + } + } + rule 2813 { + action accept + description FW825C8_19-TCP-ALLOW-109.228.1.233 + destination { + group { + address-group DT_FW825C8_19 + } + port 1433 + } + protocol tcp + source { + address 109.228.1.233 + } + } + rule 2814 { + action accept + description FW20449_2-ICMP-ALLOW-3.10.221.168 + destination { + group { + address-group DT_FW20449_2 + } + } + protocol icmp + source { + address 3.10.221.168 + } + } + rule 2815 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.100 + destination { + group { + address-group DT_FWB9699_7 + } + port 22 + } + protocol tcp + source { + address 213.171.217.100 + } + } + rule 2816 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.180 + destination { + group { + address-group DT_FWB9699_7 + } + port 22 + } + protocol tcp + source { + address 213.171.217.180 + } + } + rule 2817 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.184 + destination { + group { + address-group DT_FWB9699_7 + } + port 22 + } + protocol tcp + source { + address 213.171.217.184 + } + } + rule 2818 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.185 + destination { + group { + address-group DT_FWB9699_7 + } + port 22 + } + protocol tcp + source { + address 213.171.217.185 + } + } + rule 2819 { + action accept + description FWB9699_7-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWB9699_7 + } + port 161 + } + protocol udp + } + rule 2820 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.102 + destination { + group { + address-group DT_FWB9699_7 + } + port 22,8443 + } + protocol tcp + source { + address 213.171.217.102 + } + } + rule 2821 { + action accept + description FWB9699_7-TCP-ALLOW-213.171.217.103 + destination { + group { + address-group DT_FWB9699_7 + } + port 22 + } + protocol tcp + source { + address 213.171.217.103 + } + } + rule 2824 { + action accept + description FWE3E77_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE3E77_1 + } + port 10010,10009 + } + protocol tcp + } + rule 2825 { + action accept + description FW8A3FC_3-TCP-ALLOW-93.190.142.120 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 93.190.142.120 + } + } + rule 2826 { + action accept + description FW20449_2-ICMP-ALLOW-82.20.69.137 + destination { + group { + address-group DT_FW20449_2 + } + } + protocol icmp + source { + address 82.20.69.137 + } + } + rule 2827 { + action accept + description FW8A3FC_3-TCP-ALLOW-46.101.232.93 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 21-10000 + } + protocol tcp + source { + address 46.101.232.93 + } + } + rule 2828 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.5 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.5 + } + } + rule 2829 { + action accept + description FWD2440_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD2440_1 + } + port 1-65535 + } + protocol tcp + } + rule 2831 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.105 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.105 + } + } + rule 2833 { + action accept + description FW825C8_24-TCP-ALLOW-159.253.51.74 + destination { + group { + address-group DT_FW825C8_24 + } + port 3389,1433,995 + } + protocol tcp + source { + address 159.253.51.74 + } + } + rule 2834 { + action accept + description FW825C8_24-TCP-ALLOW-77.68.77.120 + destination { + group { + address-group DT_FW825C8_24 + } + port 1433 + } + protocol tcp + source { + address 77.68.77.120 + } + } + rule 2839 { + action accept + description FWD2440_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWD2440_1 + } + port 1-65535 + } + protocol udp + } + rule 2840 { + action accept + description FW1C8F2_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1C8F2_1 + } + port 7000-10000,5554,5443,5080,1935,1111 + } + protocol tcp + } + rule 2843 { + action accept + description FWE7180_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWE7180_1 + } + port 443,53 + } + protocol tcp_udp + } + rule 2844 { + action accept + description FWC6301_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC6301_1 + } + port 2456 + } + protocol tcp_udp + } + rule 2845 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.113 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.113 + } + } + rule 2846 { + action accept + description VPN-24589-ANY-ALLOW-10.4.57.9 + destination { + group { + address-group DT_VPN-24589 + } + } + source { + address 10.4.57.9 + } + } + rule 2847 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.237 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.212.237 + } + } + rule 2849 { + action accept + description FWFD9AF_9-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWFD9AF_9 + } + port 445 + } + protocol tcp_udp + } + rule 2850 { + action accept + description VPN-23209-ANY-ALLOW-10.4.58.8 + destination { + group { + address-group DT_VPN-23209 + } + } + source { + address 10.4.58.8 + } + } + rule 2851 { + action accept + description VPN-23209-ANY-ALLOW-10.4.59.8 + destination { + group { + address-group DT_VPN-23209 + } + } + source { + address 10.4.59.8 + } + } + rule 2853 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.29 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.29 + } + } + rule 2854 { + action accept + description FW16375_5-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW16375_5 + } + port 2096 + } + protocol tcp_udp + } + rule 2856 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.173 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.173 + } + } + rule 2858 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.35 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.35 + } + } + rule 2859 { + action accept + description FW73573_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW73573_1 + } + port 25 + } + protocol tcp_udp + } + rule 2860 { + action accept + description FW18E6E_3-TCP-ALLOW-148.253.173.242 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306 + } + protocol tcp + source { + address 148.253.173.242 + } + } + rule 2861 { + action accept + description FW8ECF4_1-TCP-ALLOW-77.68.2.215 + destination { + group { + address-group DT_FW8ECF4_1 + } + port 3306 + } + protocol tcp + source { + address 77.68.2.215 + } + } + rule 2862 { + action accept + description FW8A3FC_3-TCP_UDP-ALLOW-82.165.100.25 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 21-10000 + } + protocol tcp_udp + source { + address 82.165.100.25 + } + } + rule 2863 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.235 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.235 + } + } + rule 2864 { + action accept + description VPN-18647-ANY-ALLOW-10.4.86.114 + destination { + group { + address-group DT_VPN-18647 + } + } + source { + address 10.4.86.114 + } + } + rule 2865 { + action accept + description VPN-18647-ANY-ALLOW-10.4.87.114 + destination { + group { + address-group DT_VPN-18647 + } + } + source { + address 10.4.87.114 + } + } + rule 2867 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.107 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.107 + } + } + rule 2868 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.239 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.239 + } + } + rule 2869 { + action accept + description FWF699D_4-TCP-ALLOW-164.39.151.3 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 164.39.151.3 + } + } + rule 2870 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.245 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.245 + } + } + rule 2873 { + action accept + description FWEF92E_6-TCP-ALLOW-87.224.6.174 + destination { + group { + address-group DT_FWEF92E_6 + } + port 3389,445 + } + protocol tcp + source { + address 87.224.6.174 + } + } + rule 2874 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.130 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.130 + } + } + rule 2875 { + action accept + description FW44BF9_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW44BF9_1 + } + port 49160-49200 + } + protocol tcp + } + rule 2876 { + action accept + description VPN-24591-ANY-ALLOW-10.4.86.4 + destination { + group { + address-group DT_VPN-24591 + } + } + source { + address 10.4.86.4 + } + } + rule 2877 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.60 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.60 + } + } + rule 2879 { + action accept + description FWEF92E_6-UDP-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_6 + } + port 500 + } + protocol udp + source { + address 77.68.77.57 + } + } + rule 2880 { + action accept + description FWF699D_4-TCP-ALLOW-185.132.38.110 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 185.132.38.110 + } + } + rule 2881 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.216 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.216 + } + } + rule 2882 { + action accept + description FWEF92E_5-UDP-ALLOW-77.68.77.149 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 77.68.77.149 + } + } + rule 2883 { + action accept + description FWA2FF8_4-TCP-ALLOW-80.229.18.102 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 3306,21,22 + } + protocol tcp + source { + address 80.229.18.102 + } + } + rule 2884 { + action accept + description FWA2FF8_4-TCP-ALLOW-109.169.33.69 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 3306,21,22 + } + protocol tcp + source { + address 109.169.33.69 + } + } + rule 2885 { + action accept + description FWA2FF8_4-TCP-ALLOW-46.102.209.35 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 3306,21 + } + protocol tcp + source { + address 46.102.209.35 + } + } + rule 2886 { + action accept + description FWA2FF8_4-TCP-ALLOW-90.213.48.16 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 3306,21 + } + protocol tcp + source { + address 90.213.48.16 + } + } + rule 2887 { + action accept + description FWA2FF8_4-TCP-ALLOW-77.68.76.129 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 22 + } + protocol tcp + source { + address 77.68.76.129 + } + } + rule 2888 { + action accept + description FWA2FF8_4-TCP-ALLOW-109.228.50.145 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 22 + } + protocol tcp + source { + address 109.228.50.145 + } + } + rule 2889 { + action accept + description FWA2FF8_4-TCP-ALLOW-77.68.76.231 + destination { + group { + address-group DT_FWA2FF8_4 + } + port 22 + } + protocol tcp + source { + address 77.68.76.231 + } + } + rule 2890 { + action accept + description FW4513E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4513E_1 + } + port 50000-50020,990 + } + protocol tcp + } + rule 2893 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.40.7 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.40.7 + } + } + rule 2894 { + action accept + description VPN-21876-ANY-ALLOW-10.4.88.96 + destination { + group { + address-group DT_VPN-21876 + } + } + source { + address 10.4.88.96 + } + } + rule 2895 { + action accept + description VPN-21876-ANY-ALLOW-10.4.89.96 + destination { + group { + address-group DT_VPN-21876 + } + } + source { + address 10.4.89.96 + } + } + rule 2896 { + action accept + description VPN-26124-ANY-ALLOW-10.4.54.75 + destination { + group { + address-group DT_VPN-26124 + } + } + source { + address 10.4.54.75 + } + } + rule 2897 { + action accept + description VPN-26124-ANY-ALLOW-10.4.55.76 + destination { + group { + address-group DT_VPN-26124 + } + } + source { + address 10.4.55.76 + } + } + rule 2898 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.21 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.210.21 + } + } + rule 2899 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.213 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.213 + } + } + rule 2901 { + action accept + description FWC6301_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC6301_1 + } + port 5555 + } + protocol udp + } + rule 2902 { + action accept + description VPN-13261-ANY-ALLOW-10.4.56.173 + destination { + group { + address-group DT_VPN-13261 + } + } + source { + address 10.4.56.173 + } + } + rule 2903 { + action accept + description VPN-13261-ANY-ALLOW-10.4.57.173 + destination { + group { + address-group DT_VPN-13261 + } + } + source { + address 10.4.57.173 + } + } + rule 2909 { + action accept + description VPN-24591-ANY-ALLOW-10.4.87.4 + destination { + group { + address-group DT_VPN-24591 + } + } + source { + address 10.4.87.4 + } + } + rule 2911 { + action accept + description FWE7180_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE7180_1 + } + port 40110-40210,8090 + } + protocol tcp + } + rule 2914 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.247 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.247 + } + } + rule 2915 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.129 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.129 + } + } + rule 2916 { + action accept + description FWCB29D_1-TCP-ALLOW-51.146.16.162 + destination { + group { + address-group DT_FWCB29D_1 + } + port 8447,8443,22 + } + protocol tcp + source { + address 51.146.16.162 + } + } + rule 2917 { + action accept + description FW4E399_1-TCP-ALLOW-51.155.19.77 + destination { + group { + address-group DT_FW4E399_1 + } + port 3306 + } + protocol tcp + source { + address 51.155.19.77 + } + } + rule 2919 { + action accept + description FWC72E5_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC72E5_1 + } + port 9000-9100,6667 + } + protocol tcp + } + rule 2922 { + action accept + description FW21A75_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW21A75_2 + } + port 3000 + } + protocol tcp + } + rule 2923 { + action accept + description FW3B068_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW3B068_2 + } + port 990,60000-65000 + } + protocol tcp + } + rule 2924 { + action accept + description FW48814_3-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW48814_3 + } + port 3306 + } + protocol tcp_udp + } + rule 2925 { + action accept + description FW48814_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW48814_3 + } + port 49152-65534 + } + protocol tcp + } + rule 2926 { + action accept + description FW2B279_4-TCP-ALLOW-178.128.39.210 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443 + } + protocol tcp + source { + address 178.128.39.210 + } + } + rule 2927 { + action accept + description FW2B279_4-TCP-ALLOW-82.165.232.19 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443 + } + protocol tcp + source { + address 82.165.232.19 + } + } + rule 2928 { + action accept + description FW2B279_4-TCP-ALLOW-84.64.186.31 + destination { + group { + address-group DT_FW2B279_4 + } + port 8443 + } + protocol tcp + source { + address 84.64.186.31 + } + } + rule 2929 { + action accept + description FW1C8F2_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW1C8F2_1 + } + port 5000-65000 + } + protocol udp + } + rule 2930 { + action accept + description FW2B279_4-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2B279_4 + } + port 49152-65535 + } + protocol tcp + } + rule 2931 { + action accept + description FW608FA_1-TCP-ALLOW-195.10.106.114 + destination { + group { + address-group DT_FW608FA_1 + } + port 22 + } + protocol tcp + source { + address 195.10.106.114 + } + } + rule 2932 { + action accept + description FW608FA_1-TCP-ALLOW-213.137.25.134 + destination { + group { + address-group DT_FW608FA_1 + } + port 22 + } + protocol tcp + source { + address 213.137.25.134 + } + } + rule 2933 { + action accept + description FW608FA_1-TCP-ALLOW-92.39.202.189 + destination { + group { + address-group DT_FW608FA_1 + } + port 22 + } + protocol tcp + source { + address 92.39.202.189 + } + } + rule 2935 { + action accept + description FWC37B9_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC37B9_1 + } + port 49152-65535 + } + protocol tcp + } + rule 2936 { + action accept + description FW15C99_6-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW15C99_6 + } + port 32410-32414,1900 + } + protocol udp + } + rule 2937 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.244.146 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 116.206.244.146 + } + } + rule 2938 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.158 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.211.158 + } + } + rule 2939 { + action accept + description FW15C99_6-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW15C99_6 + } + port 32469,32400 + } + protocol tcp + } + rule 2940 { + action accept + description FW0192C_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0192C_1 + } + port 2053 + } + protocol tcp + } + rule 2941 { + action accept + description FW27949_2-TCP-ALLOW-86.179.23.119 + destination { + group { + address-group DT_FW27949_2 + } + port 443,80 + } + protocol tcp + source { + address 86.179.23.119 + } + } + rule 2942 { + action accept + description FW27949_2-TCP-ALLOW-92.15.208.193 + destination { + group { + address-group DT_FW27949_2 + } + port 443,80 + } + protocol tcp + source { + address 92.15.208.193 + } + } + rule 2943 { + action accept + description VPN-34122-ANY-ALLOW-10.4.56.122 + destination { + group { + address-group DT_VPN-34122 + } + } + source { + address 10.4.56.122 + } + } + rule 2944 { + action accept + description VPN-34122-ANY-ALLOW-10.4.57.122 + destination { + group { + address-group DT_VPN-34122 + } + } + source { + address 10.4.57.122 + } + } + rule 2945 { + action accept + description FWF323F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF323F_1 + } + port 25565,9999,8080,5001,3306 + } + protocol tcp_udp + } + rule 2946 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.132 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.132 + } + } + rule 2948 { + action accept + description VPN-30261-ANY-ALLOW-10.4.86.110 + destination { + group { + address-group DT_VPN-30261 + } + } + source { + address 10.4.86.110 + } + } + rule 2949 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.246 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.246 + } + } + rule 2951 { + action accept + description FWC2D30_1-TCP-ALLOW-157.231.100.222 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 157.231.100.222 + } + } + rule 2952 { + action accept + description FWC2D30_1-TCP-ALLOW-164.39.131.31 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 164.39.131.31 + } + } + rule 2953 { + action accept + description FWC2D30_1-TCP-ALLOW-185.199.108.0_22 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 185.199.108.0/22 + } + } + rule 2954 { + action accept + description FWC2D30_1-TCP-ALLOW-192.30.252.0_22 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 192.30.252.0/22 + } + } + rule 2955 { + action accept + description FWC2D30_1-TCP-ALLOW-80.252.78.202 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 80.252.78.202 + } + } + rule 2956 { + action accept + description FWC2D30_1-TCP-ALLOW-86.15.158.234 + destination { + group { + address-group DT_FWC2D30_1 + } + port 8443 + } + protocol tcp + source { + address 86.15.158.234 + } + } + rule 2957 { + action accept + description VPN-30261-ANY-ALLOW-10.4.87.110 + destination { + group { + address-group DT_VPN-30261 + } + } + source { + address 10.4.87.110 + } + } + rule 2958 { + action accept + description VPN-30262-ANY-ALLOW-10.4.88.36 + destination { + group { + address-group DT_VPN-30262 + } + } + source { + address 10.4.88.36 + } + } + rule 2961 { + action accept + description VPN-15950-ANY-ALLOW-10.4.88.89 + destination { + group { + address-group DT_VPN-15950 + } + } + source { + address 10.4.88.89 + } + } + rule 2962 { + action accept + description FWBFDED_1-TCP-ALLOW-78.141.24.164 + destination { + group { + address-group DT_FWBFDED_1 + } + port 3389 + } + protocol tcp + source { + address 78.141.24.164 + } + } + rule 2963 { + action accept + description VPN-30262-ANY-ALLOW-10.4.89.36 + destination { + group { + address-group DT_VPN-30262 + } + } + source { + address 10.4.89.36 + } + } + rule 2964 { + action accept + description FW1F126_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1F126_1 + } + port 2087,2083 + } + protocol tcp + } + rule 2965 { + action accept + description FWA7A50_1-ANY-ALLOW-40.120.53.80 + destination { + group { + address-group DT_FWA7A50_1 + } + } + source { + address 40.120.53.80 + } + } + rule 2967 { + action accept + description VPN-23729-ANY-ALLOW-10.4.54.10 + destination { + group { + address-group DT_VPN-23729 + } + } + source { + address 10.4.54.10 + } + } + rule 2968 { + action accept + description VPN-23729-ANY-ALLOW-10.4.55.10 + destination { + group { + address-group DT_VPN-23729 + } + } + source { + address 10.4.55.10 + } + } + rule 2969 { + action accept + description VPN-23733-ANY-ALLOW-10.4.58.12 + destination { + group { + address-group DT_VPN-23733 + } + } + source { + address 10.4.58.12 + } + } + rule 2970 { + action accept + description VPN-23733-ANY-ALLOW-10.4.59.12 + destination { + group { + address-group DT_VPN-23733 + } + } + source { + address 10.4.59.12 + } + } + rule 2971 { + action accept + description VPN-23734-ANY-ALLOW-10.4.56.29 + destination { + group { + address-group DT_VPN-23734 + } + } + source { + address 10.4.56.29 + } + } + rule 2972 { + action accept + description VPN-23734-ANY-ALLOW-10.4.57.29 + destination { + group { + address-group DT_VPN-23734 + } + } + source { + address 10.4.57.29 + } + } + rule 2975 { + action accept + description VPN-23738-ANY-ALLOW-10.4.57.13 + destination { + group { + address-group DT_VPN-23738 + } + } + source { + address 10.4.57.13 + } + } + rule 2976 { + action accept + description FWD8DD1_2-TCP-ALLOW-77.153.164.226 + destination { + group { + address-group DT_FWD8DD1_2 + } + port 3306,22 + } + protocol tcp + source { + address 77.153.164.226 + } + } + rule 2977 { + action accept + description FWE012D_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWE012D_1 + } + port 143,25 + } + protocol tcp_udp + } + rule 2978 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.120.196 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.120.196 + } + } + rule 2981 { + action accept + description FW24AB7_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW24AB7_1 + } + port 40110-40210 + } + protocol tcp_udp + } + rule 2985 { + action accept + description FW2379F_14-TCP-ALLOW-194.72.140.178 + destination { + group { + address-group DT_FW2379F_14 + } + port 3389,21 + } + protocol tcp + source { + address 194.72.140.178 + } + } + rule 2986 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.97 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.97 + } + } + rule 2988 { + action accept + description FW883EB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW883EB_1 + } + port 5005,5004,5003,5002,5001 + } + protocol tcp + } + rule 2992 { + action accept + description FW310C6_3-ANY-ALLOW-62.30.207.232 + destination { + group { + address-group DT_FW310C6_3 + } + } + source { + address 62.30.207.232 + } + } + rule 2993 { + action accept + description VPN-15950-ANY-ALLOW-10.4.89.89 + destination { + group { + address-group DT_VPN-15950 + } + } + source { + address 10.4.89.89 + } + } + rule 2994 { + action accept + description VPN-15960-ANY-ALLOW-10.4.88.90 + destination { + group { + address-group DT_VPN-15960 + } + } + source { + address 10.4.88.90 + } + } + rule 2995 { + action accept + description FWEF92E_7-UDP-ALLOW-77.68.77.57 + destination { + group { + address-group DT_FWEF92E_7 + } + port 500 + } + protocol udp + source { + address 77.68.77.57 + } + } + rule 2996 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.135 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.135 + } + } + rule 2998 { + action accept + description VPN-31002-ANY-ALLOW-10.4.88.126 + destination { + group { + address-group DT_VPN-31002 + } + } + source { + address 10.4.88.126 + } + } + rule 2999 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.246.110 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 116.206.246.110 + } + } + rule 3000 { + action accept + description FW08061_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW08061_1 + } + port 49152-65535 + } + protocol tcp + } + rule 3001 { + action accept + description VPN-15960-ANY-ALLOW-10.4.89.90 + destination { + group { + address-group DT_VPN-15960 + } + } + source { + address 10.4.89.90 + } + } + rule 3003 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.56 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.56 + } + } + rule 3004 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.47.47 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 175.157.47.47 + } + } + rule 3005 { + action accept + description FW10C3D_19-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW10C3D_19 + } + port 49152-65535,14147 + } + protocol tcp + } + rule 3006 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.136 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.210.136 + } + } + rule 3009 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.44.109 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.44.109 + } + } + rule 3010 { + action accept + description VPN-24592-ANY-ALLOW-10.4.88.9 + destination { + group { + address-group DT_VPN-24592 + } + } + source { + address 10.4.88.9 + } + } + rule 3011 { + action accept + description FW05AD0_2-TCP-ALLOW-213.171.209.161 + destination { + group { + address-group DT_FW05AD0_2 + } + port 3389,1433,21 + } + protocol tcp + source { + address 213.171.209.161 + } + } + rule 3012 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.86.254 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.86.254 + } + } + rule 3014 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.16 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.16 + } + } + rule 3018 { + action accept + description VPN-24592-ANY-ALLOW-10.4.89.9 + destination { + group { + address-group DT_VPN-24592 + } + } + source { + address 10.4.89.9 + } + } + rule 3019 { + action accept + description VPN-24593-ANY-ALLOW-10.4.54.6 + destination { + group { + address-group DT_VPN-24593 + } + } + source { + address 10.4.54.6 + } + } + rule 3020 { + action accept + description VPN-24593-ANY-ALLOW-10.4.55.6 + destination { + group { + address-group DT_VPN-24593 + } + } + source { + address 10.4.55.6 + } + } + rule 3021 { + action accept + description VPN-24594-ANY-ALLOW-10.4.58.6 + destination { + group { + address-group DT_VPN-24594 + } + } + source { + address 10.4.58.6 + } + } + rule 3022 { + action accept + description VPN-24594-ANY-ALLOW-10.4.59.6 + destination { + group { + address-group DT_VPN-24594 + } + } + source { + address 10.4.59.6 + } + } + rule 3023 { + action accept + description VPN-24595-ANY-ALLOW-10.4.56.14 + destination { + group { + address-group DT_VPN-24595 + } + } + source { + address 10.4.56.14 + } + } + rule 3024 { + action accept + description VPN-24595-ANY-ALLOW-10.4.57.14 + destination { + group { + address-group DT_VPN-24595 + } + } + source { + address 10.4.57.14 + } + } + rule 3025 { + action accept + description VPN-32528-ANY-ALLOW-10.4.58.67 + destination { + group { + address-group DT_VPN-32528 + } + } + source { + address 10.4.58.67 + } + } + rule 3026 { + action accept + description VPN-32528-ANY-ALLOW-10.4.59.67 + destination { + group { + address-group DT_VPN-32528 + } + } + source { + address 10.4.59.67 + } + } + rule 3027 { + action accept + description FW6187E_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6187E_1 + } + port 51195 + } + protocol udp + } + rule 3028 { + action accept + description FW406AB_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW406AB_1 + } + port 37013,25461,8881,8080,2095,2082,1992 + } + protocol tcp_udp + } + rule 3029 { + action accept + description FWA86A4_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA86A4_1 + } + port 30333,5666 + } + protocol tcp + } + rule 3032 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.52 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.52 + } + } + rule 3033 { + action accept + description FWC055A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWC055A_1 + } + port 2195 + } + protocol tcp + } + rule 3035 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.81 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.81 + } + } + rule 3039 { + action accept + description FW42BC7_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW42BC7_1 + } + port 53 + } + protocol tcp_udp + } + rule 3040 { + action accept + description FW42BC7_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW42BC7_1 + } + port 49152-65535 + } + protocol tcp + } + rule 3041 { + action accept + description FW310C6_3-ANY-ALLOW-88.208.198.39 + destination { + group { + address-group DT_FW310C6_3 + } + } + source { + address 88.208.198.39 + } + } + rule 3042 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.235 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.235 + } + } + rule 3043 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.205 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.212.205 + } + } + rule 3044 { + action accept + description FWBE878_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWBE878_1 + } + port 8989,5003,3000 + } + protocol tcp_udp + } + rule 3045 { + action accept + description VPN-30679-ANY-ALLOW-10.4.58.195 + destination { + group { + address-group DT_VPN-30679 + } + } + source { + address 10.4.58.195 + } + } + rule 3046 { + action accept + description FW6B9B9_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6B9B9_1 + } + port 30006-65000,27017,7101,4200,2990-3009 + } + protocol tcp + } + rule 3047 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.212 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.212 + } + } + rule 3049 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.125.4 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 123.231.125.4 + } + } + rule 3050 { + action accept + description FW49C3D_4-TCP-ALLOW-83.100.136.74 + destination { + group { + address-group DT_FW49C3D_4 + } + port 3389,445 + } + protocol tcp + source { + address 83.100.136.74 + } + } + rule 3051 { + action accept + description FW49C3D_6-TCP-ALLOW-87.224.33.215 + destination { + group { + address-group DT_FW49C3D_6 + } + port 3389,445 + } + protocol tcp + source { + address 87.224.33.215 + } + } + rule 3053 { + action accept + description FW89619_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW89619_1 + } + port 9000-10999 + } + protocol udp + } + rule 3054 { + action accept + description FWBD9D0_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBD9D0_1 + } + port 9090 + } + protocol tcp + } + rule 3055 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.47.236 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 175.157.47.236 + } + } + rule 3056 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.46.226 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.46.226 + } + } + rule 3058 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.205 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.211.205 + } + } + rule 3060 { + action accept + description FWF7B68_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF7B68_1 + } + port 49152-65535 + } + protocol tcp + } + rule 3061 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.253 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.253 + } + } + rule 3063 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.0 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.210.0 + } + } + rule 3065 { + action accept + description FW85619_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW85619_1 + } + port 6433 + } + protocol tcp + } + rule 3066 { + action accept + description FW5A5D7_3-TCP-ALLOW-188.66.79.94 + destination { + group { + address-group DT_FW5A5D7_3 + } + port 8172,3389 + } + protocol tcp + source { + address 188.66.79.94 + } + } + rule 3067 { + action accept + description FWF30BD_1-TCP-ALLOW-81.133.80.114 + destination { + group { + address-group DT_FWF30BD_1 + } + port 22 + } + protocol tcp + source { + address 81.133.80.114 + } + } + rule 3068 { + action accept + description FWF30BD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF30BD_1 + } + port 5061,5015,5001 + } + protocol tcp + } + rule 3069 { + action accept + description FWBD9D0_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWBD9D0_1 + } + port 51820 + } + protocol udp + } + rule 3070 { + action accept + description FW7C4D9_14-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW7C4D9_14 + } + port 25565,2456-2458 + } + protocol tcp_udp + } + rule 3071 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.23 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.23 + } + } + rule 3072 { + action accept + description FWEEC75_1-TCP-ALLOW-81.96.100.32 + destination { + group { + address-group DT_FWEEC75_1 + } + port 8447 + } + protocol tcp + source { + address 81.96.100.32 + } + } + rule 3073 { + action accept + description FW8A3FC_3-TCP-ALLOW-95.168.164.208 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 95.168.164.208 + } + } + rule 3074 { + action accept + description VPN-19992-ANY-ALLOW-10.4.86.158 + destination { + group { + address-group DT_VPN-19992 + } + } + source { + address 10.4.86.158 + } + } + rule 3075 { + action accept + description FWF30BD_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF30BD_1 + } + port 5090,5060 + } + protocol tcp_udp + } + rule 3076 { + action accept + description VPN-30679-ANY-ALLOW-10.4.59.195 + destination { + group { + address-group DT_VPN-30679 + } + } + source { + address 10.4.59.195 + } + } + rule 3077 { + action accept + description FW930F3_3-ANY-ALLOW-77.68.112.254 + destination { + group { + address-group DT_FW930F3_3 + } + } + source { + address 77.68.112.254 + } + } + rule 3078 { + action accept + description FW672AB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW672AB_1 + } + port 5432 + } + protocol tcp + } + rule 3079 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.252 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.211.252 + } + } + rule 3080 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.86.192 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.86.192 + } + } + rule 3081 { + action accept + description VPN-33204-ANY-ALLOW-10.4.56.176 + destination { + group { + address-group DT_VPN-33204 + } + } + source { + address 10.4.56.176 + } + } + rule 3083 { + action accept + description FW1FA8E_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW1FA8E_1 + } + port 33434 + } + protocol udp + } + rule 3084 { + action accept + description FWD2440_1-ESP-ALLOW-ANY + destination { + group { + address-group DT_FWD2440_1 + } + } + protocol esp + } + rule 3085 { + action accept + description FWA0531_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA0531_1 + } + port 53 + } + protocol tcp_udp + } + rule 3090 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.70 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.70 + } + } + rule 3091 { + action accept + description FWF7BFA_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF7BFA_1 + } + port 8000,5901,5479,5478 + } + protocol tcp + } + rule 3092 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.212 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.212 + } + } + rule 3094 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.125 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.212.125 + } + } + rule 3096 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.89 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.89 + } + } + rule 3097 { + action accept + description FWD56A2_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD56A2_1 + } + port 8001,8000 + } + protocol tcp + } + rule 3098 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.109 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.109 + } + } + rule 3099 { + action accept + description FW36425_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW36425_1 + } + port 44445,7770-7800 + } + protocol tcp + } + rule 3100 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.238 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.238 + } + } + rule 3102 { + action accept + description FW6B39D_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW6B39D_1 + } + port 49216,49215 + } + protocol tcp_udp + } + rule 3103 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.121 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.121 + } + } + rule 3105 { + action accept + description FW2379F_14-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW2379F_14 + } + port 443 + } + protocol tcp_udp + } + rule 3107 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.38 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.38 + } + } + rule 3109 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.191 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.191 + } + } + rule 3111 { + action accept + description FW27947_1-TCP-ALLOW-213.229.100.148 + destination { + group { + address-group DT_FW27947_1 + } + port 3306 + } + protocol tcp + source { + address 213.229.100.148 + } + } + rule 3112 { + action accept + description FWD42CF_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD42CF_1 + } + port 5432,5001,5000 + } + protocol tcp + } + rule 3114 { + action accept + description FW3A12F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW3A12F_1 + } + port 53 + } + protocol tcp_udp + } + rule 3116 { + action accept + description FW5A5D7_3-TCP-ALLOW-194.62.184.87 + destination { + group { + address-group DT_FW5A5D7_3 + } + port 3389 + } + protocol tcp + source { + address 194.62.184.87 + } + } + rule 3117 { + action accept + description FW5A5D7_3-TCP-ALLOW-51.219.31.78 + destination { + group { + address-group DT_FW5A5D7_3 + } + port 8172,3389 + } + protocol tcp + source { + address 51.219.31.78 + } + } + rule 3118 { + action accept + description VPN-26157-ANY-ALLOW-10.4.86.57 + destination { + group { + address-group DT_VPN-26157 + } + } + source { + address 10.4.86.57 + } + } + rule 3119 { + action accept + description VPN-26157-ANY-ALLOW-10.4.87.57 + destination { + group { + address-group DT_VPN-26157 + } + } + source { + address 10.4.87.57 + } + } + rule 3120 { + action accept + description FWA7625_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA7625_1 + } + port 943 + } + protocol tcp + } + rule 3121 { + action accept + description FWC96A1_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC96A1_1 + } + port 1194 + } + protocol udp + } + rule 3122 { + action accept + description FWA7625_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA7625_1 + } + port 1194 + } + protocol udp + } + rule 3123 { + action accept + description FWA7625_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA7625_1 + } + port 32400,10108 + } + protocol tcp_udp + } + rule 3125 { + action accept + description FW8A3FC_3-TCP-ALLOW-185.173.161.154 + destination { + group { + address-group DT_FW8A3FC_3 + } + port 465 + } + protocol tcp + source { + address 185.173.161.154 + } + } + rule 3127 { + action accept + description FW05339_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW05339_1 + } + port 46961 + } + protocol udp + } + rule 3130 { + action accept + description FWA0AA0_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA0AA0_1 + } + port 1194 + } + protocol udp + } + rule 3132 { + action accept + description FWD8DD1_2-TCP_UDP-ALLOW-77.153.164.226 + destination { + group { + address-group DT_FWD8DD1_2 + } + port 443,80 + } + protocol tcp_udp + source { + address 77.153.164.226 + } + } + rule 3134 { + action accept + description FW19987_4-TCP-ALLOW-87.224.6.174 + destination { + group { + address-group DT_FW19987_4 + } + port 3389,445,443 + } + protocol tcp + source { + address 87.224.6.174 + } + } + rule 3135 { + action accept + description FW40AE4_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW40AE4_1 + } + port 53 + } + protocol tcp_udp + } + rule 3136 { + action accept + description VPN-33204-ANY-ALLOW-10.4.57.176 + destination { + group { + address-group DT_VPN-33204 + } + } + source { + address 10.4.57.176 + } + } + rule 3137 { + action accept + description FWF3A1B_1-TCP_UDP-ALLOW-86.132.125.4 + destination { + group { + address-group DT_FWF3A1B_1 + } + port 2222 + } + protocol tcp_udp + source { + address 86.132.125.4 + } + } + rule 3138 { + action accept + description FWF3A1B_1-TCP_UDP-ALLOW-91.205.173.51 + destination { + group { + address-group DT_FWF3A1B_1 + } + port 2222 + } + protocol tcp_udp + source { + address 91.205.173.51 + } + } + rule 3143 { + action accept + description FWA86ED_101-TCP-ALLOW-109.149.121.73 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 109.149.121.73 + } + } + rule 3144 { + action accept + description FWA0AA0_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA0AA0_1 + } + port 28083,28015-28016,1935 + } + protocol tcp_udp + } + rule 3146 { + action accept + description FWF3A1B_1-TCP_UDP-ALLOW-92.233.27.144 + destination { + group { + address-group DT_FWF3A1B_1 + } + port 2222 + } + protocol tcp_udp + source { + address 92.233.27.144 + } + } + rule 3148 { + action accept + description FWA86ED_101-TCP-ALLOW-151.228.194.190 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 151.228.194.190 + } + } + rule 3149 { + action accept + description FW9B6FB_1-ICMP-ALLOW-77.68.89.115_32 + destination { + group { + address-group DT_FW9B6FB_1 + } + } + protocol icmp + source { + address 77.68.89.115/32 + } + } + rule 3153 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.199 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.199 + } + } + rule 3155 { + action accept + description FW45F3D_1-ANY-ALLOW-195.224.110.168 + destination { + group { + address-group DT_FW45F3D_1 + } + } + source { + address 195.224.110.168 + } + } + rule 3156 { + action accept + description FWF8E67_1-TCP-ALLOW-82.14.188.35 + destination { + group { + address-group DT_FWF8E67_1 + } + port 22 + } + protocol tcp + source { + address 82.14.188.35 + } + } + rule 3157 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.58 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.58 + } + } + rule 3158 { + action accept + description VPN-19992-ANY-ALLOW-10.4.87.158 + destination { + group { + address-group DT_VPN-19992 + } + } + source { + address 10.4.87.158 + } + } + rule 3159 { + action accept + description FWA86ED_101-TCP-ALLOW-5.66.24.185 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 5.66.24.185 + } + } + rule 3160 { + action accept + description FWF8E67_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF8E67_1 + } + port 3001 + } + protocol tcp + } + rule 3161 { + action accept + description FWD2440_1-AH-ALLOW-ANY + destination { + group { + address-group DT_FWD2440_1 + } + } + protocol ah + } + rule 3166 { + action accept + description FW3EBC8_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW3EBC8_1 + } + port 9001-9900,9000 + } + protocol tcp + } + rule 3167 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.244 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.244 + } + } + rule 3168 { + action accept + description FWA0531_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA0531_1 + } + port 3000 + } + protocol tcp + } + rule 3170 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.137 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.137 + } + } + rule 3173 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.104 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.104 + } + } + rule 3176 { + action accept + description FW6906B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW6906B_1 + } + port 4190 + } + protocol tcp + } + rule 3177 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.246.230 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 116.206.246.230 + } + } + rule 3178 { + action accept + description FW444AF_1-TCP-ALLOW-91.135.10.140 + destination { + group { + address-group DT_FW444AF_1 + } + port 27017 + } + protocol tcp + source { + address 91.135.10.140 + } + } + rule 3180 { + action accept + description FWA86ED_101-TCP-ALLOW-81.150.13.34 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 81.150.13.34 + } + } + rule 3181 { + action accept + description FWA86ED_101-TCP-ALLOW-82.10.14.73 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 82.10.14.73 + } + } + rule 3183 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.25 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.25 + } + } + rule 3184 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.224 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.224 + } + } + rule 3185 { + action accept + description FW9B6FB_1-TCP-ALLOW-77.68.89.115_32 + destination { + group { + address-group DT_FW9B6FB_1 + } + port 10050 + } + protocol tcp + source { + address 77.68.89.115/32 + } + } + rule 3186 { + action accept + description VPN-14673-ANY-ALLOW-10.4.89.44 + destination { + group { + address-group DT_VPN-14673 + } + } + source { + address 10.4.89.44 + } + } + rule 3187 { + action accept + description FWCA628_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWCA628_1 + } + port 2096,2095,2087,2086,2083,2082 + } + protocol tcp + } + rule 3189 { + action accept + description VPN-28484-ANY-ALLOW-10.4.58.159 + destination { + group { + address-group DT_VPN-28484 + } + } + source { + address 10.4.58.159 + } + } + rule 3190 { + action accept + description FW028C0_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW028C0_2 + } + port 44491-44498,44474 + } + protocol tcp + } + rule 3191 { + action accept + description VPN-28484-ANY-ALLOW-10.4.59.159 + destination { + group { + address-group DT_VPN-28484 + } + } + source { + address 10.4.59.159 + } + } + rule 3192 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.119 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.119 + } + } + rule 3194 { + action accept + description FWF699D_4-TCP-ALLOW-195.74.108.130 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 195.74.108.130 + } + } + rule 3195 { + action accept + description FWF699D_4-TCP-ALLOW-31.54.149.143 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 31.54.149.143 + } + } + rule 3196 { + action accept + description FWF699D_4-TCP-ALLOW-35.204.243.120 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 35.204.243.120 + } + } + rule 3197 { + action accept + description FWF699D_4-TCP-ALLOW-81.150.55.65 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 81.150.55.65 + } + } + rule 3198 { + action accept + description FWF699D_4-TCP-ALLOW-81.150.55.70 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 81.150.55.70 + } + } + rule 3199 { + action accept + description FWF699D_4-TCP-ALLOW-86.142.112.4 + destination { + group { + address-group DT_FWF699D_4 + } + port 3389 + } + protocol tcp + source { + address 86.142.112.4 + } + } + rule 3200 { + action accept + description FWF699D_4-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF699D_4 + } + port 8983 + } + protocol tcp_udp + } + rule 3201 { + action accept + description FWF699D_4-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF699D_4 + } + port 11009,10009 + } + protocol tcp + } + rule 3202 { + action accept + description VPN-2661-ANY-ALLOW-10.4.54.24 + destination { + group { + address-group DT_VPN-2661 + } + } + source { + address 10.4.54.24 + } + } + rule 3203 { + action accept + description VPN-2661-ANY-ALLOW-10.4.55.24 + destination { + group { + address-group DT_VPN-2661 + } + } + source { + address 10.4.55.24 + } + } + rule 3204 { + action accept + description VPN-9727-ANY-ALLOW-10.4.54.118 + destination { + group { + address-group DT_VPN-9727 + } + } + source { + address 10.4.54.118 + } + } + rule 3205 { + action accept + description VPN-9727-ANY-ALLOW-10.4.55.119 + destination { + group { + address-group DT_VPN-9727 + } + } + source { + address 10.4.55.119 + } + } + rule 3207 { + action accept + description FWF0221_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF0221_1 + } + port 65000,8099,8080 + } + protocol tcp_udp + } + rule 3208 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.180 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.180 + } + } + rule 3209 { + action accept + description FWA86ED_101-TCP-ALLOW-82.5.189.5 + destination { + group { + address-group DT_FWA86ED_101 + } + port 443 + } + protocol tcp + source { + address 82.5.189.5 + } + } + rule 3210 { + action accept + description FW60FD6_5-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW60FD6_5 + } + port 1194 + } + protocol udp + } + rule 3211 { + action accept + description FW60FD6_5-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW60FD6_5 + } + port 9500,9191,9090,8090,2222 + } + protocol tcp + } + rule 3212 { + action accept + description FWA86ED_101-TCP-ALLOW-84.65.217.114 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 84.65.217.114 + } + } + rule 3213 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.43.21 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.43.21 + } + } + rule 3214 { + action accept + description FW45F3D_1-ANY-ALLOW-77.68.126.251 + destination { + group { + address-group DT_FW45F3D_1 + } + } + source { + address 77.68.126.251 + } + } + rule 3215 { + action accept + description FWA86ED_101-TCP-ALLOW-86.14.23.23 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 86.14.23.23 + } + } + rule 3217 { + action accept + description FW85E02_11-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW85E02_11 + } + port 9000-10999 + } + protocol udp + } + rule 3218 { + action accept + description FW5D0FA_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW5D0FA_1 + } + port 53 + } + protocol tcp_udp + } + rule 3222 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.141 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.141 + } + } + rule 3223 { + action accept + description FWCDD8B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWCDD8B_1 + } + port 2222 + } + protocol tcp + } + rule 3224 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.185 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.185 + } + } + rule 3225 { + action accept + description FW06940_3-TCP_UDP-ALLOW-213.171.210.153 + destination { + group { + address-group DT_FW06940_3 + } + port 1-65535 + } + protocol tcp_udp + source { + address 213.171.210.153 + } + } + rule 3226 { + action accept + description FW06940_3-TCP_UDP-ALLOW-70.29.113.102 + destination { + group { + address-group DT_FW06940_3 + } + port 1-65535 + } + protocol tcp_udp + source { + address 70.29.113.102 + } + } + rule 3227 { + action accept + description FWC32BE_1-ANY-ALLOW-3.127.0.177 + destination { + group { + address-group DT_FWC32BE_1 + } + } + source { + address 3.127.0.177 + } + } + rule 3228 { + action accept + description FWA86ED_101-TCP-ALLOW-93.115.195.58 + destination { + group { + address-group DT_FWA86ED_101 + } + port 3389,443 + } + protocol tcp + source { + address 93.115.195.58 + } + } + rule 3229 { + action accept + description FWE32F2_8-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE32F2_8 + } + port 40120,30120,30110 + } + protocol tcp + } + rule 3230 { + action accept + description VPN-28515-ANY-ALLOW-10.4.56.162 + destination { + group { + address-group DT_VPN-28515 + } + } + source { + address 10.4.56.162 + } + } + rule 3231 { + action accept + description FW06940_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW06940_3 + } + port 30000-30400,8443-8447,445,80-110,21-25 + } + protocol tcp + } + rule 3232 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.134 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.211.134 + } + } + rule 3236 { + action accept + description VPN-28515-ANY-ALLOW-10.4.57.162 + destination { + group { + address-group DT_VPN-28515 + } + } + source { + address 10.4.57.162 + } + } + rule 3237 { + action accept + description FWF4063_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF4063_1 + } + port 3000 + } + protocol tcp + } + rule 3240 { + action accept + description FW06940_3-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW06940_3 + } + port 49152-65535,6379,5666,5432-5454 + } + protocol tcp_udp + } + rule 3242 { + action accept + description FW2E8D4_1-TCP-ALLOW-63.35.92.185 + destination { + group { + address-group DT_FW2E8D4_1 + } + port 3389 + } + protocol tcp + source { + address 63.35.92.185 + } + } + rule 3244 { + action accept + description FWF30BD_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWF30BD_1 + } + port 9000-10999 + } + protocol udp + } + rule 3245 { + action accept + description FWE30A1_4-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWE30A1_4 + } + port 65057 + } + protocol tcp_udp + } + rule 3246 { + action accept + description VPN-26772-ANY-ALLOW-10.4.54.123 + destination { + group { + address-group DT_VPN-26772 + } + } + source { + address 10.4.54.123 + } + } + rule 3249 { + action accept + description FW56496_1-ANY-ALLOW-77.68.82.49 + destination { + group { + address-group DT_FW56496_1 + } + } + source { + address 77.68.82.49 + } + } + rule 3251 { + action accept + description FWDA443_6-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWDA443_6 + } + port 30175,12050 + } + protocol tcp + } + rule 3253 { + action accept + description FW5A521_3-TCP-ALLOW-88.98.75.17 + destination { + group { + address-group DT_FW5A521_3 + } + port 22 + } + protocol tcp + source { + address 88.98.75.17 + } + } + rule 3254 { + action accept + description FW5A521_3-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW5A521_3 + } + port 161-162 + } + protocol udp + } + rule 3255 { + action accept + description FW5A521_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW5A521_3 + } + port 5900 + } + protocol tcp + } + rule 3259 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.178 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.214.178 + } + } + rule 3260 { + action accept + description VPN-26772-ANY-ALLOW-10.4.55.124 + destination { + group { + address-group DT_VPN-26772 + } + } + source { + address 10.4.55.124 + } + } + rule 3262 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.114 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.114 + } + } + rule 3272 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.246.30 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 116.206.246.30 + } + } + rule 3273 { + action accept + description FW2B4BA_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW2B4BA_1 + } + port 30000-31000 + } + protocol tcp + } + rule 3284 { + action accept + description FW06940_3-TCP-ALLOW-213.171.217.107 + destination { + group { + address-group DT_FW06940_3 + } + port 8443 + } + protocol tcp + source { + address 213.171.217.107 + } + } + rule 3285 { + action accept + description FW0952B_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0952B_1 + } + port 9030,9001 + } + protocol tcp + } + rule 3286 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.85.35 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.85.35 + } + } + rule 3290 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.232 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.208.232 + } + } + rule 3294 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.21 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.21 + } + } + rule 3295 { + action accept + description FW0EA3F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW0EA3F_1 + } + port 1-65535 + } + protocol tcp_udp + } + rule 3296 { + action accept + description FW9D5C7_1-TCP-ALLOW-209.97.176.108 + destination { + group { + address-group DT_FW9D5C7_1 + } + port 8447,8443,22 + } + protocol tcp + source { + address 209.97.176.108 + } + } + rule 3297 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.188 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.188 + } + } + rule 3298 { + action accept + description FW9D5C7_1-TCP-ALLOW-165.227.231.227 + destination { + group { + address-group DT_FW9D5C7_1 + } + port 9117,9113,9104,9100 + } + protocol tcp + source { + address 165.227.231.227 + } + } + rule 3299 { + action accept + description FW4DB0A_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4DB0A_1 + } + port 953 + } + protocol tcp + } + rule 3300 { + action accept + description FW4DB0A_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW4DB0A_1 + } + port 953 + } + protocol udp + } + rule 3301 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.91 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.91 + } + } + rule 3303 { + action accept + description FW56496_1-TCP-ALLOW-176.255.93.149 + destination { + group { + address-group DT_FW56496_1 + } + port 3389 + } + protocol tcp + source { + address 176.255.93.149 + } + } + rule 3304 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.79 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.79 + } + } + rule 3305 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.43 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.43 + } + } + rule 3306 { + action accept + description FW310C6_3-ANY-ALLOW-88.208.198.40 + destination { + group { + address-group DT_FW310C6_3 + } + } + source { + address 88.208.198.40 + } + } + rule 3307 { + action accept + description FW597A6_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW597A6_1 + } + port 49152-65535,990 + } + protocol tcp + } + rule 3308 { + action accept + description FW597A6_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW597A6_1 + } + port 3306 + } + protocol tcp_udp + } + rule 3309 { + action accept + description FWBC280_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBC280_1 + } + port 49152-65535,20-21 + } + protocol tcp + } + rule 3310 { + action accept + description VPN-31301-ANY-ALLOW-10.4.87.223 + destination { + group { + address-group DT_VPN-31301 + } + } + source { + address 10.4.87.223 + } + } + rule 3311 { + action accept + description FW18E6E_3-TCP-ALLOW-148.253.173.243 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306 + } + protocol tcp + source { + address 148.253.173.243 + } + } + rule 3312 { + action accept + description FW9EEDD_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW9EEDD_1 + } + port 990,197,20-23 + } + protocol tcp + } + rule 3313 { + action accept + description FW9EEDD_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW9EEDD_1 + } + port 49152-65535 + } + protocol tcp_udp + } + rule 3314 { + action accept + description VPN-31002-ANY-ALLOW-10.4.89.126 + destination { + group { + address-group DT_VPN-31002 + } + } + source { + address 10.4.89.126 + } + } + rule 3316 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.11 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.11 + } + } + rule 3317 { + action accept + description FW32EFF_49-TCP-ALLOW-195.59.191.128_25 + destination { + group { + address-group DT_FW32EFF_49 + } + port 5589 + } + protocol tcp + source { + address 195.59.191.128/25 + } + } + rule 3318 { + action accept + description FW32EFF_49-TCP-ALLOW-213.71.130.0_26 + destination { + group { + address-group DT_FW32EFF_49 + } + port 5589 + } + protocol tcp + source { + address 213.71.130.0/26 + } + } + rule 3319 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.88 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.215.88 + } + } + rule 3320 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.215.173 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.215.173 + } + } + rule 3321 { + action accept + description FW32EFF_49-TCP-ALLOW-84.19.45.82 + destination { + group { + address-group DT_FW32EFF_49 + } + port 5589 + } + protocol tcp + source { + address 84.19.45.82 + } + } + rule 3322 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-175.157.43.122 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 175.157.43.122 + } + } + rule 3323 { + action accept + description FWC1ACD_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWC1ACD_1 + } + port 28061,28060,8080 + } + protocol tcp_udp + } + rule 3324 { + action accept + description FWA5D67_1-TCP_UDP-ALLOW-84.74.32.74 + destination { + group { + address-group DT_FWA5D67_1 + } + port 3389 + } + protocol tcp_udp + source { + address 84.74.32.74 + } + } + rule 3325 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.169 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.169 + } + } + rule 3326 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.89 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.89 + } + } + rule 3329 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.35 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.35 + } + } + rule 3330 { + action accept + description FWCE020_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWCE020_1 + } + port 48402 + } + protocol udp + } + rule 3333 { + action accept + description FWF3574_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWF3574_1 + } + port 8060,445,139 + } + protocol tcp + } + rule 3334 { + action accept + description FWE6AB2_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWE6AB2_1 + } + port 44158,945,943 + } + protocol tcp + } + rule 3335 { + action accept + description FWBFC02_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBFC02_1 + } + port 44158,945,943 + } + protocol tcp + } + rule 3336 { + action accept + description FWBFC02_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWBFC02_1 + } + port 1194 + } + protocol udp + } + rule 3337 { + action accept + description FWE6AB2_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWE6AB2_1 + } + port 1194 + } + protocol udp + } + rule 3338 { + action accept + description FWBC8A6_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWBC8A6_1 + } + port 44158,945,943 + } + protocol tcp + } + rule 3339 { + action accept + description FWBC8A6_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FWBC8A6_1 + } + port 1194 + } + protocol udp + } + rule 3340 { + action accept + description FWA0AA0_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWA0AA0_1 + } + port 2302 + } + protocol tcp + } + rule 3342 { + action accept + description FW56496_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW56496_1 + } + port 22 + } + protocol tcp_udp + } + rule 3343 { + action accept + description FW56496_1-TCP-ALLOW-157.231.178.162 + destination { + group { + address-group DT_FW56496_1 + } + port 21 + } + protocol tcp + source { + address 157.231.178.162 + } + } + rule 3344 { + action accept + description FW56496_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW56496_1 + } + port 2443,1022 + } + protocol tcp + } + rule 3345 { + action accept + description FW56496_1-TCP_UDP-ALLOW-46.16.211.142 + destination { + group { + address-group DT_FW56496_1 + } + port 3389,21 + } + protocol tcp_udp + source { + address 46.16.211.142 + } + } + rule 3347 { + action accept + description FW2379F_14-GRE-ALLOW-ANY + destination { + group { + address-group DT_FW2379F_14 + } + } + protocol gre + } + rule 3348 { + action accept + description FW0E383_9-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0E383_9 + } + port 52000 + } + protocol tcp + } + rule 3350 { + action accept + description FWB4438_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWB4438_2 + } + port 993-995,7 + } + protocol tcp + } + rule 3351 { + action accept + description FW1F3D0_6-TCP_UDP-ALLOW-82.165.207.109 + destination { + group { + address-group DT_FW1F3D0_6 + } + port 4567-4568 + } + protocol tcp_udp + source { + address 82.165.207.109 + } + } + rule 3352 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.77 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.77 + } + } + rule 3358 { + action accept + description FW46F4A_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW46F4A_1 + } + port 51820 + } + protocol udp + } + rule 3359 { + action accept + description FW53C72_1-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW53C72_1 + } + port 48402 + } + protocol udp + } + rule 3360 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.251 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.210.251 + } + } + rule 3362 { + action accept + description FWAA38E_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWAA38E_1 + } + port 1001-65535 + } + protocol tcp_udp + } + rule 3363 { + action accept + description FW138F8_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FW138F8_1 + } + port 21,20 + } + protocol tcp_udp + } + rule 3364 { + action accept + description FW0BD92_3-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW0BD92_3 + } + port 18081,18080 + } + protocol tcp + } + rule 3365 { + action accept + description FWFEF05_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWFEF05_1 + } + port 1935 + } + protocol tcp_udp + } + rule 3367 { + action accept + description FW26846_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW26846_1 + } + port 8000 + } + protocol tcp + } + rule 3368 { + action accept + description FWB4438_2-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWB4438_2 + } + port 53 + } + protocol tcp_udp + } + rule 3369 { + action accept + description FWA884B_5-TCP-ALLOW-51.146.16.162 + destination { + group { + address-group DT_FWA884B_5 + } + port 8447,8443,22 + } + protocol tcp + source { + address 51.146.16.162 + } + } + rule 3370 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.22 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.22 + } + } + rule 3371 { + action accept + description FWFDE34_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWFDE34_1 + } + port 18081,18080 + } + protocol tcp + } + rule 3373 { + action accept + description FWB6101_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWB6101_1 + } + port 2280 + } + protocol tcp + } + rule 3377 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-123.231.84.203 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 123.231.84.203 + } + } + rule 3378 { + action accept + description FW1D511_2-TCP-ALLOW-92.29.46.47 + destination { + group { + address-group DT_FW1D511_2 + } + port 9090 + } + protocol tcp + source { + address 92.29.46.47 + } + } + rule 3386 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.208.175 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.208.175 + } + } + rule 3387 { + action accept + description FW1ACD9_2-TCP-ALLOW-89.197.148.38 + destination { + group { + address-group DT_FW1ACD9_2 + } + port 5015,22 + } + protocol tcp + source { + address 89.197.148.38 + } + } + rule 3388 { + action accept + description FW1ACD9_2-UDP-ALLOW-ANY + destination { + group { + address-group DT_FW1ACD9_2 + } + port 9000-10999,5090,5060 + } + protocol udp + } + rule 3389 { + action accept + description FW1ACD9_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW1ACD9_2 + } + port 5090,5060-5062 + } + protocol tcp + } + rule 3391 { + action accept + description FWA0B7F_1-TCP_UDP-ALLOW-ANY + destination { + group { + address-group DT_FWA0B7F_1 + } + port 53 + } + protocol tcp_udp + } + rule 3392 { + action accept + description FW56335_2-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW56335_2 + } + port 18081,18080 + } + protocol tcp + } + rule 3395 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.90 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.212.90 + } + } + rule 3396 { + action accept + description FW4D3E6_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW4D3E6_1 + } + port 18081,18080 + } + protocol tcp + } + rule 3397 { + action accept + description FWB118A_1-TCP-ALLOW-188.65.177.58 + destination { + group { + address-group DT_FWB118A_1 + } + port 49152-65534,8447,8443,22,21,20 + } + protocol tcp + source { + address 188.65.177.58 + } + } + rule 3398 { + action accept + description FWB118A_1-TCP-ALLOW-77.68.103.13 + destination { + group { + address-group DT_FWB118A_1 + } + port 49152-65534,8447,8443,22,21,20 + } + protocol tcp + source { + address 77.68.103.13 + } + } + rule 3399 { + action accept + description FWB118A_1-TCP-ALLOW-80.5.71.130 + destination { + group { + address-group DT_FWB118A_1 + } + port 49152-65534,8447,8443,22,21,20 + } + protocol tcp + source { + address 80.5.71.130 + } + } + rule 3402 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.205 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.205 + } + } + rule 3408 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.211.31 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.211.31 + } + } + rule 3409 { + action accept + description FW539FB_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FW539FB_1 + } + port 389 + } + protocol tcp + } + rule 3411 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.185 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.213.185 + } + } + rule 3415 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-116.206.245.124 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 116.206.245.124 + } + } + rule 3416 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.213.75 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.213.75 + } + } + rule 3417 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.34 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.214.34 + } + } + rule 3418 { + action accept + description FWEF92E_5-UDP-ALLOW-77.68.77.70 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 77.68.77.70 + } + } + rule 3419 { + action accept + description FWEF92E_5-UDP-ALLOW-77.68.92.33 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 77.68.92.33 + } + } + rule 3420 { + action accept + description FWEF92E_5-UDP-ALLOW-77.68.93.82 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 77.68.93.82 + } + } + rule 3421 { + action accept + description FWEF92E_5-UDP-ALLOW-88.208.198.93 + destination { + group { + address-group DT_FWEF92E_5 + } + port 500 + } + protocol udp + source { + address 88.208.198.93 + } + } + rule 3422 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.94 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.94 + } + } + rule 3424 { + action accept + description FW18E6E_3-TCP-ALLOW-148.253.173.244 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306 + } + protocol tcp + source { + address 148.253.173.244 + } + } + rule 3425 { + action accept + description FW18E6E_3-TCP-ALLOW-148.253.173.246 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306 + } + protocol tcp + source { + address 148.253.173.246 + } + } + rule 3426 { + action accept + description FW18E6E_3-TCP-ALLOW-195.97.222.122 + destination { + group { + address-group DT_FW18E6E_3 + } + port 3306 + } + protocol tcp + source { + address 195.97.222.122 + } + } + rule 3431 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.111 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.209.111 + } + } + rule 3432 { + action accept + description FW06940_3-TCP_UDP-ALLOW-74.208.41.119 + destination { + group { + address-group DT_FW06940_3 + } + port 1-65535 + } + protocol tcp_udp + source { + address 74.208.41.119 + } + } + rule 3438 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.252 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.252 + } + } + rule 3440 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.118 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.214.118 + } + } + rule 3442 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.209.15 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.209.15 + } + } + rule 3446 { + action accept + description FWC32BE_1-ANY-ALLOW-3.65.3.75 + destination { + group { + address-group DT_FWC32BE_1 + } + } + source { + address 3.65.3.75 + } + } + rule 3447 { + action accept + description FWC32BE_1-TCP-ALLOW-217.155.2.52 + destination { + group { + address-group DT_FWC32BE_1 + } + port 22 + } + protocol tcp + source { + address 217.155.2.52 + } + } + rule 3448 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.243 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.214.243 + } + } + rule 3449 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.214.117 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000,3389 + } + protocol tcp_udp + source { + address 112.134.214.117 + } + } + rule 3450 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.4 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.210.4 + } + } + rule 3452 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.210.177 + destination { + group { + address-group DT_FWA7A50_1 + } + port 9000 + } + protocol tcp_udp + source { + address 112.134.210.177 + } + } + rule 3454 { + action accept + description FWD498E_1-TCP-ALLOW-ANY + destination { + group { + address-group DT_FWD498E_1 + } + port 44158 + } + protocol tcp + } + rule 3455 { + action accept + description FWA7A50_1-TCP_UDP-ALLOW-112.134.212.147 + destination { + group { + address-group DT_FWA7A50_1 + } + port 3389 + } + protocol tcp_udp + source { + address 112.134.212.147 + } + } + } + receive-redirects disable + send-redirects disable + source-validation disable + state-policy { + established { + action accept + } + invalid { + action drop + } + related { + action accept + } + } + syn-cookies enable + twa-hazards-protection disable +} +high-availability { + vrrp { + group eth3-90 { + advertise-interval 3 + authentication { + password Ng-1p90 + type plaintext-password + } + interface eth3 + preempt-delay 30 + priority 10 + virtual-address 10.255.255.1/32 + virtual-address 169.254.169.254/32 + vrid 90 + } + sync-group VRRP-GROUP { + member eth3-90 + } + } +} +interfaces { + ethernet eth0 { + address 10.4.35.105/24 + description Management + duplex auto + smp-affinity auto + speed auto + } + ethernet eth1 { + description MicroVLANs + duplex auto + smp-affinity auto + speed auto + vif 3201 { + address 109.228.63.251/25 + description "MicroVLAN publica" + firewall { + in { + name WAN-INBOUND + } + local { + name LOCAL-WAN + } + } + } + } + ethernet eth2 { + address 10.4.51.133/30 + description Sync + duplex auto + firewall { + local { + name LOCAL-SYNC + } + } + smp-affinity auto + speed auto + } + ethernet eth3 { + address 10.255.255.2/20 + description "Customers LAN" + duplex auto + firewall { + in { + name LAN-INBOUND + } + local { + name LOCAL-LAN + } + } + smp-affinity auto + speed auto + } + loopback lo { + address 10.4.35.105/32 + } +} +nat { + destination { + rule 5 { + description cloud-init + destination { + address 169.254.169.254 + port http + } + inbound-interface eth3 + protocol tcp + translation { + address 82.223.45.35 + } + } + rule 20 { + description "TEMPORARY NAT for dnscache removal in favor of anycns" + destination { + address 77.68.76.12 + port domain + } + inbound-interface eth3 + protocol tcp_udp + translation { + address 212.227.123.16 + } + } + rule 25 { + description "TEMPORARY NAT for dnscache removal in favor of anycns" + destination { + address 77.68.77.12 + port domain + } + inbound-interface eth3 + protocol tcp_udp + translation { + address 212.227.123.17 + } + } + } +} +policy { + community-list 100 { + rule 10 { + action permit + regex 65500:1001 + } + } + community-list 200 { + rule 10 { + action permit + regex "65500:10**" + } + } + prefix-list Service-NETs { + rule 1 { + action permit + ge 32 + prefix 0.0.0.0/0 + } + } + route-map Any-Site-1 { + rule 10 { + action permit + match { + community { + community-list 200 + } + } + } + rule 20 { + action deny + } + } + route-map CLOUD-Service-NETs { + rule 10 { + action permit + match { + ip { + address { + prefix-list Service-NETs + } + } + } + set { + community 65500:1027 + } + } + rule 20 { + action deny + } + } + route-map None { + rule 10 { + action deny + } + } +} +protocols { + bgp 8560 { + address-family { + ipv4-unicast { + redistribute { + static { + } + } + } + } + neighbor 109.228.63.134 { + address-family { + ipv4-unicast { + route-map { + export CLOUD-Service-NETs + import Any-Site-1 + } + weight 150 + } + } + description RouteServer1-vyos + password VyOS123 + remote-as 8560 + timers { + holdtime 5 + keepalive 1 + } + } + neighbor 109.228.63.135 { + address-family { + ipv4-unicast { + route-map { + export CLOUD-Service-NETs + import Any-Site-1 + } + weight 125 + } + } + description RouteServer2-quagga + password VyOS123 + remote-as 8560 + } + neighbor 109.228.63.136 { + address-family { + ipv4-unicast { + route-map { + export CLOUD-Service-NETs + import Any-Site-1 + } + weight 100 + } + } + description RouteServer3-bird + password VyOS123 + remote-as 8560 + } + parameters { + log-neighbor-changes + router-id 10.4.35.105 + } + } + static { + interface-route 77.68.2.215/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.3.52/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.3.61/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.3.80/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.3.121/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.3.144/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.3.161/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.3.194/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.3.247/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.22/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.24/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.25/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.39/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.57/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.74/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.80/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.111/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.136/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.180/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.242/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.4.252/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.5.95/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.5.125/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.5.155/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.5.166/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.5.187/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.5.241/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.6.32/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.6.105/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.6.110/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.6.119/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.6.202/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.6.210/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.7.67/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.7.114/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.7.123/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.7.160/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.7.172/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.7.186/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.7.222/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.7.227/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.8.144/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.9.75/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.9.186/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.10.142/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.10.152/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.10.170/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.11.140/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.12.45/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.12.195/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.12.250/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.13.76/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.13.137/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.14.88/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.15.95/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.16.247/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.17.26/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.17.186/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.17.200/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.20.161/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.20.217/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.20.231/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.21.78/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.21.171/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.22.146/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.23.35/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.23.64/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.23.112/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.23.158/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.24.59/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.24.63/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.24.112/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.24.134/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.24.172/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.24.220/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.25.124/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.25.130/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.25.146/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.26.166/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.26.216/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.26.221/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.26.228/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.27.18/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.27.27/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.27.28/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.27.54/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.27.57/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.27.211/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.28.139/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.28.145/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.28.147/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.28.207/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.29.65/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.29.178/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.30.133/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.30.164/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.31.96/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.31.144/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.32.31/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.32.43/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.32.83/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.32.86/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.32.89/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.32.118/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.32.254/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.33.24/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.33.37/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.33.48/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.33.68/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.33.171/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.33.197/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.33.216/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.34.26/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.34.28/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.34.50/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.34.138/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.34.139/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.35.116/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.48.14/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.48.81/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.48.89/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.48.105/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.48.202/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.49.4/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.49.12/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.49.126/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.49.152/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.49.159/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.49.160/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.49.161/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.49.178/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.50.90/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.50.91/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.50.142/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.50.193/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.50.198/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.51.202/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.51.214/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.72.202/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.72.254/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.73.73/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.74.39/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.74.85/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.74.152/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.74.209/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.74.232/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.75.45/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.75.64/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.75.113/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.75.245/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.75.253/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.12/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.13/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.14/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.16/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.19/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.20/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.21/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.22/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.23/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.25/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.26/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.29/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.30/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.31/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.33/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.35/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.37/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.38/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.39/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.40/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.42/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.44/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.45/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.47/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.48/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.49/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.50/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.54/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.55/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.57/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.58/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.59/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.60/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.61/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.74/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.75/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.76/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.77/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.80/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.88/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.91/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.92/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.93/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.94/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.95/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.96/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.99/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.102/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.104/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.105/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.107/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.108/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.110/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.111/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.112/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.114/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.115/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.116/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.118/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.120/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.122/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.123/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.124/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.126/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.127/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.136/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.137/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.138/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.139/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.141/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.142/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.145/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.148/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.149/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.150/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.152/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.157/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.158/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.160/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.161/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.164/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.165/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.169/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.171/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.176/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.177/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.181/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.183/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.185/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.187/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.191/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.195/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.197/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.198/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.200/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.202/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.203/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.208/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.209/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.211/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.212/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.217/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.219/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.220/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.228/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.229/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.231/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.234/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.235/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.239/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.241/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.243/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.244/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.245/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.247/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.248/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.249/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.250/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.251/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.252/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.253/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.76.254/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.12/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.13/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.14/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.16/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.19/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.21/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.22/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.24/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.26/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.29/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.30/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.32/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.33/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.37/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.38/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.42/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.43/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.44/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.46/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.49/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.50/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.53/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.54/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.56/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.57/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.59/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.62/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.63/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.65/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.67/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.68/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.69/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.70/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.71/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.72/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.74/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.75/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.76/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.77/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.79/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.81/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.85/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.88/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.90/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.92/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.95/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.97/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.99/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.100/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.102/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.103/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.105/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.107/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.108/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.114/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.115/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.117/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.120/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.124/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.128/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.129/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.130/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.132/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.137/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.139/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.140/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.141/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.144/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.145/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.149/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.150/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.151/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.152/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.156/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.157/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.159/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.160/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.161/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.163/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.165/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.171/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.174/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.176/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.178/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.181/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.185/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.190/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.192/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.199/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.200/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.201/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.202/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.203/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.204/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.205/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.207/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.208/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.209/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.211/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.212/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.214/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.215/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.219/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.221/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.222/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.227/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.228/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.231/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.233/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.234/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.236/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.238/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.239/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.240/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.243/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.247/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.248/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.249/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.251/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.253/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.77.254/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.78.73/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.78.113/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.78.229/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.79.82/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.79.89/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.79.206/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.80.26/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.80.97/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.81.44/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.81.141/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.81.218/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.82.147/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.82.157/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.83.41/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.84.147/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.84.155/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.85.18/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.85.27/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.85.73/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.85.115/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.85.172/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.86.40/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.86.148/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.87.164/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.87.212/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.88.100/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.88.164/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.89.72/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.89.183/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.89.247/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.90.106/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.90.132/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.91.22/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.91.128/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.91.195/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.92.92/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.92.186/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.93.125/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.93.164/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.93.246/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.94.181/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.95.42/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.95.212/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.100.77/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.100.132/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.100.134/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.100.150/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.100.167/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.101.64/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.101.124/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.101.125/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.102.5/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.102.129/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.103.19/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.103.56/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.103.120/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.103.147/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.103.227/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.112.75/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.112.83/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.112.90/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.112.91/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.112.167/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.112.175/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.112.184/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.112.213/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.112.248/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.113.117/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.113.164/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.114.93/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.114.136/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.114.183/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.114.205/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.114.234/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.114.237/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.115.17/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.115.142/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.116.36/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.116.52/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.116.84/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.116.119/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.116.183/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.116.220/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.116.221/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.116.232/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.117.29/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.117.45/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.117.51/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.117.142/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.117.173/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.117.202/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.117.214/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.117.222/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.118.15/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.118.17/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.118.86/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.118.88/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.118.102/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.118.104/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.118.120/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.119.14/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.119.92/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.119.188/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.120.26/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.120.31/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.120.45/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.120.146/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.120.218/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.120.229/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.120.241/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.120.249/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.121.94/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.121.106/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.121.119/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.121.127/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.122.89/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.122.195/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.122.241/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.123.177/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.123.250/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.125.32/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.125.60/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.125.218/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.126.14/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.126.22/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.126.51/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.126.101/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.126.160/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.127.151/32 { + next-hop-interface eth3 { + } + } + interface-route 77.68.127.172/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.196.91/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.196.92/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.196.123/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.196.154/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.197.10/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.197.23/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.197.60/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.197.118/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.197.129/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.197.135/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.197.150/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.197.155/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.197.160/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.197.208/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.198.39/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.198.64/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.198.66/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.198.69/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.198.92/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.198.251/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.199.46/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.199.141/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.199.233/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.199.249/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.212.31/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.212.94/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.212.182/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.212.188/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.215.19/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.215.61/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.215.62/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.215.121/32 { + next-hop-interface eth3 { + } + } + interface-route 88.208.215.157/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.35.84/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.35.110/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.36.37/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.36.79/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.36.119/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.36.174/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.36.194/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.36.229/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.37.10/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.37.114/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.37.174/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.37.187/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.37.240/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.38.117/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.38.171/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.38.201/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.39.41/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.39.151/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.39.157/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.39.249/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.40.194/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.40.195/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.40.207/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.40.222/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.40.226/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.40.247/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.42.232/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.46.81/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.46.196/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.47.223/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.48.249/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.52.186/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.53.243/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.55.82/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.56.26/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.56.97/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.56.185/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.56.242/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.58.134/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.59.247/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.60.215/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.61.31/32 { + next-hop-interface eth3 { + } + } + interface-route 109.228.61.37/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.36.7/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.36.17/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.36.24/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.36.56/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.36.60/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.36.142/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.36.148/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.37.23/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.37.47/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.37.83/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.37.101/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.37.102/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.37.133/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.38.95/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.38.114/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.38.142/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.38.182/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.38.216/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.38.248/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.39.37/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.39.44/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.39.68/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.39.99/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.39.109/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.39.129/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.39.145/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.39.219/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.40.11/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.40.56/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.40.90/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.40.124/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.40.152/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.40.166/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.40.244/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.41.72/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.41.73/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.41.148/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.41.240/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.43.6/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.43.28/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.43.71/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.43.98/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.43.113/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.43.157/32 { + next-hop-interface eth3 { + } + } + interface-route 185.132.43.164/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.208.40/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.208.58/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.208.176/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.209.217/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.210.19/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.210.25/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.210.59/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.210.155/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.210.177/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.211.128/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.212.71/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.212.89/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.212.90/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.212.114/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.212.136/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.212.171/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.212.172/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.212.203/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.213.31/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.213.41/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.213.42/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.213.97/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.213.175/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.213.242/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.214.96/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.214.102/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.214.167/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.214.234/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.215.43/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.215.184/32 { + next-hop-interface eth3 { + } + } + interface-route 213.171.215.252/32 { + next-hop-interface eth3 { + } + } + route 0.0.0.0/0 { + next-hop 109.228.63.129 { + } + } + route 10.0.0.0/8 { + next-hop 10.4.35.1 { + } + } + route 10.7.197.0/24 { + next-hop 109.228.63.240 { + } + } + route 172.16.0.0/12 { + next-hop 10.4.35.1 { + } + } + route 192.168.0.0/16 { + next-hop 10.4.35.1 { + } + } + } +} +service { + lldp { + legacy-protocols { + cdp + } + snmp { + enable + } + } + snmp { + community 1Trpq25 { + authorization ro + } + contact network@arsys.es + description gb-glo-sg4ng1fw27-01 + listen-address 10.4.35.105 { + port 161 + } + location NGCS + trap-target 10.4.36.64 { + community 1Trpq25 + port 162 + } + trap-target 172.21.15.200 { + community 1Trpq25 + port 162 + } + } + ssh { + listen-address 10.4.35.105 + listen-address 10.4.51.133 + port 22 + } +} +system { + config-management { + commit-revisions 20 + } + conntrack { + expect-table-size 8192 + hash-size 262144 + modules { + sip { + disable + } + } + table-size 2097152 + timeout { + icmp 30 + other 120 + tcp { + close 10 + close-wait 60 + established 3600 + fin-wait 30 + last-ack 30 + syn-recv 5 + syn-sent 5 + time-wait 5 + } + udp { + other 10 + stream 10 + } + } + } + console { + device ttyS0 { + speed 115200 + } + } + host-name gb-glo-sg4ng1fw27-01 + ip { + arp { + table-size 2048 + } + } + ipv6 { + disable + } + login { + user vyos { + authentication { + encrypted-password $6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/ + plaintext-password "" + } + } + } + name-server 10.4.36.16 + name-server 10.4.37.16 + ntp { + server glo-ntp1.por-ngcs.lan { + } + server glo-ntp2.por-ngcs.lan { + } + } + syslog { + global { + facility all { + level notice + } + facility protocols { + level info + } + } + host 10.4.36.23 { + facility all { + level all + } + facility protocols { + level info + } + facility user { + level err + } + } + user all { + facility all { + level emerg + } + } + } + time-zone Europe/Madrid +} + + +/* Warning: Do not remove the following line. */ +/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@10:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */ +/* Release version: 1.2.6-S1 */ + diff --git a/smoketest/configs/basic-vyos b/smoketest/configs/basic-vyos new file mode 100644 index 000000000..e6f89954f --- /dev/null +++ b/smoketest/configs/basic-vyos @@ -0,0 +1,140 @@ +interfaces { + ethernet eth0 { + address 192.168.0.1/24 + duplex auto + smp-affinity auto + speed auto + } + ethernet eth1 { + duplex auto + smp-affinity auto + speed auto + } + ethernet eth2 { + duplex auto + smp-affinity auto + speed auto + vif 100 { + address 100.100.0.1/24 + } + vif-s 200 { + address 100.64.200.254/24 + vif-c 201 { + address 100.64.201.254/24 + } + vif-c 202 { + address 100.64.202.254/24 + } + } + } + loopback lo { + } +} +protocols { + static { + arp 192.168.0.20 { + hwaddr 00:50:00:00:00:20 + } + arp 192.168.0.30 { + hwaddr 00:50:00:00:00:30 + } + arp 192.168.0.40 { + hwaddr 00:50:00:00:00:40 + } + arp 100.100.0.2 { + hwaddr 00:50:00:00:02:02 + } + arp 100.100.0.3 { + hwaddr 00:50:00:00:02:03 + } + arp 100.100.0.4 { + hwaddr 00:50:00:00:02:04 + } + arp 100.64.200.1 { + hwaddr 00:50:00:00:00:01 + } + arp 100.64.200.2 { + hwaddr 00:50:00:00:00:02 + } + arp 100.64.201.10 { + hwaddr 00:50:00:00:00:10 + } + arp 100.64.201.20 { + hwaddr 00:50:00:00:00:20 + } + arp 100.64.202.30 { + hwaddr 00:50:00:00:00:30 + } + arp 100.64.202.40 { + hwaddr 00:50:00:00:00:40 + } + route 0.0.0.0/0 { + next-hop 100.64.0.1 { + } + } + } +} +service { + dhcp-server { + shared-network-name LAN { + authoritative + subnet 192.168.0.0/24 { + default-router 192.168.0.1 + dns-server 192.168.0.1 + domain-name vyos.net + domain-search vyos.net + range LANDynamic { + start 192.168.0.20 + stop 192.168.0.240 + } + } + } + } + dns { + forwarding { + allow-from 192.168.0.0/16 + cache-size 10000 + dnssec off + listen-address 192.168.0.1 + } + } + ssh { + ciphers aes128-ctr,aes192-ctr,aes256-ctr + ciphers chacha20-poly1305@openssh.com,rijndael-cbc@lysator.liu.se + listen-address 192.168.0.1 + key-exchange curve25519-sha256@libssh.org + key-exchange diffie-hellman-group1-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256 + port 22 + } +} +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 { + facility all { + level info + } + } + } + time-zone Europe/Berlin +} +/* Warning: Do not remove the following line. */ +/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@9:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */ +/* Release version: 1.2.6 */ diff --git a/smoketest/configs/bgp-big-as-cloud b/smoketest/configs/bgp-big-as-cloud index 694243d1e..65819256e 100644 --- a/smoketest/configs/bgp-big-as-cloud +++ b/smoketest/configs/bgp-big-as-cloud @@ -982,6 +982,10 @@ policy { } } } + set { + as-path-exclude "100 200 300" + as-path-prepend "64512 64512 64512" + } } rule 100 { action deny @@ -1819,6 +1823,12 @@ system { } version 9 } + sflow { + agent-address auto + server 1.2.3.4 { + port 1234 + } + } syslog-facility daemon } host-name vyos diff --git a/smoketest/configs/dialup-router-complex b/smoketest/configs/dialup-router-complex index fef79ea56..ac5ff5e99 100644 --- a/smoketest/configs/dialup-router-complex +++ b/smoketest/configs/dialup-router-complex @@ -267,6 +267,22 @@ firewall { } protocol udp } + rule 800 { + action drop + description "SSH anti brute force" + destination { + port ssh + } + log enable + protocol tcp + recent { + count 4 + time 60 + } + state { + new enable + } + } } name DMZ-WAN { default-action accept @@ -482,6 +498,9 @@ firewall { destination { port 110,995 } + limit { + rate "10/minute" + } protocol tcp } rule 123 { diff --git a/smoketest/configs/dialup-router-medium-vpn b/smoketest/configs/dialup-router-medium-vpn index af7c075e4..63d955738 100644 --- a/smoketest/configs/dialup-router-medium-vpn +++ b/smoketest/configs/dialup-router-medium-vpn @@ -6,6 +6,15 @@ firewall { ipv6-src-route disable ip-src-route disable log-martians enable + name test_tcp_flags { + rule 1 { + action drop + protocol tcp + tcp { + flags SYN,ACK,!RST,!FIN + } + } + } options { interface vtun0 { adjust-mss 1380 @@ -83,6 +92,7 @@ interfaces { } policy { route LAN-POLICY-BASED-ROUTING + ipv6-route LAN6-POLICY-BASED-ROUTING } smp-affinity auto speed auto @@ -383,6 +393,29 @@ nat { } } policy { + ipv6-route LAN6-POLICY-BASED-ROUTING { + rule 10 { + destination { + } + disable + set { + table 10 + } + source { + address 2002::1 + } + } + rule 20 { + destination { + } + set { + table 100 + } + source { + address 2008::f + } + } + } prefix-list user2-routes { rule 1 { action permit diff --git a/smoketest/configs/ipv6-disable b/smoketest/configs/ipv6-disable new file mode 100644 index 000000000..da41e9020 --- /dev/null +++ b/smoketest/configs/ipv6-disable @@ -0,0 +1,83 @@ +interfaces { + ethernet eth0 { + duplex auto + smp-affinity auto + speed auto + vif 201 { + address 172.18.201.10/24 + } + vif 202 { + address 172.18.202.10/24 + } + vif 203 { + address 172.18.203.10/24 + } + vif 204 { + address 172.18.204.10/24 + } + } +} +protocols { + static { + route 0.0.0.0/0 { + next-hop 172.18.201.254 { + distance 10 + } + next-hop 172.18.202.254 { + distance 20 + } + next-hop 172.18.203.254 { + distance 30 + } + next-hop 172.18.204.254 { + distance 40 + } + } + } +} +system { + config-management { + commit-revisions 200 + } + console { + device ttyS0 { + speed 115200 + } + } + domain-name vyos.net + host-name vyos + ipv6 { + disable + } + login { + user vyos { + authentication { + encrypted-password $6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/ + plaintext-password "" + } + level admin + } + } + name-server 172.16.254.20 + name-server 172.16.254.30 + ntp { + server 172.16.254.20 { + } + server 172.16.254.30 { + } + } + syslog { + global { + facility all { + level info + } + facility protocols { + level debug + } + } + } +} + +/* Warning: Do not remove the following line. */ +/* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@9:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */ +/* Release version: 1.2.6 */ diff --git a/smoketest/configs/qos-basic b/smoketest/configs/qos-basic new file mode 100644 index 000000000..f94a5650d --- /dev/null +++ b/smoketest/configs/qos-basic @@ -0,0 +1,205 @@ +interfaces { + ethernet eth0 { + address 10.1.1.100/24 + traffic-policy { + out FS + } + } + ethernet eth1 { + address 10.2.1.1/24 + traffic-policy { + out M2 + } + } + ethernet eth2 { + address 10.9.9.1/24 + traffic-policy { + out MY-HTB + } + } + 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 + } + conntrack { + modules { + ftp + h323 + nfs + pptp + sip + sqlnet + tftp + } + } + console { + device ttyS0 { + speed 115200 + } + } + host-name vyos + login { + user vyos { + authentication { + encrypted-password $6$r/Yw/07NXNY$/ZB.Rjf9jxEV.BYoDyLdH.kH14rU52pOBtrX.4S34qlPt77chflCHvpTCq9a6huLzwaMR50rEICzA5GoIRZlM0 + plaintext-password "" + } + } + } + ntp { + server time1.vyos.net { + } + server time2.vyos.net { + } + server time3.vyos.net { + } + } + syslog { + global { + facility all { + level info + } + facility protocols { + level debug + } + } + } +} +traffic-policy { + shaper M2 { + bandwidth auto + class 10 { + bandwidth 100% + burst 15k + match ADDRESS10 { + ip { + dscp CS4 + } + } + queue-type fair-queue + set-dscp CS5 + } + default { + bandwidth 10mbit + burst 15k + 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 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 + } + } +} +// 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.1 + diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py index 340ec4edd..816ba6dcd 100644 --- a/smoketest/scripts/cli/base_interfaces_test.py +++ b/smoketest/scripts/cli/base_interfaces_test.py @@ -1,4 +1,4 @@ -# Copyright (C) 2019-2021 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 @@ -56,6 +56,7 @@ def is_mirrored_to(interface, mirror_if, qdisc): class BasicInterfaceTest: class TestCase(VyOSUnitTestSHIM.TestCase): + _test_dhcp = False _test_ip = False _test_mtu = False _test_vlan = False @@ -77,18 +78,25 @@ class BasicInterfaceTest: # choose IPv6 minimum MTU value for tests - this must always work _mtu = '1280' - def setUp(self): + @classmethod + def setUpClass(cls): + super(BasicInterfaceTest.TestCase, cls).setUpClass() + # Setup mirror interfaces for SPAN (Switch Port Analyzer) - for span in self._mirror_interfaces: + for span in cls._mirror_interfaces: section = Section.section(span) - self.cli_set(['interfaces', section, span]) + cls.cli_set(cls, ['interfaces', section, span]) - def tearDown(self): + @classmethod + def tearDownClass(cls): # Tear down mirror interfaces for SPAN (Switch Port Analyzer) - for span in self._mirror_interfaces: + for span in cls._mirror_interfaces: section = Section.section(span) - self.cli_delete(['interfaces', section, span]) + cls.cli_delete(cls, ['interfaces', section, span]) + + super(BasicInterfaceTest.TestCase, cls).tearDownClass() + def tearDown(self): self.cli_delete(self._base_path) self.cli_commit() @@ -96,6 +104,35 @@ class BasicInterfaceTest: for intf in self._interfaces: self.assertNotIn(intf, interfaces()) + # No daemon that was started during a test should remain running + for daemon in ['dhcp6c', 'dhclient']: + self.assertFalse(process_named_running(daemon)) + + def test_dhcp_disable_interface(self): + if not self._test_dhcp: + self.skipTest('not supported') + + # When interface is configured as admin down, it must be admin down + # even when dhcpc starts on the given interface + for interface in self._interfaces: + self.cli_set(self._base_path + [interface, 'disable']) + for option in self._options.get(interface, []): + self.cli_set(self._base_path + [interface] + option.split()) + + self.cli_set(self._base_path + [interface, 'disable']) + + # Also enable DHCP (ISC DHCP always places interface in admin up + # state so we check that we do not start DHCP client. + # https://phabricator.vyos.net/T2767 + self.cli_set(self._base_path + [interface, 'address', 'dhcp']) + + self.cli_commit() + + # Validate interface state + for interface in self._interfaces: + flags = read_file(f'/sys/class/net/{interface}/flags') + self.assertEqual(int(flags, 16) & 1, 0) + def test_span_mirror(self): if not self._mirror_interfaces: self.skipTest('not supported') @@ -171,10 +208,10 @@ class BasicInterfaceTest: def test_add_multiple_ip_addresses(self): # Add address for intf in self._interfaces: + for option in self._options.get(intf, []): + self.cli_set(self._base_path + [intf] + option.split()) for addr in self._test_addr: self.cli_set(self._base_path + [intf, 'address', addr]) - for option in self._options.get(intf, []): - self.cli_set(self._base_path + [intf] + option.split()) self.cli_commit() @@ -202,6 +239,7 @@ class BasicInterfaceTest: self.cli_commit() for interface in self._interfaces: + self.assertIn(AF_INET6, ifaddresses(interface)) for addr in ifaddresses(interface)[AF_INET6]: self.assertTrue(is_ipv6_link_local(addr['addr'])) @@ -297,6 +335,23 @@ class BasicInterfaceTest: self.assertEqual(Interface(vif).get_admin_state(), 'up') + # T4064: Delete interface addresses, keep VLAN interface + for interface in self._interfaces: + base = self._base_path + [interface] + for vlan in self._vlan_range: + base = self._base_path + [interface, 'vif', vlan] + self.cli_delete(base + ['address']) + + self.cli_commit() + + # Verify no IP address is assigned + for interface in self._interfaces: + for vlan in self._vlan_range: + vif = f'{intf}.{vlan}' + for address in self._test_addr: + self.assertFalse(is_intf_addr_assigned(vif, address)) + + def test_vif_8021q_mtu_limits(self): # XXX: This testcase is not allowed to run as first testcase, reason # is the Wireless test will first load the wifi kernel hwsim module @@ -493,6 +548,24 @@ class BasicInterfaceTest: tmp = get_interface_config(vif) self.assertEqual(tmp['mtu'], int(self._mtu)) + + # T4064: Delete interface addresses, keep VLAN interface + for interface in self._interfaces: + base = self._base_path + [interface] + for vif_s in self._qinq_range: + for vif_c in self._vlan_range: + self.cli_delete(self._base_path + [interface, 'vif-s', vif_s, 'vif-c', vif_c, 'address']) + + self.cli_commit() + # Verify no IP address is assigned + for interface in self._interfaces: + base = self._base_path + [interface] + for vif_s in self._qinq_range: + for vif_c in self._vlan_range: + vif = f'{interface}.{vif_s}.{vif_c}' + for address in self._test_addr: + self.assertFalse(is_intf_addr_assigned(vif, address)) + # T3972: remove vif-c interfaces from vif-s for interface in self._interfaces: base = self._base_path + [interface] @@ -572,11 +645,11 @@ class BasicInterfaceTest: self.cli_commit() for interface in self._interfaces: - base_options = f'-A FORWARD -o {interface} -p tcp -m tcp --tcp-flags SYN,RST SYN' - out = cmd('sudo iptables-save -t mangle') + base_options = f'oifname "{interface}"' + out = cmd('sudo nft list chain raw VYOS_TCP_MSS') for line in out.splitlines(): if line.startswith(base_options): - self.assertIn(f'--set-mss {mss}', line) + self.assertIn(f'tcp option maxseg size set {mss}', line) tmp = read_file(f'/proc/sys/net/ipv4/neigh/{interface}/base_reachable_time_ms') self.assertEqual(tmp, str((int(arp_tmo) * 1000))) # tmo value is in milli seconds @@ -627,11 +700,11 @@ class BasicInterfaceTest: self.cli_commit() for interface in self._interfaces: - base_options = f'-A FORWARD -o {interface} -p tcp -m tcp --tcp-flags SYN,RST SYN' - out = cmd('sudo ip6tables-save -t mangle') + base_options = f'oifname "{interface}"' + out = cmd('sudo nft list chain ip6 raw VYOS_TCP_MSS') for line in out.splitlines(): if line.startswith(base_options): - self.assertIn(f'--set-mss {mss}', line) + self.assertIn(f'tcp option maxseg size set {mss}', line) proc_base = f'/proc/sys/net/ipv6/conf/{interface}' diff --git a/smoketest/scripts/cli/base_vyostest_shim.py b/smoketest/scripts/cli/base_vyostest_shim.py index 50f80e7d1..7cfb53045 100644 --- a/smoketest/scripts/cli/base_vyostest_shim.py +++ b/smoketest/scripts/cli/base_vyostest_shim.py @@ -16,6 +16,7 @@ import os import unittest from time import sleep +from typing import Type from vyos.configsession import ConfigSession from vyos.configsession import ConfigSessionError @@ -73,7 +74,7 @@ class VyOSUnitTestSHIM: def cli_commit(self): self._session.commit() # during a commit there is a process opening commit_lock, and run() returns 0 - while run(f'sudo lsof | grep -q {commit_lock}') == 0: + while run(f'sudo lsof -nP {commit_lock}') == 0: sleep(0.250) def getFRRconfig(self, string, end='$', endsection='^!', daemon=''): @@ -85,3 +86,17 @@ class VyOSUnitTestSHIM: print(f'\n\ncommand "{command}" returned:\n') pprint.pprint(out) return out + +# standard construction; typing suggestion: https://stackoverflow.com/a/70292317 +def ignore_warning(warning: Type[Warning]): + import warnings + from functools import wraps + + def inner(f): + @wraps(f) + def wrapped(*args, **kwargs): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=warning) + return f(*args, **kwargs) + return wrapped + return inner diff --git a/smoketest/scripts/cli/test_component_version.py b/smoketest/scripts/cli/test_component_version.py new file mode 100755 index 000000000..777379bdd --- /dev/null +++ b/smoketest/scripts/cli/test_component_version.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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.systemversions import get_system_versions, get_system_component_version + +# After T3474, component versions should be updated in the files in +# vyos-1x/interface-definitions/include/version/ +# This test verifies that the legacy version in curver_DATA does not exceed +# that in the xml cache. +class TestComponentVersion(unittest.TestCase): + def setUp(self): + self.legacy_d = get_system_versions() + self.xml_d = get_system_component_version() + + def test_component_version(self): + self.assertTrue(set(self.legacy_d).issubset(set(self.xml_d))) + for k, v in self.legacy_d.items(): + self.assertTrue(v <= self.xml_d[k]) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_configd_init.py b/smoketest/scripts/cli/test_configd_init.py new file mode 100755 index 000000000..5dec89963 --- /dev/null +++ b/smoketest/scripts/cli/test_configd_init.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 time import sleep + +from vyos.util import cmd, is_systemd_service_running + +class TestConfigdInit(unittest.TestCase): + def setUp(self): + self.running_state = is_systemd_service_running('vyos-configd.service') + + def test_configd_init(self): + if not self.running_state: + cmd('sudo systemctl start vyos-configd.service') + # allow time for init to succeed/fail + sleep(2) + self.assertTrue(is_systemd_service_running('vyos-configd.service')) + + def tearDown(self): + if not self.running_state: + cmd('sudo systemctl stop vyos-configd.service') + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py new file mode 100755 index 000000000..b8f944575 --- /dev/null +++ b/smoketest/scripts/cli/test_firewall.py @@ -0,0 +1,233 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021-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 +# 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 glob import glob + +from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.util import cmd + +sysfs_config = { + 'all_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_all', 'default': '0', 'test_value': 'disable'}, + 'broadcast_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts', 'default': '1', 'test_value': 'enable'}, + 'ip_src_route': {'sysfs': '/proc/sys/net/ipv4/conf/*/accept_source_route', 'default': '0', 'test_value': 'enable'}, + 'ipv6_receive_redirects': {'sysfs': '/proc/sys/net/ipv6/conf/*/accept_redirects', 'default': '0', 'test_value': 'enable'}, + 'ipv6_src_route': {'sysfs': '/proc/sys/net/ipv6/conf/*/accept_source_route', 'default': '-1', 'test_value': 'enable'}, + 'log_martians': {'sysfs': '/proc/sys/net/ipv4/conf/all/log_martians', 'default': '1', 'test_value': 'disable'}, + 'receive_redirects': {'sysfs': '/proc/sys/net/ipv4/conf/*/accept_redirects', 'default': '0', 'test_value': 'enable'}, + 'send_redirects': {'sysfs': '/proc/sys/net/ipv4/conf/*/send_redirects', 'default': '1', 'test_value': 'disable'}, + 'syn_cookies': {'sysfs': '/proc/sys/net/ipv4/tcp_syncookies', 'default': '1', 'test_value': 'disable'}, + 'twa_hazards_protection': {'sysfs': '/proc/sys/net/ipv4/tcp_rfc1337', 'default': '0', 'test_value': 'enable'} +} + +class TestFirewall(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestFirewall, cls).setUpClass() + + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + cls.cli_delete(cls, ['firewall']) + + cls.cli_set(cls, ['interfaces', 'ethernet', 'eth0', 'address', '172.16.10.1/24']) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['interfaces', 'ethernet', 'eth0', 'address', '172.16.10.1/24']) + super(TestFirewall, cls).tearDownClass() + + def tearDown(self): + self.cli_delete(['interfaces', 'ethernet', 'eth0', 'firewall']) + self.cli_delete(['firewall']) + self.cli_commit() + + def test_groups(self): + self.cli_set(['firewall', 'group', 'mac-group', 'smoketest_mac', 'mac-address', '00:01:02:03:04:05']) + self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network', 'network', '172.16.99.0/24']) + self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port', 'port', '53']) + self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port', 'port', '123']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'accept']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'group', 'network-group', 'smoketest_network']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'address', '172.16.10.10']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'group', 'port-group', 'smoketest_port']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'protocol', 'tcp_udp']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'action', 'accept']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'source', 'group', 'mac-group', 'smoketest_mac']) + + self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest']) + + self.cli_commit() + + nftables_search = [ + ['iifname "eth0"', 'jump NAME_smoketest'], + ['ip saddr { 172.16.99.0/24 }', 'ip daddr 172.16.10.10', 'th dport { 53, 123 }', 'return'], + ['ether saddr { 00:01:02:03:04:05 }', 'return'] + ] + + nftables_output = cmd('sudo nft list table ip filter') + + for search in nftables_search: + matched = False + for line in nftables_output.split("\n"): + if all(item in line for item in search): + matched = True + break + self.assertTrue(matched, msg=search) + + def test_basic_rules(self): + self.cli_set(['firewall', 'name', 'smoketest', 'default-action', 'drop']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'accept']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'address', '172.16.20.10']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'address', '172.16.10.10']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'action', 'reject']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'protocol', 'tcp']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'destination', 'port', '8888']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'tcp', 'flags', 'syn']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'tcp', 'flags', 'not', 'ack']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'action', 'accept']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'protocol', 'tcp']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'destination', 'port', '22']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'limit', 'rate', '5/minute']) + + self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest']) + + self.cli_commit() + + nftables_search = [ + ['iifname "eth0"', 'jump NAME_smoketest'], + ['saddr 172.16.20.10', 'daddr 172.16.10.10', 'return'], + ['tcp flags & (syn | ack) == syn', 'tcp dport { 8888 }', 'reject'], + ['tcp dport { 22 }', 'limit rate 5/minute', 'return'], + ['smoketest default-action', 'drop'] + ] + + nftables_output = cmd('sudo nft list table ip filter') + + for search in nftables_search: + matched = False + for line in nftables_output.split("\n"): + if all(item in line for item in search): + matched = True + break + self.assertTrue(matched, msg=search) + + def test_basic_rules_ipv6(self): + self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'default-action', 'drop']) + self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '1', 'action', 'accept']) + self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '1', 'source', 'address', '2002::1']) + self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '1', 'destination', 'address', '2002::1:1']) + self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '2', 'action', 'reject']) + self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '2', 'protocol', 'tcp_udp']) + self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'rule', '2', 'destination', 'port', '8888']) + + self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'ipv6-name', 'v6-smoketest']) + + self.cli_commit() + + nftables_search = [ + ['iifname "eth0"', 'jump NAME6_v6-smoketest'], + ['saddr 2002::1', 'daddr 2002::1:1', 'return'], + ['meta l4proto { tcp, udp }', 'th dport { 8888 }', 'reject'], + ['smoketest default-action', 'drop'] + ] + + nftables_output = cmd('sudo nft list table ip6 filter') + + for search in nftables_search: + matched = False + for line in nftables_output.split("\n"): + if all(item in line for item in search): + matched = True + break + self.assertTrue(matched, msg=search) + + def test_state_policy(self): + self.cli_set(['firewall', 'state-policy', 'established', 'action', 'accept']) + self.cli_set(['firewall', 'state-policy', 'related', 'action', 'accept']) + self.cli_set(['firewall', 'state-policy', 'invalid', 'action', 'drop']) + + self.cli_commit() + + chains = { + 'ip filter': ['VYOS_FW_FORWARD', 'VYOS_FW_OUTPUT', 'VYOS_FW_LOCAL'], + 'ip6 filter': ['VYOS_FW6_FORWARD', 'VYOS_FW6_OUTPUT', 'VYOS_FW6_LOCAL'] + } + + for table in ['ip filter', 'ip6 filter']: + for chain in chains[table]: + nftables_output = cmd(f'sudo nft list chain {table} {chain}') + self.assertTrue('jump VYOS_STATE_POLICY' in nftables_output) + + def test_state_and_status_rules(self): + self.cli_set(['firewall', 'name', 'smoketest', 'default-action', 'drop']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'accept']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'state', 'established', 'enable']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'state', 'related', 'enable']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'action', 'reject']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'state', 'invalid', 'enable']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'action', 'accept']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'state', 'new', 'enable']) + + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'connection-status', 'nat', 'destination']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'action', 'accept']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'state', 'new', 'enable']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'state', 'established', 'enable']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'connection-status', 'nat', 'source']) + + self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest']) + + self.cli_commit() + + nftables_search = [ + ['iifname "eth0"', 'jump NAME_smoketest'], + ['ct state { established, related }', 'return'], + ['ct state { invalid }', 'reject'], + ['ct state { new }', 'ct status { dnat }', 'return'], + ['ct state { established, new }', 'ct status { snat }', 'return'], + ['smoketest default-action', 'drop'] + ] + + nftables_output = cmd('sudo nft list table ip filter') + + for search in nftables_search: + matched = False + for line in nftables_output.split("\n"): + if all(item in line for item in search): + matched = True + break + self.assertTrue(matched, msg=search) + + def test_sysfs(self): + for name, conf in sysfs_config.items(): + paths = glob(conf['sysfs']) + for path in paths: + with open(path, 'r') as f: + self.assertEqual(f.read().strip(), conf['default'], msg=path) + + self.cli_set(['firewall', name.replace("_", "-"), conf['test_value']]) + + self.cli_commit() + + for name, conf in sysfs_config.items(): + paths = glob(conf['sysfs']) + for path in paths: + with open(path, 'r') as f: + self.assertNotEqual(f.read().strip(), conf['default'], msg=path) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_ha_virtual_server.py b/smoketest/scripts/cli/test_ha_virtual_server.py new file mode 100755 index 000000000..e3a91283e --- /dev/null +++ b/smoketest/scripts/cli/test_ha_virtual_server.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021-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 +# 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 base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.configsession import ConfigSessionError +from vyos.ifconfig.vrrp import VRRP +from vyos.util import cmd +from vyos.util import process_named_running +from vyos.util import read_file +from vyos.template import inc_ip + +PROCESS_NAME = 'keepalived' +KEEPALIVED_CONF = VRRP.location['config'] +base_path = ['high-availability'] +vrrp_interface = 'eth1' + +class TestHAVirtualServer(VyOSUnitTestSHIM.TestCase): + def tearDown(self): + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + + self.cli_delete(['interfaces', 'ethernet', vrrp_interface, 'address']) + self.cli_delete(base_path) + self.cli_commit() + + # Process must be terminated after deleting the config + self.assertFalse(process_named_running(PROCESS_NAME)) + + def test_01_ha_virtual_server(self): + algo = 'least-connection' + delay = '10' + method = 'nat' + persistence_timeout = '600' + vip = '203.0.113.111' + vport = '2222' + rservers = ['192.0.2.21', '192.0.2.22', '192.0.2.23'] + rport = '22' + proto = 'tcp' + connection_timeout = '30' + + vserver_base = base_path + ['virtual-server'] + + self.cli_set(vserver_base + [vip, 'algorithm', algo]) + self.cli_set(vserver_base + [vip, 'delay-loop', delay]) + self.cli_set(vserver_base + [vip, 'forward-method', method]) + self.cli_set(vserver_base + [vip, 'persistence-timeout', persistence_timeout]) + self.cli_set(vserver_base + [vip, 'port', vport]) + self.cli_set(vserver_base + [vip, 'protocol', proto]) + for rs in rservers: + self.cli_set(vserver_base + [vip, 'real-server', rs, 'connection-timeout', connection_timeout]) + self.cli_set(vserver_base + [vip, 'real-server', rs, 'port', rport]) + + # commit changes + self.cli_commit() + + config = read_file(KEEPALIVED_CONF) + + self.assertIn(f'delay_loop {delay}', config) + self.assertIn(f'lb_algo lc', config) + self.assertIn(f'lb_kind {method.upper()}', config) + self.assertIn(f'persistence_timeout {persistence_timeout}', config) + self.assertIn(f'protocol {proto.upper()}', config) + for rs in rservers: + self.assertIn(f'real_server {rs} {rport}', config) + self.assertIn(f'{proto.upper()}_CHECK', config) + self.assertIn(f'connect_timeout {connection_timeout}', config) + + def test_02_ha_virtual_server_and_vrrp(self): + algo = 'least-connection' + delay = '15' + method = 'nat' + persistence_timeout = '300' + vip = '203.0.113.222' + vport = '22322' + rservers = ['192.0.2.11', '192.0.2.12'] + rport = '222' + proto = 'tcp' + connection_timeout = '23' + group = 'VyOS' + vrid = '99' + + vrrp_base = base_path + ['vrrp', 'group'] + vserver_base = base_path + ['virtual-server'] + + self.cli_set(['interfaces', 'ethernet', vrrp_interface, 'address', '203.0.113.10/24']) + + # VRRP config + self.cli_set(vrrp_base + [group, 'description', group]) + self.cli_set(vrrp_base + [group, 'interface', vrrp_interface]) + self.cli_set(vrrp_base + [group, 'address', vip + '/24']) + self.cli_set(vrrp_base + [group, 'vrid', vrid]) + + # Virtual-server config + self.cli_set(vserver_base + [vip, 'algorithm', algo]) + self.cli_set(vserver_base + [vip, 'delay-loop', delay]) + self.cli_set(vserver_base + [vip, 'forward-method', method]) + self.cli_set(vserver_base + [vip, 'persistence-timeout', persistence_timeout]) + self.cli_set(vserver_base + [vip, 'port', vport]) + self.cli_set(vserver_base + [vip, 'protocol', proto]) + for rs in rservers: + self.cli_set(vserver_base + [vip, 'real-server', rs, 'connection-timeout', connection_timeout]) + self.cli_set(vserver_base + [vip, 'real-server', rs, 'port', rport]) + + # commit changes + self.cli_commit() + + config = read_file(KEEPALIVED_CONF) + + # Keepalived vrrp + self.assertIn(f'# {group}', config) + self.assertIn(f'interface {vrrp_interface}', config) + self.assertIn(f'virtual_router_id {vrid}', config) + self.assertIn(f'priority 100', config) # default value + self.assertIn(f'advert_int 1', config) # default value + self.assertIn(f'preempt_delay 0', config) # default value + + # Keepalived virtual-server + self.assertIn(f'delay_loop {delay}', config) + self.assertIn(f'lb_algo lc', config) + self.assertIn(f'lb_kind {method.upper()}', config) + self.assertIn(f'persistence_timeout {persistence_timeout}', config) + self.assertIn(f'protocol {proto.upper()}', config) + for rs in rservers: + self.assertIn(f'real_server {rs} {rport}', config) + self.assertIn(f'{proto.upper()}_CHECK', config) + self.assertIn(f'connect_timeout {connection_timeout}', config) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_ha_vrrp.py b/smoketest/scripts/cli/test_ha_vrrp.py index 2524bf2b1..68905e447 100755 --- a/smoketest/scripts/cli/test_ha_vrrp.py +++ b/smoketest/scripts/cli/test_ha_vrrp.py @@ -27,7 +27,7 @@ from vyos.template import inc_ip PROCESS_NAME = 'keepalived' KEEPALIVED_CONF = VRRP.location['config'] -base_path = ['high-availability', 'vrrp'] +base_path = ['high-availability'] vrrp_interface = 'eth1' groups = ['VLAN77', 'VLAN78', 'VLAN201'] @@ -44,7 +44,7 @@ class TestVRRP(VyOSUnitTestSHIM.TestCase): for group in groups: vlan_id = group.lstrip('VLAN') - self.cli_set(['interfaces', 'ethernet', vrrp_interface, 'vif', vlan_id]) + self.cli_delete(['interfaces', 'ethernet', vrrp_interface, 'vif', vlan_id]) self.cli_delete(base_path) self.cli_commit() @@ -56,7 +56,7 @@ class TestVRRP(VyOSUnitTestSHIM.TestCase): for group in groups: vlan_id = group.lstrip('VLAN') vip = f'100.64.{vlan_id}.1/24' - group_base = base_path + ['group', group] + group_base = base_path + ['vrrp', 'group', group] self.cli_set(['interfaces', 'ethernet', vrrp_interface, 'vif', vlan_id, 'address', inc_ip(vip, 1) + '/' + vip.split('/')[-1]]) @@ -91,7 +91,7 @@ class TestVRRP(VyOSUnitTestSHIM.TestCase): for group in groups: vlan_id = group.lstrip('VLAN') vip = f'100.64.{vlan_id}.1/24' - group_base = base_path + ['group', group] + group_base = base_path + ['vrrp', 'group', group] self.cli_set(['interfaces', 'ethernet', vrrp_interface, 'vif', vlan_id, 'address', inc_ip(vip, 1) + '/' + vip.split('/')[-1]]) @@ -108,7 +108,7 @@ class TestVRRP(VyOSUnitTestSHIM.TestCase): # Authentication self.cli_set(group_base + ['authentication', 'type', 'plaintext-password']) - self.cli_set(group_base + ['authentication', 'password', f'vyos-{group}']) + self.cli_set(group_base + ['authentication', 'password', f'{group}']) # commit changes self.cli_commit() @@ -129,7 +129,7 @@ class TestVRRP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' {vip}', config) # Authentication - self.assertIn(f'auth_pass "vyos-{group}"', config) + self.assertIn(f'auth_pass "{group}"', config) self.assertIn(f'auth_type PASS', config) def test_03_sync_group(self): @@ -138,7 +138,7 @@ class TestVRRP(VyOSUnitTestSHIM.TestCase): for group in groups: vlan_id = group.lstrip('VLAN') vip = f'100.64.{vlan_id}.1/24' - group_base = base_path + ['group', group] + group_base = base_path + ['vrrp', 'group', group] self.cli_set(['interfaces', 'ethernet', vrrp_interface, 'vif', vlan_id, 'address', inc_ip(vip, 1) + '/' + vip.split('/')[-1]]) @@ -146,7 +146,7 @@ class TestVRRP(VyOSUnitTestSHIM.TestCase): self.cli_set(group_base + ['address', vip]) self.cli_set(group_base + ['vrid', vlan_id]) - self.cli_set(base_path + ['sync-group', sync_group, 'member', group]) + self.cli_set(base_path + ['vrrp', 'sync-group', sync_group, 'member', group]) # commit changes self.cli_commit() @@ -166,5 +166,35 @@ class TestVRRP(VyOSUnitTestSHIM.TestCase): for group in groups: self.assertIn(f'{group}', config) + def test_04_exclude_vrrp_interface(self): + group = 'VyOS-WAN' + none_vrrp_interface = 'eth2' + vlan_id = '24' + vip = '100.64.24.1/24' + vip_dev = '192.0.2.2/24' + vrid = '150' + group_base = base_path + ['vrrp', 'group', group] + + self.cli_set(['interfaces', 'ethernet', vrrp_interface, 'vif', vlan_id, 'address', '100.64.24.11/24']) + self.cli_set(group_base + ['interface', f'{vrrp_interface}.{vlan_id}']) + self.cli_set(group_base + ['address', vip]) + self.cli_set(group_base + ['address', vip_dev, 'interface', none_vrrp_interface]) + self.cli_set(group_base + ['track', 'exclude-vrrp-interface']) + self.cli_set(group_base + ['track', 'interface', none_vrrp_interface]) + self.cli_set(group_base + ['vrid', vrid]) + + # commit changes + self.cli_commit() + + config = getConfig(f'vrrp_instance {group}') + + self.assertIn(f'interface {vrrp_interface}.{vlan_id}', config) + self.assertIn(f'virtual_router_id {vrid}', config) + self.assertIn(f'dont_track_primary', config) + self.assertIn(f' {vip}', config) + self.assertIn(f' {vip_dev} dev {none_vrrp_interface}', config) + self.assertIn(f'track_interface', config) + self.assertIn(f' {none_vrrp_interface}', config) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_bonding.py b/smoketest/scripts/cli/test_interfaces_bonding.py index 86000553e..237abb487 100755 --- a/smoketest/scripts/cli/test_interfaces_bonding.py +++ b/smoketest/scripts/cli/test_interfaces_bonding.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -28,6 +28,7 @@ from vyos.util import read_file class BondingInterfaceTest(BasicInterfaceTest.TestCase): @classmethod def setUpClass(cls): + cls._test_dhcp = True cls._test_ip = True cls._test_ipv6 = True cls._test_ipv6_pd = True @@ -36,7 +37,6 @@ class BondingInterfaceTest(BasicInterfaceTest.TestCase): cls._test_vlan = True cls._test_qinq = True cls._base_path = ['interfaces', 'bonding'] - cls._interfaces = ['bond0'] cls._mirror_interfaces = ['dum21354'] cls._members = [] @@ -52,9 +52,10 @@ class BondingInterfaceTest(BasicInterfaceTest.TestCase): cls._options['bond0'] = [] for member in cls._members: cls._options['bond0'].append(f'member interface {member}') + cls._interfaces = list(cls._options) # call base-classes classmethod - super(cls, cls).setUpClass() + super(BondingInterfaceTest, cls).setUpClass() def test_add_single_ip_address(self): super().test_add_single_ip_address() @@ -150,5 +151,41 @@ class BondingInterfaceTest(BasicInterfaceTest.TestCase): defined_policy = read_file(f'/sys/class/net/{interface}/bonding/xmit_hash_policy').split() self.assertEqual(defined_policy[0], hash_policy) + def test_bonding_multi_use_member(self): + # Define available bonding hash policies + for interface in ['bond10', 'bond20']: + for member in self._members: + self.cli_set(self._base_path + [interface, 'member', 'interface', member]) + + # check validate() - can not use the same member interfaces multiple times + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_delete(self._base_path + ['bond20']) + + self.cli_commit() + + def test_bonding_uniq_member_description(self): + ethernet_path = ['interfaces', 'ethernet'] + for interface in self._interfaces: + for option in self._options.get(interface, []): + self.cli_set(self._base_path + [interface] + option.split()) + + self.cli_commit() + + # Add any changes on bonding members + # For example add description on separate ethX interfaces + for interface in self._interfaces: + for member in self._members: + self.cli_set(ethernet_path + [member, 'description', member + '_interface']) + + self.cli_commit() + + # verify config + for interface in self._interfaces: + slaves = read_file(f'/sys/class/net/{interface}/bonding/slaves').split() + for member in self._members: + self.assertIn(member, slaves) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py index 4f7e03298..ca0ead9e8 100755 --- a/smoketest/scripts/cli/test_interfaces_bridge.py +++ b/smoketest/scripts/cli/test_interfaces_bridge.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -31,6 +31,7 @@ from vyos.validate import is_intf_addr_assigned class BridgeInterfaceTest(BasicInterfaceTest.TestCase): @classmethod def setUpClass(cls): + cls._test_dhcp = True cls._test_ip = True cls._test_ipv6 = True cls._test_ipv6_pd = True @@ -55,7 +56,7 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase): cls._interfaces = list(cls._options) # call base-classes classmethod - super(cls, cls).setUpClass() + super(BridgeInterfaceTest, cls).setUpClass() def tearDown(self): for intf in self._interfaces: diff --git a/smoketest/scripts/cli/test_interfaces_dummy.py b/smoketest/scripts/cli/test_interfaces_dummy.py index dedc6fe05..d96ec2c5d 100755 --- a/smoketest/scripts/cli/test_interfaces_dummy.py +++ b/smoketest/scripts/cli/test_interfaces_dummy.py @@ -24,7 +24,7 @@ class DummyInterfaceTest(BasicInterfaceTest.TestCase): cls._base_path = ['interfaces', 'dummy'] cls._interfaces = ['dum435', 'dum8677', 'dum0931', 'dum089'] # call base-classes classmethod - super(cls, cls).setUpClass() + super(DummyInterfaceTest, cls).setUpClass() if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py index 6d80e4c96..05d2ae5f5 100755 --- a/smoketest/scripts/cli/test_interfaces_ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_ethernet.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -18,32 +18,82 @@ import os import re import unittest +from netifaces import AF_INET +from netifaces import AF_INET6 +from netifaces import ifaddresses + from base_interfaces_test import BasicInterfaceTest from vyos.configsession import ConfigSessionError from vyos.ifconfig import Section +from vyos.pki import CERT_BEGIN +from vyos.template import is_ipv6 from vyos.util import cmd from vyos.util import process_named_running from vyos.util import read_file +from vyos.validate import is_ipv6_link_local + +server_ca_root_cert_data = """ +MIIBcTCCARagAwIBAgIUDcAf1oIQV+6WRaW7NPcSnECQ/lUwCgYIKoZIzj0EAwIw +HjEcMBoGA1UEAwwTVnlPUyBzZXJ2ZXIgcm9vdCBDQTAeFw0yMjAyMTcxOTQxMjBa +Fw0zMjAyMTUxOTQxMjBaMB4xHDAaBgNVBAMME1Z5T1Mgc2VydmVyIHJvb3QgQ0Ew +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ0y24GzKQf4aM2Ir12tI9yITOIzAUj +ZXyJeCmYI6uAnyAMqc4Q4NKyfq3nBi4XP87cs1jlC1P2BZ8MsjL5MdGWozIwMDAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRwC/YaieMEnjhYa7K3Flw/o0SFuzAK +BggqhkjOPQQDAgNJADBGAiEAh3qEj8vScsjAdBy5shXzXDVVOKWCPTdGrPKnu8UW +a2cCIQDlDgkzWmn5ujc5ATKz1fj+Se/aeqwh4QyoWCVTFLIxhQ== +""" -cert_data = """ -MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIw -WTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNv -bWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIx -MDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNV -BAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlP -UzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3 -QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu -+JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3Lftz -ngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93 -+dm/LDnp7C0= +server_ca_intermediate_cert_data = """ +MIIBmTCCAT+gAwIBAgIUNzrtHzLmi3QpPK57tUgCnJZhXXQwCgYIKoZIzj0EAwIw +HjEcMBoGA1UEAwwTVnlPUyBzZXJ2ZXIgcm9vdCBDQTAeFw0yMjAyMTcxOTQxMjFa +Fw0zMjAyMTUxOTQxMjFaMCYxJDAiBgNVBAMMG1Z5T1Mgc2VydmVyIGludGVybWVk +aWF0ZSBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEl2nJ1CzoqPV6hWII2m +eGN/uieU6wDMECTk/LgG8CCCSYb488dibUiFN/1UFsmoLIdIhkx/6MUCYh62m8U2 +WNujUzBRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMV3YwH88I5gFsFUibbQ +kMR0ECPsMB8GA1UdIwQYMBaAFHAL9hqJ4wSeOFhrsrcWXD+jRIW7MAoGCCqGSM49 +BAMCA0gAMEUCIQC/ahujD9dp5pMMCd3SZddqGC9cXtOwMN0JR3e5CxP13AIgIMQm +jMYrinFoInxmX64HfshYqnUY8608nK9D2BNPOHo= """ -key_data = """ -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx -2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7 -u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww +client_ca_root_cert_data = """ +MIIBcDCCARagAwIBAgIUZmoW2xVdwkZSvglnkCq0AHKa6zIwCgYIKoZIzj0EAwIw +HjEcMBoGA1UEAwwTVnlPUyBjbGllbnQgcm9vdCBDQTAeFw0yMjAyMTcxOTQxMjFa +Fw0zMjAyMTUxOTQxMjFaMB4xHDAaBgNVBAMME1Z5T1MgY2xpZW50IHJvb3QgQ0Ew +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATUpKXzQk2NOVKDN4VULk2yw4mOKPvn +mg947+VY7lbpfOfAUD0QRg95qZWCw899eKnXp/U4TkAVrmEKhUb6OJTFozIwMDAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTXu6xGWUl25X3sBtrhm3BJSICIATAK +BggqhkjOPQQDAgNIADBFAiEAnTzEwuTI9bz2Oae3LZbjP6f/f50KFJtjLZFDbQz7 +DpYCIDNRHV8zBUibC+zg5PqMpQBKd/oPfNU76nEv6xkp/ijO +""" + +client_ca_intermediate_cert_data = """ +MIIBmDCCAT+gAwIBAgIUJEMdotgqA7wU4XXJvEzDulUAGqgwCgYIKoZIzj0EAwIw +HjEcMBoGA1UEAwwTVnlPUyBjbGllbnQgcm9vdCBDQTAeFw0yMjAyMTcxOTQxMjJa +Fw0zMjAyMTUxOTQxMjJaMCYxJDAiBgNVBAMMG1Z5T1MgY2xpZW50IGludGVybWVk +aWF0ZSBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGyIVIi217s9j3O+WQ2b +6R65/Z0ZjQpELxPjBRc0CA0GFCo+pI5EvwI+jNFArvTAJ5+ZdEWUJ1DQhBKDDQdI +avCjUzBRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOUS8oNJjChB1Rb9Blcl +ETvziHJ9MB8GA1UdIwQYMBaAFNe7rEZZSXblfewG2uGbcElIgIgBMAoGCCqGSM49 +BAMCA0cAMEQCIArhaxWgRsAUbEeNHD/ULtstLHxw/P97qPUSROLQld53AiBjgiiz +9pDfISmpekZYz6bIDWRIR0cXUToZEMFNzNMrQg== +""" + +client_cert_data = """ +MIIBmTCCAUCgAwIBAgIUV5T77XdE/tV82Tk4Vzhp5BIFFm0wCgYIKoZIzj0EAwIw +JjEkMCIGA1UEAwwbVnlPUyBjbGllbnQgaW50ZXJtZWRpYXRlIENBMB4XDTIyMDIx +NzE5NDEyMloXDTMyMDIxNTE5NDEyMlowIjEgMB4GA1UEAwwXVnlPUyBjbGllbnQg +Y2VydGlmaWNhdGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARuyynqfc/qJj5e +KJ03oOH8X4Z8spDeAPO9WYckMM0ldPj+9kU607szFzPwjaPWzPdgyIWz3hcN8yAh +CIhytmJao1AwTjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTIFKrxZ+PqOhYSUqnl +TGCUmM7wTjAfBgNVHSMEGDAWgBTlEvKDSYwoQdUW/QZXJRE784hyfTAKBggqhkjO +PQQDAgNHADBEAiAvO8/jvz05xqmP3OXD53XhfxDLMIxzN4KPoCkFqvjlhQIgIHq2 +/geVx3rAOtSps56q/jiDouN/aw01TdpmGKVAa9U= +""" + +client_key_data = """ +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgxaxAQsJwjoOCByQE ++qSYKtKtJzbdbOnTsKNSrfgkFH6hRANCAARuyynqfc/qJj5eKJ03oOH8X4Z8spDe +APO9WYckMM0ldPj+9kU607szFzPwjaPWzPdgyIWz3hcN8yAhCIhytmJa """ def get_wpa_supplicant_value(interface, key): @@ -51,9 +101,14 @@ def get_wpa_supplicant_value(interface, key): tmp = re.findall(r'\n?{}=(.*)'.format(key), tmp) return tmp[0] +def get_certificate_count(interface, cert_type): + tmp = read_file(f'/run/wpa_supplicant/{interface}_{cert_type}.pem') + return tmp.count(CERT_BEGIN) + class EthernetInterfaceTest(BasicInterfaceTest.TestCase): @classmethod def setUpClass(cls): + cls._test_dhcp = True cls._test_ip = True cls._test_ipv6 = True cls._test_ipv6_pd = True @@ -79,7 +134,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase): cls._macs[interface] = read_file(f'/sys/class/net/{interface}/address') # call base-classes classmethod - super(cls, cls).setUpClass() + super(EthernetInterfaceTest, cls).setUpClass() def tearDown(self): for interface in self._interfaces: @@ -91,30 +146,19 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase): self.cli_set(self._base_path + [interface, 'speed', 'auto']) self.cli_set(self._base_path + [interface, 'hw-id', self._macs[interface]]) - # Tear down mirror interfaces for SPAN (Switch Port Analyzer) - for span in self._mirror_interfaces: - section = Section.section(span) - self.cli_delete(['interfaces', section, span]) - self.cli_commit() - def test_dhcp_disable_interface(self): - # When interface is configured as admin down, it must be admin down - # even when dhcpc starts on the given interface - for interface in self._interfaces: - self.cli_set(self._base_path + [interface, 'disable']) - - # Also enable DHCP (ISC DHCP always places interface in admin up - # state so we check that we do not start DHCP client. - # https://phabricator.vyos.net/T2767 - self.cli_set(self._base_path + [interface, 'address', 'dhcp']) - - self.cli_commit() - - # Validate interface state - for interface in self._interfaces: - flags = read_file(f'/sys/class/net/{interface}/flags') - self.assertEqual(int(flags, 16) & 1, 0) + # Verify that no address remains on the system as this is an eternal + # interface. + for intf in self._interfaces: + self.assertNotIn(AF_INET, ifaddresses(intf)) + # required for IPv6 link-local address + self.assertIn(AF_INET6, ifaddresses(intf)) + for addr in ifaddresses(intf)[AF_INET6]: + # checking link local addresses makes no sense + if is_ipv6_link_local(addr['addr']): + continue + 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, @@ -165,16 +209,23 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase): self.cli_commit() def test_eapol_support(self): - ca_name = 'eapol' - cert_name = 'eapol' + ca_certs = { + 'eapol-server-ca-root': server_ca_root_cert_data, + 'eapol-server-ca-intermediate': server_ca_intermediate_cert_data, + 'eapol-client-ca-root': client_ca_root_cert_data, + 'eapol-client-ca-intermediate': client_ca_intermediate_cert_data, + } + cert_name = 'eapol-client' - self.cli_set(['pki', 'ca', ca_name, 'certificate', cert_data.replace('\n','')]) - self.cli_set(['pki', 'certificate', cert_name, 'certificate', cert_data.replace('\n','')]) - self.cli_set(['pki', 'certificate', cert_name, 'private', 'key', key_data.replace('\n','')]) + for name, data in ca_certs.items(): + self.cli_set(['pki', 'ca', name, 'certificate', data.replace('\n','')]) + + self.cli_set(['pki', 'certificate', cert_name, 'certificate', client_cert_data.replace('\n','')]) + self.cli_set(['pki', 'certificate', cert_name, 'private', 'key', client_key_data.replace('\n','')]) for interface in self._interfaces: # Enable EAPoL - self.cli_set(self._base_path + [interface, 'eapol', 'ca-certificate', ca_name]) + self.cli_set(self._base_path + [interface, 'eapol', 'ca-certificate', 'eapol-server-ca-intermediate']) self.cli_set(self._base_path + [interface, 'eapol', 'certificate', cert_name]) self.cli_commit() @@ -206,7 +257,12 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase): tmp = get_wpa_supplicant_value(interface, 'identity') self.assertEqual(f'"{mac}"', tmp) - self.cli_delete(['pki', 'ca', ca_name]) + # Check certificate files have the full chain + self.assertEqual(get_certificate_count(interface, 'ca'), 2) + self.assertEqual(get_certificate_count(interface, 'cert'), 3) + + for name in ca_certs: + self.cli_delete(['pki', 'ca', name]) self.cli_delete(['pki', 'certificate', cert_name]) if __name__ == '__main__': diff --git a/smoketest/scripts/cli/test_interfaces_geneve.py b/smoketest/scripts/cli/test_interfaces_geneve.py index 6233ade6e..0e5098aa7 100755 --- a/smoketest/scripts/cli/test_interfaces_geneve.py +++ b/smoketest/scripts/cli/test_interfaces_geneve.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -34,7 +34,7 @@ class GeneveInterfaceTest(BasicInterfaceTest.TestCase): } cls._interfaces = list(cls._options) # call base-classes classmethod - super(cls, cls).setUpClass() + super(GeneveInterfaceTest, cls).setUpClass() def test_geneve_parameters(self): tos = '40' @@ -43,7 +43,7 @@ class GeneveInterfaceTest(BasicInterfaceTest.TestCase): for option in self._options.get(intf, []): self.cli_set(self._base_path + [intf] + option.split()) - self.cli_set(self._base_path + [intf, 'parameters', 'ip', 'dont-fragment']) + self.cli_set(self._base_path + [intf, 'parameters', 'ip', 'df', 'set']) self.cli_set(self._base_path + [intf, 'parameters', 'ip', 'tos', tos]) self.cli_set(self._base_path + [intf, 'parameters', 'ip', 'ttl', str(ttl)]) ttl += 10 diff --git a/smoketest/scripts/cli/test_interfaces_l2tpv3.py b/smoketest/scripts/cli/test_interfaces_l2tpv3.py index 06ced5c40..aed8e6f15 100755 --- a/smoketest/scripts/cli/test_interfaces_l2tpv3.py +++ b/smoketest/scripts/cli/test_interfaces_l2tpv3.py @@ -39,7 +39,7 @@ class L2TPv3InterfaceTest(BasicInterfaceTest.TestCase): } cls._interfaces = list(cls._options) # call base-classes classmethod - super(cls, cls).setUpClass() + super(L2TPv3InterfaceTest, cls).setUpClass() def test_add_single_ip_address(self): super().test_add_single_ip_address() diff --git a/smoketest/scripts/cli/test_interfaces_loopback.py b/smoketest/scripts/cli/test_interfaces_loopback.py index 85b5ca6d6..5ff9c250e 100755 --- a/smoketest/scripts/cli/test_interfaces_loopback.py +++ b/smoketest/scripts/cli/test_interfaces_loopback.py @@ -29,7 +29,7 @@ class LoopbackInterfaceTest(BasicInterfaceTest.TestCase): cls._base_path = ['interfaces', 'loopback'] cls._interfaces = ['lo'] # call base-classes classmethod - super(cls, cls).setUpClass() + super(LoopbackInterfaceTest, cls).setUpClass() def tearDown(self): self.cli_delete(self._base_path) diff --git a/smoketest/scripts/cli/test_interfaces_macsec.py b/smoketest/scripts/cli/test_interfaces_macsec.py index e4280a5b7..e5e5a558e 100755 --- a/smoketest/scripts/cli/test_interfaces_macsec.py +++ b/smoketest/scripts/cli/test_interfaces_macsec.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -40,6 +40,7 @@ def get_cipher(interface): class MACsecInterfaceTest(BasicInterfaceTest.TestCase): @classmethod def setUpClass(cls): + cls._test_dhcp = True cls._test_ip = True cls._test_ipv6 = True cls._base_path = ['interfaces', 'macsec'] @@ -52,7 +53,7 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase): cls._interfaces = list(cls._options) # call base-classes classmethod - super(cls, cls).setUpClass() + super(MACsecInterfaceTest, cls).setUpClass() def test_macsec_encryption(self): # MACsec can be operating in authentication and encryption mode - both diff --git a/smoketest/scripts/cli/test_interfaces_netns.py b/smoketest/scripts/cli/test_interfaces_netns.py new file mode 100755 index 000000000..9975a6b09 --- /dev/null +++ b/smoketest/scripts/cli/test_interfaces_netns.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 re +import os +import json +import unittest + +from netifaces import interfaces +from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.configsession import ConfigSession +from vyos.configsession import ConfigSessionError +from vyos.ifconfig import Interface +from vyos.ifconfig import Section +from vyos.util import cmd + +base_path = ['netns'] +namespaces = ['mgmt', 'front', 'back', 'ams-ix'] + +class NETNSTest(VyOSUnitTestSHIM.TestCase): + + def setUp(self): + self._interfaces = ['dum10', 'dum12', 'dum50'] + + def test_create_netns(self): + for netns in namespaces: + base = base_path + ['name', netns] + self.cli_set(base) + + # commit changes + self.cli_commit() + + netns_list = cmd('ip netns ls') + + # Verify NETNS configuration + for netns in namespaces: + self.assertTrue(netns in netns_list) + + + def test_netns_assign_interface(self): + netns = 'foo' + self.cli_set(['netns', 'name', netns]) + + # Set + for iface in self._interfaces: + self.cli_set(['interfaces', 'dummy', iface, 'netns', netns]) + + # commit changes + self.cli_commit() + + netns_iface_list = cmd(f'sudo ip netns exec {netns} ip link show') + + for iface in self._interfaces: + self.assertTrue(iface in netns_iface_list) + + # Delete + for iface in self._interfaces: + self.cli_delete(['interfaces', 'dummy', iface, 'netns', netns]) + + # commit changes + self.cli_commit() + + netns_iface_list = cmd(f'sudo ip netns exec {netns} ip link show') + + for iface in self._interfaces: + self.assertNotIn(iface, netns_iface_list) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_openvpn.py b/smoketest/scripts/cli/test_interfaces_openvpn.py index f8a6ae986..b2143d16e 100755 --- a/smoketest/scripts/cli/test_interfaces_openvpn.py +++ b/smoketest/scripts/cli/test_interfaces_openvpn.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -37,10 +37,46 @@ PROCESS_NAME = 'openvpn' base_path = ['interfaces', 'openvpn'] -cert_data = 'MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIwWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIxMDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu+JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3LftzngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93+dm/LDnp7C0=' -key_data = 'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww' -dh_data = 'MIIBCAKCAQEApzGAPcQlLJiOyfGZgl1qxNgufXkdpjG7lMaOrO4TGr1giFe3jIFOFxJNC/G9Dn+KSukaWssVVR+Jwr/JesZFPawihS03wC7cZsccykNRIjiteqJDwYJZUHieOxyCuCeY4pqOUCl1uswRGjLvIFtwynpnXKKuz2YtjNifma90PEgv/vVWKix+Q0TAbdbzJzO5xp8UVn9DuYfSr10k3LbDqDM7w5ezHZxFk24S5pN/yoOpdbxB8TS67q3IYXxR3F+RseKu4J3AvkxXSP1j7COXddPpLnvbJT/SW8NrjuC/n0eKGvmeyqNv108Y89jnT79MxMMRQk66iwlsd1m4pa/OYwIBAg==' -ovpn_key_data = '443f2a710ac411c36894b2531e62c4550b079b8f3f08997f4be57c64abfdaaa431d2396b01ecec3a2c0618959e8186d99f489742d25673ffb3268841ebb2e7042a2daabe584e79d51d2b1d7409bf8840f7e42efa3e660a521719b04ee88b9043e6315ae12da7c9abd55f67eeed71a9ee8c6e163b5d2661fc332cf90cb45658b4adf892f79537d37d3a3d90da283ce885adf325ffd2b5be92067cdf0345c7712c9d36b642c170351b6d9ce9f6230c7a2617b0c181121bce7d5373404fb68e65210b36e6d40ef2769cf8990503859f6f2db3c85ba74420430a6250d6a74ca51ece4b85124bfdfec0c8a530cefa7350378d81a4539f74bed832a902ae4798142e4a' +cert_data = """ +MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIw +WTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNv +bWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIx +MDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNV +BAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlP +UzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3 +QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu ++JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3Lftz +ngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93 ++dm/LDnp7C0= +""" + +key_data = """ +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx +2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7 +u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww +""" + +dh_data = """ +MIIBCAKCAQEApzGAPcQlLJiOyfGZgl1qxNgufXkdpjG7lMaOrO4TGr1giFe3jIFO +FxJNC/G9Dn+KSukaWssVVR+Jwr/JesZFPawihS03wC7cZsccykNRIjiteqJDwYJZ +UHieOxyCuCeY4pqOUCl1uswRGjLvIFtwynpnXKKuz2YtjNifma90PEgv/vVWKix+ +Q0TAbdbzJzO5xp8UVn9DuYfSr10k3LbDqDM7w5ezHZxFk24S5pN/yoOpdbxB8TS6 +7q3IYXxR3F+RseKu4J3AvkxXSP1j7COXddPpLnvbJT/SW8NrjuC/n0eKGvmeyqNv +108Y89jnT79MxMMRQk66iwlsd1m4pa/OYwIBAg== +""" + +ovpn_key_data = """ +443f2a710ac411c36894b2531e62c4550b079b8f3f08997f4be57c64abfdaaa4 +31d2396b01ecec3a2c0618959e8186d99f489742d25673ffb3268841ebb2e704 +2a2daabe584e79d51d2b1d7409bf8840f7e42efa3e660a521719b04ee88b9043 +e6315ae12da7c9abd55f67eeed71a9ee8c6e163b5d2661fc332cf90cb45658b4 +adf892f79537d37d3a3d90da283ce885adf325ffd2b5be92067cdf0345c7712c +9d36b642c170351b6d9ce9f6230c7a2617b0c181121bce7d5373404fb68e6521 +0b36e6d40ef2769cf8990503859f6f2db3c85ba74420430a6250d6a74ca51ece +4b85124bfdfec0c8a530cefa7350378d81a4539f74bed832a902ae4798142e4a +""" remote_port = '1194' protocol = 'udp' @@ -59,20 +95,28 @@ def get_vrf(interface): return tmp class TestInterfacesOpenVPN(VyOSUnitTestSHIM.TestCase): - def setUp(self): - self.cli_set(['interfaces', 'dummy', dummy_if, 'address', '192.0.2.1/32']) - self.cli_set(['vrf', 'name', vrf_name, 'table', '12345']) + @classmethod + def setUpClass(cls): + super(TestInterfacesOpenVPN, cls).setUpClass() - self.cli_set(['pki', 'ca', 'ovpn_test', 'certificate', cert_data]) - self.cli_set(['pki', 'certificate', 'ovpn_test', 'certificate', cert_data]) - self.cli_set(['pki', 'certificate', 'ovpn_test', 'private', 'key', key_data]) - self.cli_set(['pki', 'dh', 'ovpn_test', 'parameters', dh_data]) - self.cli_set(['pki', 'openvpn', 'shared-secret', 'ovpn_test', 'key', ovpn_key_data]) + cls.cli_set(cls, ['interfaces', 'dummy', dummy_if, 'address', '192.0.2.1/32']) + cls.cli_set(cls, ['vrf', 'name', vrf_name, 'table', '12345']) + + cls.cli_set(cls, ['pki', 'ca', 'ovpn_test', 'certificate', cert_data.replace('\n','')]) + cls.cli_set(cls, ['pki', 'certificate', 'ovpn_test', 'certificate', cert_data.replace('\n','')]) + cls.cli_set(cls, ['pki', 'certificate', 'ovpn_test', 'private', 'key', key_data.replace('\n','')]) + cls.cli_set(cls, ['pki', 'dh', 'ovpn_test', 'parameters', dh_data.replace('\n','')]) + cls.cli_set(cls, ['pki', 'openvpn', 'shared-secret', 'ovpn_test', 'key', ovpn_key_data.replace('\n','')]) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['interfaces', 'dummy', dummy_if]) + cls.cli_delete(cls, ['vrf']) + + super(TestInterfacesOpenVPN, cls).tearDownClass() def tearDown(self): self.cli_delete(base_path) - self.cli_delete(['interfaces', 'dummy', dummy_if]) - self.cli_delete(['vrf']) self.cli_commit() def test_openvpn_client_verify(self): @@ -532,6 +576,46 @@ class TestInterfacesOpenVPN(VyOSUnitTestSHIM.TestCase): self.cli_commit() + def test_openvpn_options(self): + # Ensure OpenVPN process restart on openvpn-option CLI node change + + interface = 'vtun5001' + path = base_path + [interface] + + self.cli_set(path + ['mode', 'site-to-site']) + self.cli_set(path + ['local-address', '10.0.0.2']) + self.cli_set(path + ['remote-address', '192.168.0.3']) + self.cli_set(path + ['shared-secret-key', 'ovpn_test']) + + self.cli_commit() + + # Now verify the OpenVPN "raw" option passing. Once an openvpn-option is + # added, modified or deleted from the CLI, OpenVPN daemon must be restarted + cur_pid = process_named_running('openvpn') + self.cli_set(path + ['openvpn-option', '--persist-tun']) + self.cli_commit() + + # PID must be different as OpenVPN Must be restarted + new_pid = process_named_running('openvpn') + self.assertNotEqual(cur_pid, new_pid) + cur_pid = new_pid + + self.cli_set(path + ['openvpn-option', '--persist-key']) + self.cli_commit() + + # PID must be different as OpenVPN Must be restarted + new_pid = process_named_running('openvpn') + self.assertNotEqual(cur_pid, new_pid) + cur_pid = new_pid + + self.cli_delete(path + ['openvpn-option']) + self.cli_commit() + + # PID must be different as OpenVPN Must be restarted + new_pid = process_named_running('openvpn') + self.assertNotEqual(cur_pid, new_pid) + cur_pid = new_pid + def test_openvpn_site2site_interfaces_tun(self): # Create two OpenVPN site-to-site interfaces diff --git a/smoketest/scripts/cli/test_interfaces_pppoe.py b/smoketest/scripts/cli/test_interfaces_pppoe.py index 4f1e1ee99..8927121a8 100755 --- a/smoketest/scripts/cli/test_interfaces_pppoe.py +++ b/smoketest/scripts/cli/test_interfaces_pppoe.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2021 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 @@ -34,9 +34,12 @@ def get_config_value(interface, key): # add a classmethod to setup a temporaray PPPoE server for "proper" validation class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase): - def setUp(self): - self._interfaces = ['pppoe10', 'pppoe20', 'pppoe30'] - self._source_interface = 'eth0' + @classmethod + def setUpClass(cls): + super(PPPoEInterfaceTest, cls).setUpClass() + + cls._interfaces = ['pppoe10', 'pppoe20', 'pppoe30'] + cls._source_interface = 'eth0' def tearDown(self): # Validate PPPoE client process @@ -60,7 +63,6 @@ class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + [interface, 'authentication', 'user', user]) self.cli_set(base_path + [interface, 'authentication', 'password', passwd]) - self.cli_set(base_path + [interface, 'default-route', 'auto']) self.cli_set(base_path + [interface, 'mtu', mtu]) self.cli_set(base_path + [interface, 'no-peer-dns']) @@ -136,7 +138,7 @@ class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase): for interface in self._interfaces: self.cli_set(base_path + [interface, 'authentication', 'user', 'vyos']) self.cli_set(base_path + [interface, 'authentication', 'password', 'vyos']) - self.cli_set(base_path + [interface, 'default-route', 'none']) + self.cli_set(base_path + [interface, 'no-default-route']) self.cli_set(base_path + [interface, 'no-peer-dns']) self.cli_set(base_path + [interface, 'source-interface', self._source_interface]) self.cli_set(base_path + [interface, 'ipv6', 'address', 'autoconf']) diff --git a/smoketest/scripts/cli/test_interfaces_pseudo_ethernet.py b/smoketest/scripts/cli/test_interfaces_pseudo_ethernet.py index ae899cddd..a51b8d52c 100755 --- a/smoketest/scripts/cli/test_interfaces_pseudo_ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_pseudo_ethernet.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -23,6 +23,7 @@ from base_interfaces_test import BasicInterfaceTest class PEthInterfaceTest(BasicInterfaceTest.TestCase): @classmethod def setUpClass(cls): + cls._test_dhcp = True cls._test_ip = True cls._test_ipv6 = True cls._test_ipv6_pd = True @@ -47,7 +48,7 @@ class PEthInterfaceTest(BasicInterfaceTest.TestCase): cls._interfaces = list(cls._options) # call base-classes classmethod - super(cls, cls).setUpClass() + super(PEthInterfaceTest, cls).setUpClass() if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_tunnel.py b/smoketest/scripts/cli/test_interfaces_tunnel.py index fc2e254d6..44bfbb5f0 100755 --- a/smoketest/scripts/cli/test_interfaces_tunnel.py +++ b/smoketest/scripts/cli/test_interfaces_tunnel.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -42,16 +42,16 @@ class TunnelInterfaceTest(BasicInterfaceTest.TestCase): } cls._interfaces = list(cls._options) # call base-classes classmethod - super(cls, cls).setUpClass() + super(TunnelInterfaceTest, cls).setUpClass() - def setUp(self): - super().setUp() - self.cli_set(['interfaces', 'dummy', source_if, 'address', self.local_v4 + '/32']) - self.cli_set(['interfaces', 'dummy', source_if, 'address', self.local_v6 + '/128']) + # create some test interfaces + cls.cli_set(cls, ['interfaces', 'dummy', source_if, 'address', cls.local_v4 + '/32']) + cls.cli_set(cls, ['interfaces', 'dummy', source_if, 'address', cls.local_v6 + '/128']) - def tearDown(self): - self.cli_delete(['interfaces', 'dummy', source_if]) - super().tearDown() + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['interfaces', 'dummy', source_if]) + super().tearDownClass() def test_ipv4_encapsulations(self): # When running tests ensure that for certain encapsulation types the @@ -202,7 +202,7 @@ class TunnelInterfaceTest(BasicInterfaceTest.TestCase): self.assertEqual(encapsulation, conf['linkinfo']['info_kind']) self.assertEqual(self.local_v4, conf['linkinfo']['info_data']['local']) self.assertEqual(remote_ip4, conf['linkinfo']['info_data']['remote']) - self.assertEqual(64, conf['linkinfo']['info_data']['ttl']) + self.assertEqual(64, conf['linkinfo']['info_data']['ttl']) # Change remote ip address (inc host by 2 new_remote = inc_ip(remote_ip4, 2) @@ -239,7 +239,7 @@ class TunnelInterfaceTest(BasicInterfaceTest.TestCase): self.assertEqual(encapsulation, conf['linkinfo']['info_kind']) self.assertEqual(self.local_v4, conf['linkinfo']['info_data']['local']) self.assertEqual(remote_ip4, conf['linkinfo']['info_data']['remote']) - self.assertEqual(64, conf['linkinfo']['info_data']['ttl']) + self.assertEqual(64, conf['linkinfo']['info_data']['ttl']) self.assertEqual(f'0.0.0.{ip_key}', conf['linkinfo']['info_data']['ikey']) self.assertEqual(f'0.0.0.{ip_key}', conf['linkinfo']['info_data']['okey']) self.assertEqual(int(idx), conf['linkinfo']['info_data']['erspan_index']) @@ -295,7 +295,7 @@ class TunnelInterfaceTest(BasicInterfaceTest.TestCase): self.assertEqual(encapsulation, conf['linkinfo']['info_kind']) self.assertEqual(self.local_v6, conf['linkinfo']['info_data']['local']) self.assertEqual(remote_ip6, conf['linkinfo']['info_data']['remote']) - self.assertEqual(64, conf['linkinfo']['info_data']['ttl']) + self.assertEqual(64, conf['linkinfo']['info_data']['ttl']) self.assertEqual(f'0.0.0.{ip_key}', conf['linkinfo']['info_data']['ikey']) self.assertEqual(f'0.0.0.{ip_key}', conf['linkinfo']['info_data']['okey']) self.assertEqual(erspan_ver, conf['linkinfo']['info_data']['erspan_ver']) @@ -312,5 +312,89 @@ class TunnelInterfaceTest(BasicInterfaceTest.TestCase): conf = get_interface_config(interface) self.assertEqual(new_remote, conf['linkinfo']['info_data']['remote']) + def test_tunnel_src_any_gre_key(self): + interface = f'tun1280' + encapsulation = 'gre' + src_addr = '0.0.0.0' + key = '127' + + self.cli_set(self._base_path + [interface, 'encapsulation', encapsulation]) + self.cli_set(self._base_path + [interface, 'source-address', src_addr]) + # GRE key must be supplied with a 0.0.0.0 source address + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(self._base_path + [interface, 'parameters', 'ip', 'key', key]) + + self.cli_commit() + + def test_multiple_gre_tunnel_same_remote(self): + tunnels = { + 'tun10' : { + 'encapsulation' : 'gre', + 'source_interface' : source_if, + 'remote' : '1.2.3.4', + }, + 'tun20' : { + 'encapsulation' : 'gre', + 'source_interface' : source_if, + 'remote' : '1.2.3.4', + }, + } + + for tunnel, tunnel_config in tunnels.items(): + self.cli_set(self._base_path + [tunnel, 'encapsulation', tunnel_config['encapsulation']]) + if 'source_interface' in tunnel_config: + self.cli_set(self._base_path + [tunnel, 'source-interface', tunnel_config['source_interface']]) + if 'remote' in tunnel_config: + self.cli_set(self._base_path + [tunnel, 'remote', tunnel_config['remote']]) + + # GRE key must be supplied when two or more tunnels are formed to the same desitnation + with self.assertRaises(ConfigSessionError): + self.cli_commit() + for tunnel, tunnel_config in tunnels.items(): + self.cli_set(self._base_path + [tunnel, 'parameters', 'ip', 'key', tunnel.lstrip('tun')]) + + self.cli_commit() + + for tunnel, tunnel_config in tunnels.items(): + conf = get_interface_config(tunnel) + ip_key = tunnel.lstrip('tun') + + self.assertEqual(tunnel_config['source_interface'], conf['link']) + self.assertEqual(tunnel_config['encapsulation'], conf['linkinfo']['info_kind']) + self.assertEqual(tunnel_config['remote'], conf['linkinfo']['info_data']['remote']) + self.assertEqual(f'0.0.0.{ip_key}', conf['linkinfo']['info_data']['ikey']) + self.assertEqual(f'0.0.0.{ip_key}', conf['linkinfo']['info_data']['okey']) + + def test_multiple_gre_tunnel_different_remote(self): + tunnels = { + 'tun10' : { + 'encapsulation' : 'gre', + 'source_interface' : source_if, + 'remote' : '1.2.3.4', + }, + 'tun20' : { + 'encapsulation' : 'gre', + 'source_interface' : source_if, + 'remote' : '1.2.3.5', + }, + } + + for tunnel, tunnel_config in tunnels.items(): + self.cli_set(self._base_path + [tunnel, 'encapsulation', tunnel_config['encapsulation']]) + if 'source_interface' in tunnel_config: + self.cli_set(self._base_path + [tunnel, 'source-interface', tunnel_config['source_interface']]) + if 'remote' in tunnel_config: + self.cli_set(self._base_path + [tunnel, 'remote', tunnel_config['remote']]) + + self.cli_commit() + + for tunnel, tunnel_config in tunnels.items(): + conf = get_interface_config(tunnel) + + self.assertEqual(tunnel_config['source_interface'], conf['link']) + self.assertEqual(tunnel_config['encapsulation'], conf['linkinfo']['info_kind']) + self.assertEqual(tunnel_config['remote'], conf['linkinfo']['info_data']['remote']) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_vxlan.py b/smoketest/scripts/cli/test_interfaces_vxlan.py index f63c850d8..058f13721 100755 --- a/smoketest/scripts/cli/test_interfaces_vxlan.py +++ b/smoketest/scripts/cli/test_interfaces_vxlan.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -16,9 +16,11 @@ import unittest +from vyos.configsession import ConfigSessionError from vyos.ifconfig import Interface +from vyos.util import get_bridge_fdb from vyos.util import get_interface_config - +from vyos.template import is_ipv6 from base_interfaces_test import BasicInterfaceTest class VXLANInterfaceTest(BasicInterfaceTest.TestCase): @@ -32,10 +34,12 @@ class VXLANInterfaceTest(BasicInterfaceTest.TestCase): 'vxlan10': ['vni 10', 'remote 127.0.0.2'], 'vxlan20': ['vni 20', 'group 239.1.1.1', 'source-interface eth0'], 'vxlan30': ['vni 30', 'remote 2001:db8:2000::1', 'source-address 2001:db8:1000::1', 'parameters ipv6 flowlabel 0x1000'], + 'vxlan40': ['vni 40', 'remote 127.0.0.2', 'remote 127.0.0.3'], + 'vxlan50': ['vni 50', 'remote 2001:db8:2000::1', 'remote 2001:db8:2000::2', 'parameters ipv6 flowlabel 0x1000'], } cls._interfaces = list(cls._options) # call base-classes classmethod - super(cls, cls).setUpClass() + super(VXLANInterfaceTest, cls).setUpClass() def test_vxlan_parameters(self): tos = '40' @@ -44,7 +48,7 @@ class VXLANInterfaceTest(BasicInterfaceTest.TestCase): for option in self._options.get(intf, []): self.cli_set(self._base_path + [intf] + option.split()) - self.cli_set(self._base_path + [intf, 'parameters', 'ip', 'dont-fragment']) + self.cli_set(self._base_path + [intf, 'parameters', 'ip', 'df', 'set']) self.cli_set(self._base_path + [intf, 'parameters', 'ip', 'tos', tos]) self.cli_set(self._base_path + [intf, 'parameters', 'ip', 'ttl', str(ttl)]) ttl += 10 @@ -54,21 +58,34 @@ class VXLANInterfaceTest(BasicInterfaceTest.TestCase): ttl = 20 for interface in self._interfaces: options = get_interface_config(interface) + bridge = get_bridge_fdb(interface) vni = options['linkinfo']['info_data']['id'] self.assertIn(f'vni {vni}', self._options[interface]) - if any('link' in s for s in self._options[interface]): + if any('source-interface' in s for s in self._options[interface]): link = options['linkinfo']['info_data']['link'] self.assertIn(f'source-interface {link}', self._options[interface]) - if any('local6' in s for s in self._options[interface]): - remote = options['linkinfo']['info_data']['local6'] - self.assertIn(f'source-address {local6}', self._options[interface]) - - if any('remote6' in s for s in self._options[interface]): - remote = options['linkinfo']['info_data']['remote6'] - self.assertIn(f'remote {remote}', self._options[interface]) + # Verify source-address setting was properly configured on the Kernel + if any('source-address' in s for s in self._options[interface]): + for s in self._options[interface]: + if 'source-address' in s: + address = s.split()[-1] + if is_ipv6(address): + tmp = options['linkinfo']['info_data']['local6'] + else: + tmp = options['linkinfo']['info_data']['local'] + self.assertIn(f'source-address {tmp}', self._options[interface]) + + # Verify remote setting was properly configured on the Kernel + if any('remote' in s for s in self._options[interface]): + for s in self._options[interface]: + if 'remote' in s: + for fdb in bridge: + if 'mac' in fdb and fdb['mac'] == '00:00:00:00:00:00': + remote = fdb['dst'] + self.assertIn(f'remote {remote}', self._options[interface]) if any('group' in s for s in self._options[interface]): group = options['linkinfo']['info_data']['group'] @@ -78,6 +95,9 @@ class VXLANInterfaceTest(BasicInterfaceTest.TestCase): label = options['linkinfo']['info_data']['label'] self.assertIn(f'parameters ipv6 flowlabel {label}', self._options[interface]) + if any('external' in s for s in self._options[interface]): + self.assertTrue(options['linkinfo']['info_data']['external']) + self.assertEqual('vxlan', options['linkinfo']['info_kind']) self.assertEqual('set', options['linkinfo']['info_data']['df']) self.assertEqual(f'0x{tos}', options['linkinfo']['info_data']['tos']) @@ -85,5 +105,36 @@ class VXLANInterfaceTest(BasicInterfaceTest.TestCase): self.assertEqual(Interface(interface).get_admin_state(), 'up') ttl += 10 + def test_vxlan_external(self): + interface = 'vxlan0' + source_address = '192.0.2.1' + self.cli_set(self._base_path + [interface, 'external']) + self.cli_set(self._base_path + [interface, 'source-address', source_address]) + + # Both 'VNI' and 'external' can not be specified at the same time. + self.cli_set(self._base_path + [interface, 'vni', '111']) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_delete(self._base_path + [interface, 'vni']) + + # Now add some more interfaces - this must fail and a CLI error needs + # to be generated as Linux can only handle one VXLAN tunnel when using + # external mode. + for intf in self._interfaces: + for option in self._options.get(intf, []): + self.cli_set(self._base_path + [intf] + option.split()) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + # Remove those test interfaces again + for intf in self._interfaces: + self.cli_delete(self._base_path + [intf]) + + self.cli_commit() + + options = get_interface_config(interface) + self.assertTrue(options['linkinfo']['info_data']['external']) + self.assertEqual('vxlan', options['linkinfo']['info_kind']) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_wireguard.py b/smoketest/scripts/cli/test_interfaces_wireguard.py index aaf27a2c4..f3e9670f7 100755 --- a/smoketest/scripts/cli/test_interfaces_wireguard.py +++ b/smoketest/scripts/cli/test_interfaces_wireguard.py @@ -23,10 +23,13 @@ from vyos.configsession import ConfigSessionError base_path = ['interfaces', 'wireguard'] class WireGuardInterfaceTest(VyOSUnitTestSHIM.TestCase): - def setUp(self): - self._test_addr = ['192.0.2.1/26', '192.0.2.255/31', '192.0.2.64/32', + @classmethod + def setUpClass(cls): + super(WireGuardInterfaceTest, cls).setUpClass() + + cls._test_addr = ['192.0.2.1/26', '192.0.2.255/31', '192.0.2.64/32', '2001:db8:1::ffff/64', '2001:db8:101::1/112'] - self._interfaces = ['wg0', 'wg1'] + cls._interfaces = ['wg0', 'wg1'] def tearDown(self): self.cli_delete(base_path) diff --git a/smoketest/scripts/cli/test_interfaces_wireless.py b/smoketest/scripts/cli/test_interfaces_wireless.py index 4f539a23c..a24f37d8d 100755 --- a/smoketest/scripts/cli/test_interfaces_wireless.py +++ b/smoketest/scripts/cli/test_interfaces_wireless.py @@ -48,7 +48,7 @@ class WirelessInterfaceTest(BasicInterfaceTest.TestCase): } cls._interfaces = list(cls._options) # call base-classes classmethod - super(cls, cls).setUpClass() + super(WirelessInterfaceTest, cls).setUpClass() def test_wireless_add_single_ip_address(self): # derived method to check if member interfaces are enslaved properly diff --git a/smoketest/scripts/cli/test_nat.py b/smoketest/scripts/cli/test_nat.py index 75c628244..408facfb3 100755 --- a/smoketest/scripts/cli/test_nat.py +++ b/smoketest/scripts/cli/test_nat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -14,7 +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 import jmespath import json import unittest @@ -29,10 +28,13 @@ src_path = base_path + ['source'] dst_path = base_path + ['destination'] class TestNAT(VyOSUnitTestSHIM.TestCase): - def setUp(self): + @classmethod + def setUpClass(cls): + super(TestNAT, cls).setUpClass() + # ensure we can also run this test on a live system - so lets clean # out the current configuration :) - self.cli_delete(base_path) + cls.cli_delete(cls, base_path) def tearDown(self): self.cli_delete(base_path) @@ -57,36 +59,44 @@ class TestNAT(VyOSUnitTestSHIM.TestCase): self.cli_commit() - tmp = cmd('sudo nft -j list table nat') + tmp = cmd('sudo nft -j list chain ip nat POSTROUTING') data_json = jmespath.search('nftables[?rule].rule[?chain]', json.loads(tmp)) for idx in range(0, len(data_json)): - rule = str(rules[idx]) data = data_json[idx] - network = f'192.168.{rule}.0/24' - - self.assertEqual(data['chain'], 'POSTROUTING') - self.assertEqual(data['comment'], f'SRC-NAT-{rule}') - self.assertEqual(data['family'], 'ip') - self.assertEqual(data['table'], 'nat') - - iface = dict_search('match.right', data['expr'][0]) - direction = dict_search('match.left.payload.field', data['expr'][1]) - address = dict_search('match.right.prefix.addr', data['expr'][1]) - mask = dict_search('match.right.prefix.len', data['expr'][1]) + if idx == 0: + self.assertEqual(data['chain'], 'POSTROUTING') + self.assertEqual(data['family'], 'ip') + self.assertEqual(data['table'], 'nat') - if int(rule) < 200: - self.assertEqual(direction, 'saddr') - self.assertEqual(iface, outbound_iface_100) - # check for masquerade keyword - self.assertIn('masquerade', data['expr'][3]) + jump_target = dict_search('jump.target', data['expr'][1]) + self.assertEqual(jump_target,'VYOS_PRE_SNAT_HOOK') else: - self.assertEqual(direction, 'daddr') - self.assertEqual(iface, outbound_iface_200) - # check for return keyword due to 'exclude' - self.assertIn('return', data['expr'][3]) - - self.assertEqual(f'{address}/{mask}', network) + rule = str(rules[idx - 1]) + network = f'192.168.{rule}.0/24' + + self.assertEqual(data['chain'], 'POSTROUTING') + self.assertEqual(data['comment'], f'SRC-NAT-{rule}') + self.assertEqual(data['family'], 'ip') + self.assertEqual(data['table'], 'nat') + + iface = dict_search('match.right', data['expr'][0]) + direction = dict_search('match.left.payload.field', data['expr'][1]) + address = dict_search('match.right.prefix.addr', data['expr'][1]) + mask = dict_search('match.right.prefix.len', data['expr'][1]) + + if int(rule) < 200: + self.assertEqual(direction, 'saddr') + self.assertEqual(iface, outbound_iface_100) + # check for masquerade keyword + self.assertIn('masquerade', data['expr'][3]) + else: + self.assertEqual(direction, 'daddr') + self.assertEqual(iface, outbound_iface_200) + # check for return keyword due to 'exclude' + self.assertIn('return', data['expr'][3]) + + self.assertEqual(f'{address}/{mask}', network) def test_dnat(self): rules = ['100', '110', '120', '130', '200', '210', '220', '230'] @@ -109,33 +119,42 @@ class TestNAT(VyOSUnitTestSHIM.TestCase): self.cli_commit() - tmp = cmd('sudo nft -j list table nat') + tmp = cmd('sudo nft -j list chain ip nat PREROUTING') data_json = jmespath.search('nftables[?rule].rule[?chain]', json.loads(tmp)) for idx in range(0, len(data_json)): - rule = str(rules[idx]) data = data_json[idx] - port = int(f'10{rule}') - - self.assertEqual(data['chain'], 'PREROUTING') - self.assertEqual(data['comment'].split()[0], f'DST-NAT-{rule}') - self.assertEqual(data['family'], 'ip') - self.assertEqual(data['table'], 'nat') - - iface = dict_search('match.right', data['expr'][0]) - direction = dict_search('match.left.payload.field', data['expr'][1]) - protocol = dict_search('match.left.payload.protocol', data['expr'][1]) - dnat_addr = dict_search('dnat.addr', data['expr'][3]) - dnat_port = dict_search('dnat.port', data['expr'][3]) - - self.assertEqual(direction, 'sport') - self.assertEqual(dnat_addr, '192.0.2.1') - self.assertEqual(dnat_port, port) - if int(rule) < 200: - self.assertEqual(iface, inbound_iface_100) - self.assertEqual(protocol, inbound_proto_100) + if idx == 0: + self.assertEqual(data['chain'], 'PREROUTING') + self.assertEqual(data['family'], 'ip') + self.assertEqual(data['table'], 'nat') + + jump_target = dict_search('jump.target', data['expr'][1]) + self.assertEqual(jump_target,'VYOS_PRE_DNAT_HOOK') else: - self.assertEqual(iface, inbound_iface_200) + + rule = str(rules[idx - 1]) + port = int(f'10{rule}') + + self.assertEqual(data['chain'], 'PREROUTING') + self.assertEqual(data['comment'].split()[0], f'DST-NAT-{rule}') + self.assertEqual(data['family'], 'ip') + self.assertEqual(data['table'], 'nat') + + iface = dict_search('match.right', data['expr'][0]) + direction = dict_search('match.left.payload.field', data['expr'][1]) + protocol = dict_search('match.left.payload.protocol', data['expr'][1]) + dnat_addr = dict_search('dnat.addr', data['expr'][3]) + dnat_port = dict_search('dnat.port', data['expr'][3]) + + self.assertEqual(direction, 'sport') + self.assertEqual(dnat_addr, '192.0.2.1') + self.assertEqual(dnat_port, port) + if int(rule) < 200: + self.assertEqual(iface, inbound_iface_100) + self.assertEqual(protocol, inbound_proto_100) + else: + self.assertEqual(iface, inbound_iface_200) def test_snat_required_translation_address(self): # T2813: Ensure translation address is specified diff --git a/smoketest/scripts/cli/test_nat66.py b/smoketest/scripts/cli/test_nat66.py index 8afe0da26..aac6a30f9 100755 --- a/smoketest/scripts/cli/test_nat66.py +++ b/smoketest/scripts/cli/test_nat66.py @@ -32,7 +32,7 @@ dst_path = base_path + ['destination'] class TestNAT66(VyOSUnitTestSHIM.TestCase): @classmethod def setUpClass(cls): - super(cls, cls).setUpClass() + super(TestNAT66, cls).setUpClass() # ensure we can also run this test on a live system - so lets clean # out the current configuration :) @@ -185,4 +185,4 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase): self.cli_commit() if __name__ == '__main__': - unittest.main(verbosity=2, failfast=True) + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_pki.py b/smoketest/scripts/cli/test_pki.py index 45a4bd61e..e92123dbc 100755 --- a/smoketest/scripts/cli/test_pki.py +++ b/smoketest/scripts/cli/test_pki.py @@ -129,8 +129,13 @@ xGsJxVHfSKeooUQn6q76sg== """ class TestPKI(VyOSUnitTestSHIM.TestCase): - def setUp(self): - self.cli_delete(base_path) + @classmethod + def setUpClass(cls): + super(TestPKI, 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) def tearDown(self): self.cli_delete(base_path) diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py index 1286a768d..e8c6ff19b 100755 --- a/smoketest/scripts/cli/test_policy.py +++ b/smoketest/scripts/cli/test_policy.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -307,7 +307,7 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): continue for rule, rule_config in as_path_config['rule'].items(): - tmp = f'bgp as-path access-list {as_path}' + tmp = f'bgp as-path access-list {as_path} seq {rule}' if rule_config['action'] == 'permit': tmp += ' permit' else: @@ -665,6 +665,40 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): self.assertIn(tmp, config) + def test_prefix_list_duplicates(self): + # FRR does not allow to specify the same profix list rule multiple times + # + # vyos(config)# ip prefix-list foo seq 10 permit 192.0.2.0/24 + # vyos(config)# ip prefix-list foo seq 20 permit 192.0.2.0/24 + # % Configuration failed. + # Error type: validation + # Error description: duplicated prefix list value: 192.0.2.0/24 + + # There is also a VyOS verify() function to test this + + prefix = '100.64.0.0/10' + prefix_list = 'duplicates' + test_range = range(20, 25) + path = base_path + ['prefix-list', prefix_list] + + for rule in test_range: + self.cli_set(path + ['rule', str(rule), 'action', 'permit']) + self.cli_set(path + ['rule', str(rule), 'prefix', prefix]) + + # Duplicate prefixes + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + for rule in test_range: + self.cli_set(path + ['rule', str(rule), 'le', str(rule)]) + + self.cli_commit() + + config = self.getFRRconfig('ip prefix-list', end='') + for rule in test_range: + tmp = f'ip prefix-list {prefix_list} seq {rule} permit {prefix} le {rule}' + self.assertIn(tmp, config) + def test_route_map(self): access_list = '50' as_path_list = '100' @@ -766,27 +800,28 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): '10' : { 'action' : 'deny', 'set' : { - 'aggregator-as' : '1234567890', - 'aggregator-ip' : '10.255.255.0', - 'as-path-exclude' : '1234', - 'as-path-prepend' : '1234567890 987654321', - 'atomic-aggregate' : '', - 'distance' : '110', - 'extcommunity-bw' : '20000', - 'extcommunity-rt' : '123:456', - 'extcommunity-soo' : '456:789', - 'ipv6-next-hop-global': '2001::1', - 'ipv6-next-hop-local' : 'fe80::1', - 'ip-next-hop' : '192.168.1.1', - 'large-community' : '100:200:300', - 'local-preference' : '500', - 'metric' : '150', - 'metric-type' : 'type-1', - 'origin' : 'incomplete', - 'originator-id' : '172.16.10.1', - 'src' : '100.0.0.1', - 'tag' : '65530', - 'weight' : '2', + 'aggregator-as' : '1234567890', + 'aggregator-ip' : '10.255.255.0', + 'as-path-exclude' : '1234', + 'as-path-prepend' : '1234567890 987654321', + 'as-path-prepend-last-as' : '5', + 'atomic-aggregate' : '', + 'distance' : '110', + 'extcommunity-bw' : '20000', + 'extcommunity-rt' : '123:456', + 'extcommunity-soo' : '456:789', + 'ipv6-next-hop-global' : '2001::1', + 'ipv6-next-hop-local' : 'fe80::1', + 'ip-next-hop' : '192.168.1.1', + 'large-community' : '100:200:300', + 'local-preference' : '500', + 'metric' : '150', + 'metric-type' : 'type-1', + 'origin' : 'incomplete', + 'originator-id' : '172.16.10.1', + 'src' : '100.0.0.1', + 'tag' : '65530', + 'weight' : '2', }, }, }, @@ -814,6 +849,13 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): 'evpn-vni' : '1234', }, }, + '20' : { + 'action' : 'permit', + 'set' : { + 'evpn-gateway-ipv4' : '192.0.2.99', + 'evpn-gateway-ipv6' : '2001:db8:f00::1', + }, + }, }, }, } @@ -924,9 +966,9 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): if 'aggregator-ip' in rule_config['set']: self.cli_set(path + ['rule', rule, 'set', 'aggregator', 'ip', rule_config['set']['aggregator-ip']]) if 'as-path-exclude' in rule_config['set']: - self.cli_set(path + ['rule', rule, 'set', 'as-path-exclude', rule_config['set']['as-path-exclude']]) + self.cli_set(path + ['rule', rule, 'set', 'as-path', 'exclude', rule_config['set']['as-path-exclude']]) if 'as-path-prepend' in rule_config['set']: - self.cli_set(path + ['rule', rule, 'set', 'as-path-prepend', rule_config['set']['as-path-prepend']]) + self.cli_set(path + ['rule', rule, 'set', 'as-path', 'prepend', rule_config['set']['as-path-prepend']]) if 'atomic-aggregate' in rule_config['set']: self.cli_set(path + ['rule', rule, 'set', 'atomic-aggregate']) if 'distance' in rule_config['set']: @@ -961,6 +1003,10 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): self.cli_set(path + ['rule', rule, 'set', 'tag', rule_config['set']['tag']]) if 'weight' in rule_config['set']: self.cli_set(path + ['rule', rule, 'set', 'weight', rule_config['set']['weight']]) + if 'evpn-gateway-ipv4' in rule_config['set']: + self.cli_set(path + ['rule', rule, 'set', 'evpn', 'gateway', 'ipv4', rule_config['set']['evpn-gateway-ipv4']]) + if 'evpn-gateway-ipv6' in rule_config['set']: + self.cli_set(path + ['rule', rule, 'set', 'evpn', 'gateway', 'ipv6', rule_config['set']['evpn-gateway-ipv6']]) self.cli_commit() @@ -1030,7 +1076,7 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): tmp = f'match ipv6 address prefix-list {rule_config["match"]["ipv6-address-pfx"]}' self.assertIn(tmp, config) if 'ipv6-nexthop' in rule_config['match']: - tmp = f'match ipv6 next-hop {rule_config["match"]["ipv6-nexthop"]}' + tmp = f'match ipv6 next-hop address {rule_config["match"]["ipv6-nexthop"]}' self.assertIn(tmp, config) if 'large-community' in rule_config['match']: tmp = f'match large-community {rule_config["match"]["large-community"]}' @@ -1084,6 +1130,8 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): tmp += 'as-path exclude ' + rule_config['set']['as-path-exclude'] elif 'as-path-prepend' in rule_config['set']: tmp += 'as-path prepend ' + rule_config['set']['as-path-prepend'] + elif 'as-path-prepend-last-as' in rule_config['set']: + tmp += 'as-path prepend last-as' + rule_config['set']['as-path-prepend-last-as'] elif 'atomic-aggregate' in rule_config['set']: tmp += 'atomic-aggregate' elif 'distance' in rule_config['set']: @@ -1118,6 +1166,10 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): tmp += 'tag ' + rule_config['set']['tag'] elif 'weight' in rule_config['set']: tmp += 'weight ' + rule_config['set']['weight'] + elif 'vpn-gateway-ipv4' in rule_config['set']: + tmp += 'evpn gateway ipv4 ' + rule_config['set']['vpn-gateway-ipv4'] + elif 'vpn-gateway-ipv6' in rule_config['set']: + tmp += 'evpn gateway ipv6 ' + rule_config['set']['vpn-gateway-ipv6'] self.assertIn(tmp, config) @@ -1135,18 +1187,13 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): self.cli_commit() - # Check generated configuration - - # Expected values original = """ 50: from 203.0.113.1 lookup 23 50: from 203.0.113.2 lookup 23 """ tmp = cmd('ip rule show prio 50') - original = original.split() - tmp = tmp.split() - self.assertEqual(tmp, original) + self.assertEqual(sort_ip(tmp), sort_ip(original)) # Test set table for fwmark def test_fwmark_table_id(self): @@ -1161,17 +1208,32 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): self.cli_commit() - # Check generated configuration - - # Expected values original = """ 101: from all fwmark 0x18 lookup 154 """ tmp = cmd('ip rule show prio 101') - original = original.split() - tmp = tmp.split() - self.assertEqual(tmp, original) + self.assertEqual(sort_ip(tmp), sort_ip(original)) + + # Test set table for destination + def test_destination_table_id(self): + path = base_path + ['local-route'] + + dst = '203.0.113.1' + rule = '102' + table = '154' + + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'destination', dst]) + + self.cli_commit() + + original = """ + 102: from all to 203.0.113.1 lookup 154 + """ + tmp = cmd('ip rule show prio 102') + + self.assertEqual(sort_ip(tmp), sort_ip(original)) # Test set table for sources with fwmark def test_fwmark_sources_table_id(self): @@ -1188,18 +1250,301 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): self.cli_commit() - # Check generated configuration - - # Expected values original = """ 100: from 203.0.113.11 fwmark 0x17 lookup 150 100: from 203.0.113.12 fwmark 0x17 lookup 150 """ tmp = cmd('ip rule show prio 100') - original = original.split() - tmp = tmp.split() - self.assertEqual(tmp, original) + self.assertEqual(sort_ip(tmp), sort_ip(original)) + + # Test set table for sources with iif + def test_iif_sources_table_id(self): + path = base_path + ['local-route'] + + sources = ['203.0.113.11', '203.0.113.12'] + iif = 'lo' + rule = '100' + table = '150' + + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'inbound-interface', iif]) + for src in sources: + self.cli_set(path + ['rule', rule, 'source', src]) + + self.cli_commit() + + # Check generated configuration + # Expected values + original = """ + 100: from 203.0.113.11 iif lo lookup 150 + 100: from 203.0.113.12 iif lo lookup 150 + """ + tmp = cmd('ip rule show prio 100') + + self.assertEqual(sort_ip(tmp), sort_ip(original)) + + # Test set table for sources and destinations with fwmark + def test_fwmark_sources_destination_table_id(self): + path = base_path + ['local-route'] + + sources = ['203.0.113.11', '203.0.113.12'] + destinations = ['203.0.113.13', '203.0.113.15'] + fwmk = '23' + rule = '103' + table = '150' + for src in sources: + for dst in destinations: + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'source', src]) + self.cli_set(path + ['rule', rule, 'destination', dst]) + self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + + self.cli_commit() + + original = """ + 103: from 203.0.113.11 to 203.0.113.13 fwmark 0x17 lookup 150 + 103: from 203.0.113.11 to 203.0.113.15 fwmark 0x17 lookup 150 + 103: from 203.0.113.12 to 203.0.113.13 fwmark 0x17 lookup 150 + 103: from 203.0.113.12 to 203.0.113.15 fwmark 0x17 lookup 150 + """ + tmp = cmd('ip rule show prio 103') + + self.assertEqual(sort_ip(tmp), sort_ip(original)) + + # Test set table ipv6 for some sources ipv6 + def test_ipv6_table_id(self): + path = base_path + ['local-route6'] + + sources = ['2001:db8:123::/48', '2001:db8:126::/48'] + rule = '50' + table = '23' + for src in sources: + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'source', src]) + + self.cli_commit() + + original = """ + 50: from 2001:db8:123::/48 lookup 23 + 50: from 2001:db8:126::/48 lookup 23 + """ + tmp = cmd('ip -6 rule show prio 50') + + self.assertEqual(sort_ip(tmp), sort_ip(original)) + + # Test set table for fwmark ipv6 + def test_fwmark_ipv6_table_id(self): + path = base_path + ['local-route6'] + + fwmk = '24' + rule = '100' + table = '154' + + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + + self.cli_commit() + + original = """ + 100: from all fwmark 0x18 lookup 154 + """ + tmp = cmd('ip -6 rule show prio 100') + + self.assertEqual(sort_ip(tmp), sort_ip(original)) + + # Test set table for destination ipv6 + def test_destination_ipv6_table_id(self): + path = base_path + ['local-route6'] + + dst = '2001:db8:1337::/126' + rule = '101' + table = '154' + + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'destination', dst]) + + self.cli_commit() + + original = """ + 101: from all to 2001:db8:1337::/126 lookup 154 + """ + tmp = cmd('ip -6 rule show prio 101') + + self.assertEqual(sort_ip(tmp), sort_ip(original)) + + # Test set table for sources with fwmark ipv6 + def test_fwmark_sources_ipv6_table_id(self): + path = base_path + ['local-route6'] + + sources = ['2001:db8:1338::/126', '2001:db8:1339::/126'] + fwmk = '23' + rule = '102' + table = '150' + for src in sources: + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'source', src]) + self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + + self.cli_commit() + + original = """ + 102: from 2001:db8:1338::/126 fwmark 0x17 lookup 150 + 102: from 2001:db8:1339::/126 fwmark 0x17 lookup 150 + """ + tmp = cmd('ip -6 rule show prio 102') + + self.assertEqual(sort_ip(tmp), sort_ip(original)) + + # Test set table for sources with iif ipv6 + def test_iif_sources_ipv6_table_id(self): + path = base_path + ['local-route6'] + + sources = ['2001:db8:1338::/126', '2001:db8:1339::/126'] + iif = 'lo' + rule = '102' + table = '150' + for src in sources: + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'source', src]) + self.cli_set(path + ['rule', rule, 'inbound-interface', iif]) + + self.cli_commit() + + # Check generated configuration + # Expected values + original = """ + 102: from 2001:db8:1338::/126 iif lo lookup 150 + 102: from 2001:db8:1339::/126 iif lo lookup 150 + """ + tmp = cmd('ip -6 rule show prio 102') + + self.assertEqual(sort_ip(tmp), sort_ip(original)) + + # Test set table for sources and destinations with fwmark ipv6 + def test_fwmark_sources_destination_ipv6_table_id(self): + path = base_path + ['local-route6'] + + sources = ['2001:db8:1338::/126', '2001:db8:1339::/56'] + destinations = ['2001:db8:13::/48', '2001:db8:16::/48'] + fwmk = '23' + rule = '103' + table = '150' + for src in sources: + for dst in destinations: + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'source', src]) + self.cli_set(path + ['rule', rule, 'destination', dst]) + self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + + self.cli_commit() + + original = """ + 103: from 2001:db8:1338::/126 to 2001:db8:13::/48 fwmark 0x17 lookup 150 + 103: from 2001:db8:1338::/126 to 2001:db8:16::/48 fwmark 0x17 lookup 150 + 103: from 2001:db8:1339::/56 to 2001:db8:13::/48 fwmark 0x17 lookup 150 + 103: from 2001:db8:1339::/56 to 2001:db8:16::/48 fwmark 0x17 lookup 150 + """ + tmp = cmd('ip -6 rule show prio 103') + + self.assertEqual(sort_ip(tmp), sort_ip(original)) + + # Test delete table for sources and destination with fwmark ipv4/ipv6 + def test_delete_ipv4_ipv6_table_id(self): + path = base_path + ['local-route'] + path_v6 = base_path + ['local-route6'] + + sources = ['203.0.113.0/24', '203.0.114.5'] + destinations = ['203.0.112.0/24', '203.0.116.5'] + sources_v6 = ['2001:db8:1338::/126', '2001:db8:1339::/56'] + destinations_v6 = ['2001:db8:13::/48', '2001:db8:16::/48'] + fwmk = '23' + rule = '103' + table = '150' + for src in sources: + for dst in destinations: + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + self.cli_set(path + ['rule', rule, 'source', src]) + self.cli_set(path + ['rule', rule, 'destination', dst]) + self.cli_set(path + ['rule', rule, 'fwmark', fwmk]) + + for src in sources_v6: + for dst in destinations_v6: + self.cli_set(path_v6 + ['rule', rule, 'set', 'table', table]) + self.cli_set(path_v6 + ['rule', rule, 'source', src]) + self.cli_set(path_v6 + ['rule', rule, 'destination', dst]) + self.cli_set(path_v6 + ['rule', rule, 'fwmark', fwmk]) + + self.cli_commit() + + original = """ + 103: from 203.0.113.0/24 to 203.0.116.5 fwmark 0x17 lookup 150 + 103: from 203.0.114.5 to 203.0.112.0/24 fwmark 0x17 lookup 150 + 103: from 203.0.114.5 to 203.0.116.5 fwmark 0x17 lookup 150 + 103: from 203.0.113.0/24 to 203.0.112.0/24 fwmark 0x17 lookup 150 + """ + original_v6 = """ + 103: from 2001:db8:1338::/126 to 2001:db8:16::/48 fwmark 0x17 lookup 150 + 103: from 2001:db8:1339::/56 to 2001:db8:13::/48 fwmark 0x17 lookup 150 + 103: from 2001:db8:1339::/56 to 2001:db8:16::/48 fwmark 0x17 lookup 150 + 103: from 2001:db8:1338::/126 to 2001:db8:13::/48 fwmark 0x17 lookup 150 + """ + tmp = cmd('ip rule show prio 103') + tmp_v6 = cmd('ip -6 rule show prio 103') + + self.assertEqual(sort_ip(tmp), sort_ip(original)) + self.assertEqual(sort_ip(tmp_v6), sort_ip(original_v6)) + + self.cli_delete(path) + self.cli_delete(path_v6) + self.cli_commit() + + tmp = cmd('ip rule show prio 103') + tmp_v6 = cmd('ip -6 rule show prio 103') + + self.assertEqual(sort_ip(tmp), []) + self.assertEqual(sort_ip(tmp_v6), []) + + # Test multiple commits ipv4 + def test_multiple_commit_ipv4_table_id(self): + path = base_path + ['local-route'] + + sources = ['192.0.2.1', '192.0.2.2'] + destination = '203.0.113.25' + rule = '105' + table = '151' + self.cli_set(path + ['rule', rule, 'set', 'table', table]) + for src in sources: + self.cli_set(path + ['rule', rule, 'source', src]) + + self.cli_commit() + + original_first = """ + 105: from 192.0.2.1 lookup 151 + 105: from 192.0.2.2 lookup 151 + """ + tmp = cmd('ip rule show prio 105') + + self.assertEqual(sort_ip(tmp), sort_ip(original_first)) + + # Create second commit with added destination + self.cli_set(path + ['rule', rule, 'destination', destination]) + self.cli_commit() + + original_second = """ + 105: from 192.0.2.1 to 203.0.113.25 lookup 151 + 105: from 192.0.2.2 to 203.0.113.25 lookup 151 + """ + tmp = cmd('ip rule show prio 105') + + self.assertEqual(sort_ip(tmp), sort_ip(original_second)) + + +def sort_ip(output): + o = '\n'.join([' '.join(line.strip().split()) for line in output.strip().splitlines()]) + o = o.splitlines() + o.sort() + return o if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_policy_route.py b/smoketest/scripts/cli/test_policy_route.py new file mode 100755 index 000000000..e2d70f289 --- /dev/null +++ b/smoketest/scripts/cli/test_policy_route.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021-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 +# 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 base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.util import cmd + +mark = '100' +table_mark_offset = 0x7fffffff +table_id = '101' +interface = 'eth0' +interface_ip = '172.16.10.1/24' + +class TestPolicyRoute(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestPolicyRoute, cls).setUpClass() + + cls.cli_set(cls, ['interfaces', 'ethernet', interface, 'address', interface_ip]) + cls.cli_set(cls, ['protocols', 'static', 'table', table_id, 'route', '0.0.0.0/0', 'interface', interface]) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['interfaces', 'ethernet', interface, 'address', interface_ip]) + cls.cli_delete(cls, ['protocols', 'static', 'table', table_id]) + + super(TestPolicyRoute, cls).tearDownClass() + + def tearDown(self): + self.cli_delete(['interfaces', 'ethernet', interface, 'policy']) + self.cli_delete(['policy', 'route']) + self.cli_delete(['policy', 'route6']) + self.cli_commit() + + def test_pbr_mark(self): + self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'source', 'address', '172.16.20.10']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'destination', 'address', '172.16.10.10']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'set', 'mark', mark]) + + self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route', 'smoketest']) + + self.cli_commit() + + mark_hex = "{0:#010x}".format(int(mark)) + + nftables_search = [ + [f'iifname "{interface}"','jump VYOS_PBR_smoketest'], + ['ip daddr 172.16.10.10', 'ip saddr 172.16.20.10', 'meta mark set ' + mark_hex], + ] + + nftables_output = cmd('sudo nft list table ip mangle') + + for search in nftables_search: + matched = False + for line in nftables_output.split("\n"): + if all(item in line for item in search): + matched = True + break + self.assertTrue(matched) + + def test_pbr_table(self): + self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'protocol', 'tcp']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'destination', 'port', '8888']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'tcp', 'flags', 'syn']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'tcp', 'flags', 'not', 'ack']) + self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'set', 'table', table_id]) + self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'protocol', 'tcp_udp']) + self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'destination', 'port', '8888']) + self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'set', 'table', table_id]) + + self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route', 'smoketest']) + self.cli_set(['interfaces', 'ethernet', interface, 'policy', 'route6', 'smoketest6']) + + self.cli_commit() + + mark_hex = "{0:#010x}".format(table_mark_offset - int(table_id)) + + # IPv4 + + nftables_search = [ + [f'iifname "{interface}"', 'jump VYOS_PBR_smoketest'], + ['tcp flags & (syn | ack) == syn', 'tcp dport { 8888 }', 'meta mark set ' + mark_hex] + ] + + nftables_output = cmd('sudo nft list table ip mangle') + + for search in nftables_search: + matched = False + for line in nftables_output.split("\n"): + if all(item in line for item in search): + matched = True + break + self.assertTrue(matched) + + # IPv6 + + nftables6_search = [ + [f'iifname "{interface}"', 'jump VYOS_PBR6_smoketest'], + ['meta l4proto { tcp, udp }', 'th dport { 8888 }', 'meta mark set ' + mark_hex] + ] + + nftables6_output = cmd('sudo nft list table ip6 mangle') + + for search in nftables6_search: + matched = False + for line in nftables6_output.split("\n"): + if all(item in line for item in search): + matched = True + break + self.assertTrue(matched) + + # IP rule fwmark -> table + + ip_rule_search = [ + ['fwmark ' + hex(table_mark_offset - int(table_id)), 'lookup ' + table_id] + ] + + ip_rule_output = cmd('ip rule show') + + for search in ip_rule_search: + matched = False + for line in ip_rule_output.split("\n"): + if all(item in line for item in search): + matched = True + break + self.assertTrue(matched) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_bfd.py b/smoketest/scripts/cli/test_protocols_bfd.py index 297398d3c..fdc254a05 100755 --- a/smoketest/scripts/cli/test_protocols_bfd.py +++ b/smoketest/scripts/cli/test_protocols_bfd.py @@ -24,30 +24,35 @@ PROCESS_NAME = 'bfdd' base_path = ['protocols', 'bfd'] dum_if = 'dum1001' +vrf_name = 'red' peers = { '192.0.2.10' : { 'intv_rx' : '500', 'intv_tx' : '600', 'multihop' : '', 'source_addr': '192.0.2.254', - }, + 'profile' : 'foo-bar-baz', + }, '192.0.2.20' : { 'echo_mode' : '', 'intv_echo' : '100', 'intv_mult' : '100', 'intv_rx' : '222', 'intv_tx' : '333', + 'passive' : '', 'shutdown' : '', + 'profile' : 'foo', 'source_intf': dum_if, - }, - '2001:db8::a' : { + }, + '2001:db8::1000:1' : { 'source_addr': '2001:db8::1', - 'source_intf': dum_if, - }, - '2001:db8::b' : { + 'vrf' : vrf_name, + }, + '2001:db8::2000:1' : { 'source_addr': '2001:db8::1', 'multihop' : '', - }, + 'profile' : 'baz_foo', + }, } profiles = { @@ -59,9 +64,15 @@ profiles = { 'intv_tx' : '333', 'shutdown' : '', }, - 'bar' : { + 'foo-bar-baz' : { + 'intv_mult' : '4', + 'intv_rx' : '400', + 'intv_tx' : '400', + }, + 'baz_foo' : { 'intv_mult' : '102', 'intv_rx' : '444', + 'passive' : '', }, } @@ -73,6 +84,8 @@ class TestProtocolsBFD(VyOSUnitTestSHIM.TestCase): self.assertTrue(process_named_running(PROCESS_NAME)) def test_bfd_peer(self): + self.cli_set(['vrf', 'name', vrf_name, 'table', '1000']) + for peer, peer_config in peers.items(): if 'echo_mode' in peer_config: self.cli_set(base_path + ['peer', peer, 'echo-mode']) @@ -86,18 +99,22 @@ class TestProtocolsBFD(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['peer', peer, 'interval', 'transmit', peer_config["intv_tx"]]) if 'multihop' in peer_config: self.cli_set(base_path + ['peer', peer, 'multihop']) + if 'passive' in peer_config: + self.cli_set(base_path + ['peer', peer, 'passive']) if 'shutdown' in peer_config: self.cli_set(base_path + ['peer', peer, 'shutdown']) if 'source_addr' in peer_config: self.cli_set(base_path + ['peer', peer, 'source', 'address', peer_config["source_addr"]]) if 'source_intf' in peer_config: self.cli_set(base_path + ['peer', peer, 'source', 'interface', peer_config["source_intf"]]) + if 'vrf' in peer_config: + self.cli_set(base_path + ['peer', peer, 'vrf', peer_config["vrf"]]) # commit changes self.cli_commit() # Verify FRR bgpd configuration - frrconfig = self.getFRRconfig('bfd') + frrconfig = self.getFRRconfig('bfd', daemon=PROCESS_NAME) for peer, peer_config in peers.items(): tmp = f'peer {peer}' if 'multihop' in peer_config: @@ -106,28 +123,33 @@ class TestProtocolsBFD(VyOSUnitTestSHIM.TestCase): tmp += f' local-address {peer_config["source_addr"]}' if 'source_intf' in peer_config: tmp += f' interface {peer_config["source_intf"]}' + if 'vrf' in peer_config: + tmp += f' vrf {peer_config["vrf"]}' self.assertIn(tmp, frrconfig) - peerconfig = self.getFRRconfig(f' peer {peer}', end='') + peerconfig = self.getFRRconfig(f' peer {peer}', end='', daemon=PROCESS_NAME) if 'echo_mode' in peer_config: self.assertIn(f'echo-mode', peerconfig) if 'intv_echo' in peer_config: - self.assertIn(f'echo-interval {peer_config["intv_echo"]}', peerconfig) + self.assertIn(f'echo receive-interval {peer_config["intv_echo"]}', peerconfig) + self.assertIn(f'echo transmit-interval {peer_config["intv_echo"]}', peerconfig) if 'intv_mult' in peer_config: self.assertIn(f'detect-multiplier {peer_config["intv_mult"]}', peerconfig) if 'intv_rx' in peer_config: self.assertIn(f'receive-interval {peer_config["intv_rx"]}', peerconfig) if 'intv_tx' in peer_config: self.assertIn(f'transmit-interval {peer_config["intv_tx"]}', peerconfig) + if 'passive' in peer_config: + self.assertIn(f'passive-mode', peerconfig) if 'shutdown' in peer_config: self.assertIn(f'shutdown', peerconfig) else: self.assertNotIn(f'shutdown', peerconfig) - def test_bfd_profile(self): - peer = '192.0.2.10' + self.cli_delete(['vrf', 'name', vrf_name]) + def test_bfd_profile(self): for profile, profile_config in profiles.items(): if 'echo_mode' in profile_config: self.cli_set(base_path + ['profile', profile, 'echo-mode']) @@ -139,10 +161,25 @@ class TestProtocolsBFD(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['profile', profile, 'interval', 'receive', profile_config["intv_rx"]]) if 'intv_tx' in profile_config: self.cli_set(base_path + ['profile', profile, 'interval', 'transmit', profile_config["intv_tx"]]) + if 'passive' in profile_config: + self.cli_set(base_path + ['profile', profile, 'passive']) if 'shutdown' in profile_config: self.cli_set(base_path + ['profile', profile, 'shutdown']) - self.cli_set(base_path + ['peer', peer, 'profile', list(profiles)[0]]) + for peer, peer_config in peers.items(): + if 'profile' in peer_config: + self.cli_set(base_path + ['peer', peer, 'profile', peer_config["profile"] + 'wrong']) + if 'source_addr' in peer_config: + self.cli_set(base_path + ['peer', peer, 'source', 'address', peer_config["source_addr"]]) + if 'source_intf' in peer_config: + self.cli_set(base_path + ['peer', peer, 'source', 'interface', peer_config["source_intf"]]) + + # BFD profile does not exist! + with self.assertRaises(ConfigSessionError): + self.cli_commit() + for peer, peer_config in peers.items(): + if 'profile' in peer_config: + self.cli_set(base_path + ['peer', peer, 'profile', peer_config["profile"]]) # commit changes self.cli_commit() @@ -151,19 +188,27 @@ class TestProtocolsBFD(VyOSUnitTestSHIM.TestCase): for profile, profile_config in profiles.items(): config = self.getFRRconfig(f' profile {profile}', endsection='^ !') if 'echo_mode' in profile_config: - self.assertIn(f'echo-mode', config) + self.assertIn(f' echo-mode', config) if 'intv_echo' in profile_config: - self.assertIn(f'echo-interval {profile_config["intv_echo"]}', config) + self.assertIn(f' echo receive-interval {profile_config["intv_echo"]}', config) + self.assertIn(f' echo transmit-interval {profile_config["intv_echo"]}', config) if 'intv_mult' in profile_config: - self.assertIn(f'detect-multiplier {profile_config["intv_mult"]}', config) + self.assertIn(f' detect-multiplier {profile_config["intv_mult"]}', config) if 'intv_rx' in profile_config: - self.assertIn(f'receive-interval {profile_config["intv_rx"]}', config) + self.assertIn(f' receive-interval {profile_config["intv_rx"]}', config) if 'intv_tx' in profile_config: - self.assertIn(f'transmit-interval {profile_config["intv_tx"]}', config) + self.assertIn(f' transmit-interval {profile_config["intv_tx"]}', config) + if 'passive' in profile_config: + self.assertIn(f' passive-mode', config) if 'shutdown' in profile_config: - self.assertIn(f'shutdown', config) + self.assertIn(f' shutdown', config) else: self.assertNotIn(f'shutdown', config) + for peer, peer_config in peers.items(): + peerconfig = self.getFRRconfig(f' peer {peer}', end='', daemon=PROCESS_NAME) + if 'profile' in peer_config: + self.assertIn(f' profile {peer_config["profile"]}', peerconfig) + 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 16284ed01..9c0c93779 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -32,119 +32,154 @@ prefix_list_in = 'pfx-foo-in' prefix_list_out = 'pfx-foo-out' prefix_list_in6 = 'pfx-foo-in6' prefix_list_out6 = 'pfx-foo-out6' +bfd_profile = 'foo-bar-baz' neighbor_config = { '192.0.2.1' : { - 'cap_dynamic' : '', - 'cap_ext_next' : '', - 'remote_as' : '100', - 'adv_interv' : '400', - 'passive' : '', - 'password' : 'VyOS-Secure123', - 'shutdown' : '', - 'cap_over' : '', - 'ttl_security' : '5', - 'local_as' : '300', - 'route_map_in' : route_map_in, - 'route_map_out': route_map_out, + 'bfd' : '', + 'cap_dynamic' : '', + 'cap_ext_next' : '', + 'remote_as' : '100', + 'adv_interv' : '400', + 'passive' : '', + 'password' : 'VyOS-Secure123', + 'shutdown' : '', + 'cap_over' : '', + 'ttl_security' : '5', + 'local_as' : '300', + 'route_map_in' : route_map_in, + 'route_map_out' : route_map_out, 'no_send_comm_ext' : '', - 'addpath_all' : '', + 'addpath_all' : '', }, '192.0.2.2' : { - 'remote_as' : '200', - 'shutdown' : '', - 'no_cap_nego' : '', - 'port' : '667', - 'cap_strict' : '', - 'pfx_list_in' : prefix_list_in, - 'pfx_list_out' : prefix_list_out, + 'bfd_profile' : bfd_profile, + 'remote_as' : '200', + 'shutdown' : '', + 'no_cap_nego' : '', + 'port' : '667', + 'cap_strict' : '', + 'advertise_map' : route_map_in, + 'non_exist_map' : route_map_out, + 'pfx_list_in' : prefix_list_in, + 'pfx_list_out' : prefix_list_out, 'no_send_comm_std' : '', }, '192.0.2.3' : { - 'description' : 'foo bar baz', - 'remote_as' : '200', - 'passive' : '', - 'multi_hop' : '5', - 'update_src' : 'lo', + 'advertise_map' : route_map_in, + 'description' : 'foo bar baz', + 'remote_as' : '200', + 'passive' : '', + 'multi_hop' : '5', + 'update_src' : 'lo', + 'peer_group' : 'foo', + 'graceful_rst' : '', }, '2001:db8::1' : { - 'cap_dynamic' : '', - 'cap_ext_next' : '', - 'remote_as' : '123', - 'adv_interv' : '400', - 'passive' : '', - 'password' : 'VyOS-Secure123', - 'shutdown' : '', - 'cap_over' : '', - 'ttl_security' : '5', - 'local_as' : '300', - 'solo' : '', - 'route_map_in' : route_map_in, - 'route_map_out': route_map_out, + 'advertise_map' : route_map_in, + 'exist_map' : route_map_out, + 'cap_dynamic' : '', + 'cap_ext_next' : '', + 'remote_as' : '123', + 'adv_interv' : '400', + 'passive' : '', + 'password' : 'VyOS-Secure123', + 'shutdown' : '', + 'cap_over' : '', + 'ttl_security' : '5', + 'local_as' : '300', + 'solo' : '', + 'route_map_in' : route_map_in, + 'route_map_out' : route_map_out, 'no_send_comm_std' : '', 'addpath_per_as' : '', + 'peer_group' : 'foo-bar', }, '2001:db8::2' : { - 'remote_as' : '456', - 'shutdown' : '', - 'no_cap_nego' : '', - 'port' : '667', - 'cap_strict' : '', - 'pfx_list_in' : prefix_list_in6, - 'pfx_list_out' : prefix_list_out6, + 'remote_as' : '456', + 'shutdown' : '', + 'no_cap_nego' : '', + 'port' : '667', + 'cap_strict' : '', + 'pfx_list_in' : prefix_list_in6, + 'pfx_list_out' : prefix_list_out6, 'no_send_comm_ext' : '', + 'peer_group' : 'foo-bar_baz', + 'graceful_rst_hlp' : '' }, } peer_group_config = { 'foo' : { - 'remote_as' : '100', - 'passive' : '', - 'password' : 'VyOS-Secure123', - 'shutdown' : '', - 'cap_over' : '', - 'ttl_security': '5', + 'advertise_map' : route_map_in, + 'exist_map' : route_map_out, + 'bfd' : '', + 'remote_as' : '100', + 'passive' : '', + 'password' : 'VyOS-Secure123', + 'shutdown' : '', + 'cap_over' : '', + 'ttl_security' : '5', }, 'bar' : { - 'description' : 'foo peer bar group', - 'remote_as' : '200', - 'shutdown' : '', - 'no_cap_nego' : '', - 'local_as' : '300', - 'pfx_list_in' : prefix_list_in, - 'pfx_list_out' : prefix_list_out, + 'remote_as' : '111', + 'graceful_rst_no' : '' + }, + 'foo-bar' : { + 'advertise_map' : route_map_in, + 'description' : 'foo peer bar group', + 'remote_as' : '200', + 'shutdown' : '', + 'no_cap_nego' : '', + 'local_as' : '300', + 'pfx_list_in' : prefix_list_in, + 'pfx_list_out' : prefix_list_out, 'no_send_comm_ext' : '', }, - 'baz' : { - 'cap_dynamic' : '', - 'cap_ext_next' : '', - 'remote_as' : '200', - 'passive' : '', - 'multi_hop' : '5', - 'update_src' : 'lo', - 'route_map_in' : route_map_in, - 'route_map_out': route_map_out, + 'foo-bar_baz' : { + 'advertise_map' : route_map_in, + 'non_exist_map' : route_map_out, + 'bfd_profile' : bfd_profile, + 'cap_dynamic' : '', + 'cap_ext_next' : '', + 'remote_as' : '200', + 'passive' : '', + 'multi_hop' : '5', + 'update_src' : 'lo', + 'route_map_in' : route_map_in, + 'route_map_out' : route_map_out, }, } class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): - def setUp(self): - self.cli_set(['policy', 'route-map', route_map_in, 'rule', '10', 'action', 'permit']) - self.cli_set(['policy', 'route-map', route_map_out, 'rule', '10', 'action', 'permit']) - self.cli_set(['policy', 'prefix-list', prefix_list_in, 'rule', '10', 'action', 'permit']) - self.cli_set(['policy', 'prefix-list', prefix_list_in, 'rule', '10', 'prefix', '192.0.2.0/25']) - self.cli_set(['policy', 'prefix-list', prefix_list_out, 'rule', '10', 'action', 'permit']) - self.cli_set(['policy', 'prefix-list', prefix_list_out, 'rule', '10', 'prefix', '192.0.2.128/25']) - - self.cli_set(['policy', 'prefix-list6', prefix_list_in6, 'rule', '10', 'action', 'permit']) - self.cli_set(['policy', 'prefix-list6', prefix_list_in6, 'rule', '10', 'prefix', '2001:db8:1000::/64']) - self.cli_set(['policy', 'prefix-list6', prefix_list_out6, 'rule', '10', 'action', 'deny']) - self.cli_set(['policy', 'prefix-list6', prefix_list_out6, 'rule', '10', 'prefix', '2001:db8:2000::/64']) + @classmethod + def setUpClass(cls): + super(TestProtocolsBGP, 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, ['policy', 'route-map', route_map_in, 'rule', '10', 'action', 'permit']) + cls.cli_set(cls, ['policy', 'route-map', route_map_out, 'rule', '10', 'action', 'permit']) + cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_in, 'rule', '10', 'action', 'permit']) + cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_in, 'rule', '10', 'prefix', '192.0.2.0/25']) + cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_out, 'rule', '10', 'action', 'permit']) + cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_out, 'rule', '10', 'prefix', '192.0.2.128/25']) + + cls.cli_set(cls, ['policy', 'prefix-list6', prefix_list_in6, 'rule', '10', 'action', 'permit']) + cls.cli_set(cls, ['policy', 'prefix-list6', prefix_list_in6, 'rule', '10', 'prefix', '2001:db8:1000::/64']) + cls.cli_set(cls, ['policy', 'prefix-list6', prefix_list_out6, 'rule', '10', 'action', 'deny']) + cls.cli_set(cls, ['policy', 'prefix-list6', prefix_list_out6, 'rule', '10', 'prefix', '2001:db8:2000::/64']) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['policy']) + def setUp(self): self.cli_set(base_path + ['local-as', ASN]) def tearDown(self): - self.cli_delete(['policy']) self.cli_delete(['vrf']) self.cli_delete(base_path) self.cli_commit() @@ -154,6 +189,11 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): 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: + self.assertIn(f' neighbor {peer} bfd', frrconfig) + if 'bfd_profile' in peer_config: + self.assertIn(f' neighbor {peer} bfd profile {peer_config["bfd_profile"]}', frrconfig) + self.assertIn(f' neighbor {peer} bfd check-control-plane-failure', frrconfig) if 'cap_dynamic' in peer_config: self.assertIn(f' neighbor {peer} capability dynamic', frrconfig) if 'cap_ext_next' in peer_config: @@ -198,7 +238,19 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' neighbor {peer} addpath-tx-all-paths', frrconfig) if 'addpath_per_as' in peer_config: self.assertIn(f' neighbor {peer} addpath-tx-bestpath-per-AS', frrconfig) - + if 'advertise_map' in peer_config: + base = f' neighbor {peer} advertise-map {peer_config["advertise_map"]}' + if 'exist_map' in peer_config: + base = f'{base} exist-map {peer_config["exist_map"]}' + if 'non_exist_map' in peer_config: + base = f'{base} non-exist-map {peer_config["non_exist_map"]}' + self.assertIn(base, frrconfig) + if 'graceful_rst' in peer_config: + self.assertIn(f' neighbor {peer} graceful-restart', frrconfig) + if 'graceful_rst_no' in peer_config: + self.assertIn(f' neighbor {peer} graceful-restart-disable', frrconfig) + if 'graceful_rst_hlp' in peer_config: + self.assertIn(f' neighbor {peer} graceful-restart-helper', frrconfig) def test_bgp_01_simple(self): router_id = '127.0.0.1' @@ -208,6 +260,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): max_path_v4ibgp = '4' max_path_v6 = '8' max_path_v6ibgp = '16' + cond_adv_timer = '30' + min_hold_time = '2' self.cli_set(base_path + ['parameters', 'router-id', router_id]) self.cli_set(base_path + ['parameters', 'log-neighbor-changes']) @@ -229,6 +283,14 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['parameters', 'bestpath', 'bandwidth', 'default-weight-for-missing']) self.cli_set(base_path + ['parameters', 'bestpath', 'compare-routerid']) + self.cli_set(base_path + ['parameters', 'conditional-advertisement', 'timer', cond_adv_timer]) + self.cli_set(base_path + ['parameters', 'fast-convergence']) + self.cli_set(base_path + ['parameters', 'minimum-holdtime', min_hold_time]) + self.cli_set(base_path + ['parameters', 'no-suppress-duplicates']) + self.cli_set(base_path + ['parameters', 'reject-as-sets']) + self.cli_set(base_path + ['parameters', 'shutdown']) + self.cli_set(base_path + ['parameters', 'suppress-fib-pending']) + # AFI maximum path support self.cli_set(base_path + ['address-family', 'ipv4-unicast', 'maximum-paths', 'ebgp', max_path_v4]) self.cli_set(base_path + ['address-family', 'ipv4-unicast', 'maximum-paths', 'ibgp', max_path_v4ibgp]) @@ -244,12 +306,19 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' bgp router-id {router_id}', frrconfig) self.assertIn(f' bgp log-neighbor-changes', frrconfig) self.assertIn(f' bgp default local-preference {local_pref}', frrconfig) + self.assertIn(f' bgp conditional-advertisement timer {cond_adv_timer}', frrconfig) + self.assertIn(f' bgp fast-convergence', frrconfig) self.assertIn(f' bgp graceful-restart stalepath-time {stalepath_time}', frrconfig) self.assertIn(f' bgp graceful-shutdown', frrconfig) self.assertIn(f' bgp bestpath as-path multipath-relax', frrconfig) self.assertIn(f' bgp bestpath bandwidth default-weight-for-missing', frrconfig) self.assertIn(f' bgp bestpath compare-routerid', frrconfig) + self.assertIn(f' bgp minimum-holdtime {min_hold_time}', frrconfig) + self.assertIn(f' bgp reject-as-sets', frrconfig) + self.assertIn(f' bgp shutdown', frrconfig) + self.assertIn(f' bgp suppress-fib-pending', frrconfig) self.assertNotIn(f'bgp ebgp-requires-policy', frrconfig) + self.assertIn(f' no bgp suppress-duplicates', frrconfig) afiv4_config = self.getFRRconfig(' address-family ipv4 unicast') self.assertIn(f' maximum-paths {max_path_v4}', afiv4_config) @@ -263,6 +332,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): def test_bgp_02_neighbors(self): # Test out individual neighbor configuration items, not all of them are # also available to a peer-group! + self.cli_set(base_path + ['parameters', 'deterministic-med']) + for peer, peer_config in neighbor_config.items(): afi = 'ipv4-unicast' if is_ipv6(peer): @@ -270,6 +341,11 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): if 'adv_interv' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'advertisement-interval', peer_config["adv_interv"]]) + if 'bfd' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'bfd']) + if 'bfd_profile' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'bfd', 'profile', peer_config["bfd_profile"]]) + self.cli_set(base_path + ['neighbor', peer, 'bfd', 'check-control-plane-failure']) if 'cap_dynamic' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'capability', 'dynamic']) if 'cap_ext_next' in peer_config: @@ -318,6 +394,26 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'addpath-tx-all']) if 'addpath_per_as' in peer_config: self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'addpath-tx-per-as']) + if 'graceful_rst' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'graceful-restart', 'enable']) + if 'graceful_rst_no' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'graceful-restart', 'disable']) + if 'graceful_rst_hlp' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'graceful-restart', 'restart-helper']) + + # Conditional advertisement + if 'advertise_map' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'conditionally-advertise', 'advertise-map', peer_config["advertise_map"]]) + # Either exist-map or non-exist-map needs to be specified + if 'exist_map' not in peer_config and 'non_exist_map' not in peer_config: + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'conditionally-advertise', 'exist-map', route_map_in]) + + if 'exist_map' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'conditionally-advertise', 'exist-map', peer_config["exist_map"]]) + if 'non_exist_map' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'conditionally-advertise', 'non-exist-map', peer_config["non_exist_map"]]) # commit changes self.cli_commit() @@ -339,6 +435,11 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): def test_bgp_03_peer_groups(self): # Test out individual peer-group configuration items for peer_group, config in peer_group_config.items(): + if 'bfd' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'bfd']) + if 'bfd_profile' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'bfd', 'profile', config["bfd_profile"]]) + self.cli_set(base_path + ['peer-group', peer_group, 'bfd', 'check-control-plane-failure']) if 'cap_dynamic' in config: self.cli_set(base_path + ['peer-group', peer_group, 'capability', 'dynamic']) if 'cap_ext_next' in config: @@ -381,6 +482,31 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'addpath-tx-all']) if 'addpath_per_as' in config: self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'addpath-tx-per-as']) + if 'graceful_rst' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'graceful-restart', 'enable']) + if 'graceful_rst_no' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'graceful-restart', 'disable']) + if 'graceful_rst_hlp' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'graceful-restart', 'restart-helper']) + + # Conditional advertisement + if 'advertise_map' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'conditionally-advertise', 'advertise-map', config["advertise_map"]]) + # Either exist-map or non-exist-map needs to be specified + if 'exist_map' not in config and 'non_exist_map' not in config: + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'conditionally-advertise', 'exist-map', route_map_in]) + + if 'exist_map' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'conditionally-advertise', 'exist-map', config["exist_map"]]) + if 'non_exist_map' in config: + self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'conditionally-advertise', 'non-exist-map', config["non_exist_map"]]) + + for peer, peer_config in neighbor_config.items(): + if 'peer_group' in peer_config: + self.cli_set(base_path + ['neighbor', peer, 'peer-group', peer_config['peer_group']]) + # commit changes self.cli_commit() @@ -393,6 +519,10 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' neighbor {peer_group} peer-group', frrconfig) self.verify_frr_config(peer, peer_config, frrconfig) + for peer, peer_config in neighbor_config.items(): + if 'peer_group' in peer_config: + self.assertIn(f' neighbor {peer} peer-group {peer_config["peer_group"]}', frrconfig) + def test_bgp_04_afi_ipv4(self): networks = { @@ -752,5 +882,44 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' rt vpn import {rt_import}', afi_config) self.assertIn(f' exit-address-family', afi_config) + def test_bgp_14_remote_as_peer_group_override(self): + # Peer-group member cannot override remote-as of peer-group + remote_asn = str(int(ASN) + 150) + neighbor = '192.0.2.1' + peer_group = 'bar' + interface = 'eth0' + + self.cli_set(base_path + ['local-as', ASN]) + self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', remote_asn]) + self.cli_set(base_path + ['neighbor', neighbor, 'peer-group', peer_group]) + self.cli_set(base_path + ['peer-group', peer_group, 'remote-as', remote_asn]) + + # Peer-group member cannot override remote-as of peer-group + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_delete(base_path + ['neighbor', neighbor, 'remote-as']) + + # re-test with interface based peer-group + self.cli_set(base_path + ['neighbor', interface, 'interface', 'peer-group', peer_group]) + self.cli_set(base_path + ['neighbor', interface, 'interface', 'remote-as', 'external']) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_delete(base_path + ['neighbor', interface, 'interface', 'remote-as']) + + # re-test with interface based v6only peer-group + self.cli_set(base_path + ['neighbor', interface, 'interface', 'v6only', 'peer-group', peer_group]) + self.cli_set(base_path + ['neighbor', interface, 'interface', 'v6only', 'remote-as', 'external']) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_delete(base_path + ['neighbor', interface, 'interface', 'v6only', 'remote-as']) + + self.cli_commit() + + frrconfig = self.getFRRconfig(f'router bgp {ASN}') + self.assertIn(f'router bgp {ASN}', frrconfig) + self.assertIn(f' neighbor {neighbor} peer-group {peer_group}', frrconfig) + self.assertIn(f' neighbor {peer_group} peer-group', frrconfig) + self.assertIn(f' neighbor {peer_group} remote-as {remote_asn}', frrconfig) + if __name__ == '__main__': - unittest.main(verbosity=2)
\ No newline at end of file + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py index f4b0a690d..ee4be0b37 100755 --- a/smoketest/scripts/cli/test_protocols_isis.py +++ b/smoketest/scripts/cli/test_protocols_isis.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -33,7 +33,11 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): cls._interfaces = Section.interfaces('ethernet') # call base-classes classmethod - super(cls, cls).setUpClass() + super(TestProtocolsISIS, 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) def tearDown(self): self.cli_delete(base_path) @@ -71,13 +75,13 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify all changes - tmp = self.getFRRconfig(f'router isis {domain}') + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f' net {net}', tmp) self.assertIn(f' log-adjacency-changes', tmp) self.assertIn(f' redistribute ipv4 connected level-2 route-map {route_map}', tmp) for interface in self._interfaces: - tmp = self.getFRRconfig(f'interface {interface}') + tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') self.assertIn(f' ip router isis {domain}', tmp) self.assertIn(f' ipv6 router isis {domain}', tmp) @@ -104,11 +108,11 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR isisd configuration - tmp = self.getFRRconfig(f'router isis {domain}') + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f'router isis {domain}', tmp) self.assertIn(f' net {net}', tmp) - tmp = self.getFRRconfig(f'router isis {domain} vrf {vrf}') + tmp = self.getFRRconfig(f'router isis {domain} vrf {vrf}', daemon='isisd') self.assertIn(f'router isis {domain} vrf {vrf}', tmp) self.assertIn(f' net {net}', tmp) @@ -124,22 +128,26 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.isis_base_config() self.cli_set(base_path + ['redistribute', 'ipv4', 'connected', 'level-2', 'route-map', route_map]) self.cli_set(base_path + ['route-map', route_map]) + self.cli_set(base_path + ['level', 'level-2']) # commit changes self.cli_commit() # Verify FRR configuration zebra_route_map = f'ip protocol isis route-map {route_map}' - frrconfig = self.getFRRconfig(zebra_route_map) + frrconfig = self.getFRRconfig(zebra_route_map, daemon='zebra') self.assertIn(zebra_route_map, frrconfig) + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') + self.assertIn(' is-type level-2-only', tmp) + # Remove the route-map again self.cli_delete(base_path + ['route-map']) # commit changes self.cli_commit() # Verify FRR configuration - frrconfig = self.getFRRconfig(zebra_route_map) + frrconfig = self.getFRRconfig(zebra_route_map, daemon='zebra') self.assertNotIn(zebra_route_map, frrconfig) self.cli_delete(['policy', 'route-map', route_map]) @@ -159,7 +167,7 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify all changes - tmp = self.getFRRconfig(f'router isis {domain}') + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f' net {net}', tmp) for afi in ['ipv4', 'ipv6']: @@ -172,6 +180,8 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): password = 'foo' self.isis_base_config() + for interface in self._interfaces: + self.cli_set(base_path + ['interface', interface, 'password', 'plaintext-password', f'{password}-{interface}']) self.cli_set(base_path + ['area-password', 'plaintext-password', password]) self.cli_set(base_path + ['area-password', 'md5', password]) @@ -192,24 +202,28 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify all changes - tmp = self.getFRRconfig(f'router isis {domain}') + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f' net {net}', tmp) self.assertIn(f' domain-password clear {password}', tmp) self.assertIn(f' area-password clear {password}', tmp) + for interface in self._interfaces: + tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') + self.assertIn(f' isis password clear {password}-{interface}', tmp) - def test_isis_06_spf_delay(self): - self.isis_base_config() - + def test_isis_06_spf_delay_bfd(self): network = 'point-to-point' holddown = '10' init_delay = '50' long_delay = '200' short_delay = '100' time_to_learn = '75' + bfd_profile = 'isis-bfd' + self.cli_set(base_path + ['net', net]) for interface in self._interfaces: self.cli_set(base_path + ['interface', interface, 'network', network]) + self.cli_set(base_path + ['interface', interface, 'bfd', 'profile', bfd_profile]) self.cli_set(base_path + ['spf-delay-ietf', 'holddown', holddown]) # verify() - All types of spf-delay must be configured @@ -226,11 +240,6 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): with self.assertRaises(ConfigSessionError): self.cli_commit() - self.cli_set(base_path + ['spf-delay-ietf', 'long-delay', long_delay]) - # verify() - All types of spf-delay must be configured - with self.assertRaises(ConfigSessionError): - self.cli_commit() - self.cli_set(base_path + ['spf-delay-ietf', 'short-delay', short_delay]) # verify() - All types of spf-delay must be configured with self.assertRaises(ConfigSessionError): @@ -241,15 +250,17 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify all changes - tmp = self.getFRRconfig(f'router isis {domain}') + tmp = self.getFRRconfig(f'router isis {domain}', daemon='isisd') self.assertIn(f' net {net}', tmp) self.assertIn(f' spf-delay-ietf init-delay {init_delay} short-delay {short_delay} long-delay {long_delay} holddown {holddown} time-to-learn {time_to_learn}', tmp) for interface in self._interfaces: - tmp = self.getFRRconfig(f'interface {interface}') + tmp = self.getFRRconfig(f'interface {interface}', daemon='isisd') self.assertIn(f' ip router isis {domain}', tmp) self.assertIn(f' ipv6 router isis {domain}', tmp) self.assertIn(f' isis network {network}', tmp) + self.assertIn(f' isis bfd', tmp) + self.assertIn(f' isis bfd profile {bfd_profile}', tmp) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_mpls.py b/smoketest/scripts/cli/test_protocols_mpls.py new file mode 100755 index 000000000..76e6ca35a --- /dev/null +++ b/smoketest/scripts/cli/test_protocols_mpls.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 base_vyostest_shim import VyOSUnitTestSHIM +from vyos.configsession import ConfigSessionError +from vyos.ifconfig import Section +from vyos.util import process_named_running + +PROCESS_NAME = 'ldpd' +base_path = ['protocols', 'mpls', 'ldp'] + +peers = { + '192.0.2.10' : { + 'intv_rx' : '500', + 'intv_tx' : '600', + 'multihop' : '', + 'source_addr': '192.0.2.254', + }, + '192.0.2.20' : { + 'echo_mode' : '', + 'intv_echo' : '100', + 'intv_mult' : '100', + 'intv_rx' : '222', + 'intv_tx' : '333', + 'passive' : '', + 'shutdown' : '', + }, + '2001:db8::a' : { + 'source_addr': '2001:db8::1', + }, + '2001:db8::b' : { + 'source_addr': '2001:db8::1', + 'multihop' : '', + }, +} + +profiles = { + 'foo' : { + 'echo_mode' : '', + 'intv_echo' : '100', + 'intv_mult' : '101', + 'intv_rx' : '222', + 'intv_tx' : '333', + 'shutdown' : '', + }, + 'bar' : { + 'intv_mult' : '102', + 'intv_rx' : '444', + 'passive' : '', + }, +} + +class TestProtocolsMPLS(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestProtocolsMPLS, 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) + + def tearDown(self): + self.cli_delete(base_path) + self.cli_commit() + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + + def test_mpls_basic(self): + router_id = '1.2.3.4' + transport_ipv4_addr = '5.6.7.8' + interfaces = Section.interfaces('ethernet') + + self.cli_set(base_path + ['router-id', router_id]) + + # At least one LDP interface must be configured + with self.assertRaises(ConfigSessionError): + self.cli_commit() + for interface in interfaces: + self.cli_set(base_path + ['interface', interface]) + + # LDP transport address missing + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(base_path + ['discovery', 'transport-ipv4-address', transport_ipv4_addr]) + + # Commit changes + self.cli_commit() + + # Validate configuration + frrconfig = self.getFRRconfig('mpls ldp', daemon=PROCESS_NAME) + self.assertIn(f'mpls ldp', frrconfig) + self.assertIn(f' router-id {router_id}', frrconfig) + + # Validate AFI IPv4 + afiv4_config = self.getFRRconfig(' address-family ipv4', daemon=PROCESS_NAME) + self.assertIn(f' discovery transport-address {transport_ipv4_addr}', afiv4_config) + for interface in interfaces: + self.assertIn(f' interface {interface}', afiv4_config) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_nhrp.py b/smoketest/scripts/cli/test_protocols_nhrp.py index aa0ac268d..40b19fec7 100755 --- a/smoketest/scripts/cli/test_protocols_nhrp.py +++ b/smoketest/scripts/cli/test_protocols_nhrp.py @@ -18,6 +18,7 @@ import unittest from base_vyostest_shim import VyOSUnitTestSHIM +from vyos.firewall import find_nftables_rule from vyos.util import call, process_named_running, read_file tunnel_path = ['interfaces', 'tunnel'] @@ -91,6 +92,14 @@ class TestProtocolsNHRP(VyOSUnitTestSHIM.TestCase): for line in opennhrp_lines: self.assertIn(line, tmp_opennhrp_conf) + firewall_matches = [ + 'ip protocol gre', + 'ip saddr 192.0.2.1', + 'ip daddr 224.0.0.0/4', + 'comment "VYOS_NHRP_tun100"' + ] + + self.assertTrue(find_nftables_rule('ip filter', 'VYOS_FW_OUTPUT', firewall_matches) is not None) self.assertTrue(process_named_running('opennhrp')) if __name__ == '__main__': diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index 0529eefbd..e15ea478b 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -33,14 +33,25 @@ route_map = 'foo-bar-baz10' log = logging.getLogger('TestProtocolsOSPF') class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): - def setUp(self): - self.cli_set(['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) - self.cli_set(['policy', 'route-map', route_map, 'rule', '20', 'action', 'permit']) + @classmethod + def setUpClass(cls): + super(TestProtocolsOSPF, cls).setUpClass() + + cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) + cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '20', 'action', 'permit']) + + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + cls.cli_delete(cls, base_path) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['policy', 'route-map', route_map]) + super(TestProtocolsOSPF, cls).tearDownClass() def tearDown(self): # Check for running process self.assertTrue(process_named_running(PROCESS_NAME)) - self.cli_delete(['policy', 'route-map', route_map]) self.cli_delete(base_path) self.cli_commit() @@ -189,31 +200,7 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): for neighbor in neighbors: self.assertIn(f' neighbor {neighbor} priority {priority} poll-interval {poll_interval}', frrconfig) # default - - def test_ospf_07_passive_interface(self): - self.cli_set(base_path + ['passive-interface', 'default']) - interfaces = Section.interfaces('ethernet') - for interface in interfaces: - self.cli_set(base_path + ['passive-interface-exclude', interface]) - - # commit changes - self.cli_commit() - - # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf') - try: - self.assertIn(f'router ospf', frrconfig) - self.assertIn(f' passive-interface default', frrconfig) # default - for interface in interfaces: - self.assertIn(f' no passive-interface {interface}', frrconfig) # default - except: - log.debug(frrconfig) - log.debug(cmd('sudo dmesg')) - log.debug(cmd('sudo cat /var/log/messages')) - log.debug(cmd('vtysh -c "show run"')) - self.fail('Now we can hopefully see why OSPF fails!') - - def test_ospf_08_redistribute(self): + def test_ospf_07_redistribute(self): metric = '15' metric_type = '1' redistribute = ['bgp', 'connected', 'isis', 'kernel', 'rip', 'static'] @@ -223,9 +210,15 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['redistribute', protocol, 'route-map', route_map]) self.cli_set(base_path + ['redistribute', protocol, 'metric-type', metric_type]) + # enable FRR debugging to find the root cause of failing testcases + cmd('touch /tmp/vyos.frr.debug') + # commit changes self.cli_commit() + # disable FRR debugging + cmd('rm -f /tmp/vyos.frr.debug') + # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') try: @@ -234,11 +227,10 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.assertIn(f' redistribute {protocol} metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) except: log.debug(frrconfig) - log.debug(cmd('sudo cat /var/log/messages')) - log.debug(cmd('vtysh -c "show run"')) + log.debug(cmd('sudo cat /tmp/vyos-configd-script-stdout')) self.fail('Now we can hopefully see why OSPF fails!') - def test_ospf_09_virtual_link(self): + def test_ospf_08_virtual_link(self): networks = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'] area = '10' shortcut = 'enable' @@ -268,22 +260,26 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.assertIn(f' network {network} area {area}', frrconfig) - def test_ospf_10_interface_configuration(self): + def test_ospf_09_interface_configuration(self): interfaces = Section.interfaces('ethernet') password = 'vyos1234' bandwidth = '10000' cost = '150' network = 'point-to-point' priority = '200' + bfd_profile = 'vyos-test' + self.cli_set(base_path + ['passive-interface', 'default']) for interface in interfaces: - self.cli_set(base_path + ['interface', interface, 'authentication', 'plaintext-password', password]) - self.cli_set(base_path + ['interface', interface, 'bandwidth', bandwidth]) - self.cli_set(base_path + ['interface', interface, 'bfd']) - self.cli_set(base_path + ['interface', interface, 'cost', cost]) - self.cli_set(base_path + ['interface', interface, 'mtu-ignore']) - self.cli_set(base_path + ['interface', interface, 'network', network]) - self.cli_set(base_path + ['interface', interface, 'priority', priority]) + base_interface = base_path + ['interface', interface] + self.cli_set(base_interface + ['authentication', 'plaintext-password', password]) + self.cli_set(base_interface + ['bandwidth', bandwidth]) + self.cli_set(base_interface + ['bfd', 'profile', bfd_profile]) + self.cli_set(base_interface + ['cost', cost]) + self.cli_set(base_interface + ['mtu-ignore']) + self.cli_set(base_interface + ['network', network]) + self.cli_set(base_interface + ['priority', priority]) + self.cli_set(base_interface + ['passive', 'disable']) # commit changes self.cli_commit() @@ -293,45 +289,15 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.assertIn(f'interface {interface}', config) self.assertIn(f' ip ospf authentication-key {password}', config) self.assertIn(f' ip ospf bfd', config) + self.assertIn(f' ip ospf bfd profile {bfd_profile}', config) self.assertIn(f' ip ospf cost {cost}', config) self.assertIn(f' ip ospf mtu-ignore', config) self.assertIn(f' ip ospf network {network}', config) self.assertIn(f' ip ospf priority {priority}', config) + self.assertIn(f' no ip ospf passive', config) self.assertIn(f' bandwidth {bandwidth}', config) - - def test_ospf_11_vrfs(self): - # It is safe to assume that when the basic VRF test works, all - # other OSPF related features work, as we entirely inherit the CLI - # templates and Jinja2 FRR template. - table = '1000' - vrf = 'blue' - vrf_base = ['vrf', 'name', vrf] - vrf_iface = 'eth1' - self.cli_set(vrf_base + ['table', table]) - self.cli_set(vrf_base + ['protocols', 'ospf', 'interface', vrf_iface]) - self.cli_set(['interfaces', 'ethernet', vrf_iface, 'vrf', vrf]) - - # Also set a default VRF OSPF config - self.cli_set(base_path) - self.cli_commit() - - # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf') - self.assertIn(f'router ospf', frrconfig) - self.assertIn(f' auto-cost reference-bandwidth 100', frrconfig) - self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults - - frrconfig = self.getFRRconfig(f'router ospf vrf {vrf}') - self.assertIn(f'router ospf vrf {vrf}', frrconfig) - self.assertIn(f' auto-cost reference-bandwidth 100', frrconfig) - self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults - - self.cli_delete(['vrf', 'name', vrf]) - self.cli_delete(['interfaces', 'ethernet', vrf_iface, 'vrf']) - - - def test_ospf_12_zebra_route_map(self): + def test_ospf_10_zebra_route_map(self): # Implemented because of T3328 self.cli_set(base_path + ['route-map', route_map]) # commit changes @@ -351,7 +317,7 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): frrconfig = self.getFRRconfig(zebra_route_map) self.assertNotIn(zebra_route_map, frrconfig) - def test_ospf_13_interface_area(self): + def test_ospf_11_interface_area(self): area = '0' interfaces = Section.interfaces('ethernet') @@ -375,6 +341,61 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): self.assertIn(f'interface {interface}', config) self.assertIn(f' ip ospf area {area}', config) + def test_ospf_12_vrfs(self): + # It is safe to assume that when the basic VRF test works, all + # other OSPF related features work, as we entirely inherit the CLI + # templates and Jinja2 FRR template. + table = '1000' + vrf = 'blue' + vrf_base = ['vrf', 'name', vrf] + vrf_iface = 'eth1' + self.cli_set(vrf_base + ['table', table]) + self.cli_set(vrf_base + ['protocols', 'ospf', 'interface', vrf_iface]) + self.cli_set(['interfaces', 'ethernet', vrf_iface, 'vrf', vrf]) + + # Also set a default VRF OSPF config + self.cli_set(base_path) + self.cli_commit() + + # Verify FRR ospfd configuration + frrconfig = self.getFRRconfig('router ospf') + self.assertIn(f'router ospf', frrconfig) + self.assertIn(f' auto-cost reference-bandwidth 100', frrconfig) + self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults + + frrconfig = self.getFRRconfig(f'router ospf vrf {vrf}') + self.assertIn(f'router ospf vrf {vrf}', frrconfig) + self.assertIn(f' auto-cost reference-bandwidth 100', frrconfig) + self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults + + # cleanup + self.cli_delete(['vrf', 'name', vrf]) + self.cli_delete(['interfaces', 'ethernet', vrf_iface, 'vrf']) + + def test_ospf_13_export_list(self): + # Verify explort-list works on ospf-area + acl = '100' + seq = '10' + area = '0.0.0.10' + network = '10.0.0.0/8' + + + self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'action', 'permit']) + self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'source', 'any']) + self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'destination', 'any']) + self.cli_set(base_path + ['area', area, 'network', network]) + self.cli_set(base_path + ['area', area, 'export-list', acl]) + + # commit changes + self.cli_commit() + + # Verify FRR ospfd configuration + frrconfig = self.getFRRconfig('router ospf') + self.assertIn(f'router ospf', frrconfig) + self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # default + self.assertIn(f' network {network} area {area}', frrconfig) + self.assertIn(f' area {area} export-list {acl}', frrconfig) + if __name__ == '__main__': logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_ospfv3.py b/smoketest/scripts/cli/test_protocols_ospfv3.py index c0673629e..fa80ad555 100755 --- a/smoketest/scripts/cli/test_protocols_ospfv3.py +++ b/smoketest/scripts/cli/test_protocols_ospfv3.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -18,16 +18,35 @@ import unittest from base_vyostest_shim import VyOSUnitTestSHIM +from vyos.configsession import ConfigSessionError from vyos.ifconfig import Section from vyos.util import process_named_running PROCESS_NAME = 'ospf6d' base_path = ['protocols', 'ospfv3'] +route_map = 'foo-bar-baz-0815' + router_id = '192.0.2.1' default_area = '0' class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestProtocolsOSPFv3, cls).setUpClass() + + cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) + cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '20', 'action', 'permit']) + + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + cls.cli_delete(cls, base_path) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['policy', 'route-map', route_map]) + super(TestProtocolsOSPFv3, cls).tearDownClass() + def tearDown(self): # Check for running process self.assertTrue(process_named_running(PROCESS_NAME)) @@ -49,13 +68,13 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): interfaces = Section.interfaces('ethernet') for interface in interfaces: - self.cli_set(base_path + ['area', default_area, 'interface', interface]) + self.cli_set(base_path + ['interface', interface, 'area', default_area]) # commit changes self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) self.assertIn(f' area {default_area} range {prefix}', frrconfig) self.assertIn(f' ospf6 router-id {router_id}', frrconfig) @@ -63,7 +82,8 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.assertIn(f' area {default_area} export-list {acl_name}', frrconfig) for interface in interfaces: - self.assertIn(f' interface {interface} area {default_area}', frrconfig) + if_config = self.getFRRconfig(f'interface {interface}', daemon='ospf6d') + self.assertIn(f'ipv6 ospf6 area {default_area}', if_config) self.cli_delete(['policy', 'access-list6', acl_name]) @@ -83,7 +103,7 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) self.assertIn(f' distance {dist_global}', frrconfig) self.assertIn(f' distance ospf6 intra-area {dist_intra_area} inter-area {dist_inter_area} external {dist_external}', frrconfig) @@ -103,12 +123,14 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) for protocol in redistribute: self.assertIn(f' redistribute {protocol} route-map {route_map}', frrconfig) + def test_ospfv3_04_interfaces(self): + bfd_profile = 'vyos-ipv6' self.cli_set(base_path + ['parameters', 'router-id', router_id]) self.cli_set(base_path + ['area', default_area]) @@ -118,7 +140,7 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): interfaces = Section.interfaces('ethernet') for interface in interfaces: if_base = base_path + ['interface', interface] - self.cli_set(if_base + ['bfd']) + self.cli_set(if_base + ['bfd', 'profile', bfd_profile]) self.cli_set(if_base + ['cost', cost]) self.cli_set(if_base + ['instance-id', '0']) self.cli_set(if_base + ['mtu-ignore']) @@ -132,15 +154,16 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) cost = '100' priority = '10' for interface in interfaces: - if_config = self.getFRRconfig(f'interface {interface}') + if_config = self.getFRRconfig(f'interface {interface}', daemon='ospf6d') self.assertIn(f'interface {interface}', if_config) self.assertIn(f' ipv6 ospf6 bfd', if_config) + self.assertIn(f' ipv6 ospf6 bfd profile {bfd_profile}', if_config) self.assertIn(f' ipv6 ospf6 cost {cost}', if_config) self.assertIn(f' ipv6 ospf6 mtu-ignore', if_config) self.assertIn(f' ipv6 ospf6 network point-to-point', if_config) @@ -161,10 +184,102 @@ class TestProtocolsOSPFv3(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify FRR ospfd configuration - frrconfig = self.getFRRconfig('router ospf6') + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') self.assertIn(f'router ospf6', frrconfig) self.assertIn(f' area {area_stub} stub', frrconfig) self.assertIn(f' area {area_stub_nosum} stub no-summary', frrconfig) + + def test_ospfv3_06_area_nssa(self): + area_nssa = '1.1.1.1' + area_nssa_nosum = '2.2.2.2' + area_nssa_default = '3.3.3.3' + + self.cli_set(base_path + ['area', area_nssa, 'area-type', 'nssa']) + self.cli_set(base_path + ['area', area_nssa, 'area-type', 'stub']) + # can only set one area-type per OSPFv3 area + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_delete(base_path + ['area', area_nssa, 'area-type', 'stub']) + + self.cli_set(base_path + ['area', area_nssa_nosum, 'area-type', 'nssa', 'no-summary']) + self.cli_set(base_path + ['area', area_nssa_nosum, 'area-type', 'nssa', 'default-information-originate']) + self.cli_set(base_path + ['area', area_nssa_default, 'area-type', 'nssa', 'default-information-originate']) + + # commit changes + self.cli_commit() + + # Verify FRR ospfd configuration + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') + self.assertIn(f'router ospf6', frrconfig) + self.assertIn(f' area {area_nssa} nssa', frrconfig) + self.assertIn(f' area {area_nssa_nosum} nssa default-information-originate no-summary', frrconfig) + self.assertIn(f' area {area_nssa_default} nssa default-information-originate', frrconfig) + + + def test_ospfv3_07_default_originate(self): + seq = '100' + metric = '50' + metric_type = '1' + + self.cli_set(base_path + ['default-information', 'originate', 'metric', metric]) + self.cli_set(base_path + ['default-information', 'originate', 'metric-type', metric_type]) + self.cli_set(base_path + ['default-information', 'originate', 'route-map', route_map]) + + # commit changes + self.cli_commit() + + # Verify FRR ospfd configuration + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') + self.assertIn(f'router ospf6', frrconfig) + self.assertIn(f' default-information originate metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) + + # Now set 'always' + self.cli_set(base_path + ['default-information', 'originate', 'always']) + self.cli_commit() + + # Verify FRR ospfd configuration + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') + self.assertIn(f' default-information originate always metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) + + + def test_ospfv3_08_vrfs(self): + # It is safe to assume that when the basic VRF test works, all + # other OSPF related features work, as we entirely inherit the CLI + # templates and Jinja2 FRR template. + table = '1000' + vrf = 'blue' + vrf_base = ['vrf', 'name', vrf] + vrf_iface = 'eth1' + router_id = '1.2.3.4' + router_id_vrf = '1.2.3.5' + + self.cli_set(vrf_base + ['table', table]) + self.cli_set(vrf_base + ['protocols', 'ospfv3', 'interface', vrf_iface, 'bfd']) + self.cli_set(vrf_base + ['protocols', 'ospfv3', 'parameters', 'router-id', router_id_vrf]) + + self.cli_set(['interfaces', 'ethernet', vrf_iface, 'vrf', vrf]) + + # Also set a default VRF OSPF config + self.cli_set(base_path + ['parameters', 'router-id', router_id]) + self.cli_commit() + + # Verify FRR ospfd configuration + frrconfig = self.getFRRconfig('router ospf6', daemon='ospf6d') + self.assertIn(f'router ospf6', frrconfig) + self.assertIn(f' ospf6 router-id {router_id}', frrconfig) + + frrconfig = self.getFRRconfig(f'interface {vrf_iface}', daemon='ospf6d') + self.assertIn(f'interface {vrf_iface}', frrconfig) + self.assertIn(f' ipv6 ospf6 bfd', frrconfig) + + frrconfig = self.getFRRconfig(f'router ospf6 vrf {vrf}', daemon='ospf6d') + self.assertIn(f'router ospf6 vrf {vrf}', frrconfig) + self.assertIn(f' ospf6 router-id {router_id_vrf}', frrconfig) + + # cleanup + self.cli_delete(['vrf', 'name', vrf]) + self.cli_delete(['interfaces', 'ethernet', vrf_iface, 'vrf']) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_ripng.py b/smoketest/scripts/cli/test_protocols_ripng.py index 40585e778..53336a533 100755 --- a/smoketest/scripts/cli/test_protocols_ripng.py +++ b/smoketest/scripts/cli/test_protocols_ripng.py @@ -54,7 +54,7 @@ class TestProtocolsRIPng(VyOSUnitTestSHIM.TestCase): # Check for running process self.assertTrue(process_named_running(PROCESS_NAME)) - def test_ripng(self): + def test_ripng_01_parameters(self): metric = '8' interfaces = Section.interfaces('ethernet') aggregates = ['2001:db8:1000::/48', '2001:db8:2000::/48', '2001:db8:3000::/48'] @@ -121,5 +121,25 @@ class TestProtocolsRIPng(VyOSUnitTestSHIM.TestCase): proto = 'ospf6' self.assertIn(f' redistribute {proto} metric {metric} route-map {route_map}', frrconfig) + def test_ripng_02_zebra_route_map(self): + # Implemented because of T3328 + self.cli_set(base_path + ['route-map', route_map]) + # commit changes + self.cli_commit() + + # Verify FRR configuration + zebra_route_map = f'ipv6 protocol ripng route-map {route_map}' + frrconfig = self.getFRRconfig(zebra_route_map) + self.assertIn(zebra_route_map, frrconfig) + + # Remove the route-map again + self.cli_delete(base_path + ['route-map']) + # commit changes + self.cli_commit() + + # Verify FRR configuration + frrconfig = self.getFRRconfig(zebra_route_map) + self.assertNotIn(zebra_route_map, frrconfig) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_rpki.py b/smoketest/scripts/cli/test_protocols_rpki.py index d9792ce8d..e5e45565b 100755 --- a/smoketest/scripts/cli/test_protocols_rpki.py +++ b/smoketest/scripts/cli/test_protocols_rpki.py @@ -36,8 +36,6 @@ class TestProtocolsRPKI(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Nothing RPKI specific should be left over in the config - # - # Disabled until T3266 is resolved # frrconfig = self.getFRRconfig('rpki') # self.assertNotIn('rpki', frrconfig) diff --git a/smoketest/scripts/cli/test_protocols_static.py b/smoketest/scripts/cli/test_protocols_static.py index 4c4eb5a7c..19efe7786 100755 --- a/smoketest/scripts/cli/test_protocols_static.py +++ b/smoketest/scripts/cli/test_protocols_static.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -52,9 +52,16 @@ routes = { }, 'blackhole' : { 'distance' : '90' }, }, - '100.64.0.0/10' : { + '100.64.0.0/16' : { 'blackhole' : { }, }, + '100.65.0.0/16' : { + 'reject' : { 'distance' : '10', 'tag' : '200' }, + }, + '100.66.0.0/16' : { + 'blackhole' : { }, + 'reject' : { 'distance' : '10', 'tag' : '200' }, + }, '2001:db8:100::/40' : { 'next_hop' : { '2001:db8::1' : { 'distance' : '10' }, @@ -74,6 +81,9 @@ routes = { }, 'blackhole' : { 'distance' : '250', 'tag' : '500' }, }, + '2001:db8:300::/40' : { + 'reject' : { 'distance' : '250', 'tag' : '500' }, + }, '2001:db8::/32' : { 'blackhole' : { 'distance' : '200', 'tag' : '600' }, }, @@ -82,9 +92,15 @@ routes = { tables = ['80', '81', '82'] class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase): - def setUp(self): - # This is our "target" VRF when leaking routes: - self.cli_set(['vrf', 'name', 'black', 'table', '43210']) + @classmethod + def setUpClass(cls): + super(TestProtocolsStatic, cls).setUpClass() + cls.cli_set(cls, ['vrf', 'name', 'black', 'table', '43210']) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['vrf']) + super(TestProtocolsStatic, cls).tearDownClass() def tearDown(self): for route, route_config in routes.items(): @@ -135,6 +151,20 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase): if 'tag' in route_config['blackhole']: self.cli_set(base + ['blackhole', 'tag', route_config['blackhole']['tag']]) + if 'reject' in route_config: + self.cli_set(base + ['reject']) + if 'distance' in route_config['reject']: + self.cli_set(base + ['reject', 'distance', route_config['reject']['distance']]) + if 'tag' in route_config['reject']: + self.cli_set(base + ['reject', 'tag', route_config['reject']['tag']]) + + if {'blackhole', 'reject'} <= set(route_config): + # Can not use blackhole and reject at the same time + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_delete(base + ['blackhole']) + self.cli_delete(base + ['reject']) + # commit changes self.cli_commit() @@ -177,6 +207,11 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase): else: self.assertIn(tmp, frrconfig) + if {'blackhole', 'reject'} <= set(route_config): + # Can not use blackhole and reject at the same time + # Config error validated above - skip this route + continue + if 'blackhole' in route_config: tmp = f'{ip_ipv6} route {route} blackhole' if 'tag' in route_config['blackhole']: @@ -186,6 +221,15 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase): self.assertIn(tmp, frrconfig) + if 'reject' in route_config: + tmp = f'{ip_ipv6} route {route} reject' + if 'tag' in route_config['reject']: + tmp += ' tag ' + route_config['reject']['tag'] + if 'distance' in route_config['reject']: + tmp += ' ' + route_config['reject']['distance'] + + self.assertIn(tmp, frrconfig) + def test_02_static_table(self): for table in tables: for route, route_config in routes.items(): @@ -389,11 +433,8 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase): self.assertIn(tmp, frrconfig) - self.cli_delete(['vrf']) - def test_04_static_zebra_route_map(self): # Implemented because of T3328 - self.debug = True route_map = 'foo-static-in' self.cli_set(['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) diff --git a/smoketest/scripts/cli/test_protocols_static_arp.py b/smoketest/scripts/cli/test_protocols_static_arp.py new file mode 100755 index 000000000..b61d8f854 --- /dev/null +++ b/smoketest/scripts/cli/test_protocols_static_arp.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 json +import unittest + +from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.util import cmd + +base_path = ['protocols', 'static', 'arp'] +interface = 'eth0' +address = '192.0.2.1/24' + +class TestARP(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestARP, 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) + + # we need a L2 interface with a L3 address to properly configure ARP entries + cls.cli_set(cls, ['interfaces', 'ethernet', interface, 'address', address]) + + @classmethod + def tearDownClass(cls): + # cleanuop L2 interface + cls.cli_delete(cls, ['interfaces', 'ethernet', interface, 'address', address]) + cls.cli_commit(cls) + + super(TestARP, cls).tearDownClass() + + def tearDown(self): + # delete test config + self.cli_delete(base_path) + self.cli_commit() + + def test_static_arp(self): + test_data = { + '192.0.2.10' : { 'mac' : '00:01:02:03:04:0a' }, + '192.0.2.11' : { 'mac' : '00:01:02:03:04:0b' }, + '192.0.2.12' : { 'mac' : '00:01:02:03:04:0c' }, + '192.0.2.13' : { 'mac' : '00:01:02:03:04:0d' }, + '192.0.2.14' : { 'mac' : '00:01:02:03:04:0e' }, + '192.0.2.15' : { 'mac' : '00:01:02:03:04:0f' }, + } + + for host, host_config in test_data.items(): + self.cli_set(base_path + ['interface', interface, 'address', host, 'mac', host_config['mac']]) + + self.cli_commit() + + arp_table = json.loads(cmd('ip -j -4 neigh show')) + for host, host_config in test_data.items(): + # As we search within a list of hosts we need to mark if it was + # found or not. This ensures all hosts from test_data are processed + found = False + for entry in arp_table: + # Other ARP entry - not related to this testcase + if entry['dst'] not in list(test_data): + continue + + if entry['dst'] == host: + self.assertEqual(entry['lladdr'], host_config['mac']) + self.assertEqual(entry['dev'], interface) + found = True + + if found == False: + print(entry) + self.assertTrue(found) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py index 14666db15..9c9d6d9f1 100755 --- a/smoketest/scripts/cli/test_service_dhcp-server.py +++ b/smoketest/scripts/cli/test_service_dhcp-server.py @@ -38,7 +38,7 @@ domain_name = 'vyos.net' class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): @classmethod def setUpClass(cls): - super(cls, cls).setUpClass() + super(TestServiceDHCPServer, cls).setUpClass() cidr_mask = subnet.split('/')[-1] cls.cli_set(cls, ['interfaces', 'dummy', 'dum8765', 'address', f'{router}/{cidr_mask}']) @@ -46,7 +46,7 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): @classmethod def tearDownClass(cls): cls.cli_delete(cls, ['interfaces', 'dummy', 'dum8765']) - super(cls, cls).tearDownClass() + super(TestServiceDHCPServer, cls).tearDownClass() def tearDown(self): self.cli_delete(base_path) @@ -461,12 +461,11 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): self.assertIn(f'mclt 1800;', config) self.assertIn(f'mclt 1800;', config) self.assertIn(f'split 128;', config) - self.assertIn(f'port 520;', config) - self.assertIn(f'peer port 520;', config) + self.assertIn(f'port 647;', config) + self.assertIn(f'peer port 647;', config) self.assertIn(f'max-response-delay 30;', config) self.assertIn(f'max-unacked-updates 10;', config) self.assertIn(f'load balance max seconds 3;', config) - self.assertIn(f'peer port 520;', config) self.assertIn(f'address {failover_local};', config) self.assertIn(f'peer address {failover_remote};', config) diff --git a/smoketest/scripts/cli/test_service_dhcpv6-server.py b/smoketest/scripts/cli/test_service_dhcpv6-server.py index 7177f1505..f83453323 100755 --- a/smoketest/scripts/cli/test_service_dhcpv6-server.py +++ b/smoketest/scripts/cli/test_service_dhcpv6-server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -32,16 +32,24 @@ dns_1 = '2001:db8::1' dns_2 = '2001:db8::2' domain = 'vyos.net' nis_servers = ['2001:db8:ffff::1', '2001:db8:ffff::2'] -interface = 'eth1' +interface = 'eth0' interface_addr = inc_ip(subnet, 1) + '/64' -class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): - def setUp(self): - self.cli_set(['interfaces', 'ethernet', interface, 'address', interface_addr]) +class TestServiceDHCPv6Server(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestServiceDHCPv6Server, cls).setUpClass() + cls.cli_set(cls, ['interfaces', 'ethernet', interface, 'address', interface_addr]) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['interfaces', 'ethernet', interface, 'address', interface_addr]) + cls.cli_commit(cls) + + super(TestServiceDHCPv6Server, cls).tearDownClass() def tearDown(self): self.cli_delete(base_path) - self.cli_delete(['interfaces', 'ethernet', interface, 'address', interface_addr]) self.cli_commit() def test_single_pool(self): diff --git a/smoketest/scripts/cli/test_service_https.py b/smoketest/scripts/cli/test_service_https.py index 8e69efd9c..71fb3e177 100755 --- a/smoketest/scripts/cli/test_service_https.py +++ b/smoketest/scripts/cli/test_service_https.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 @@ -16,14 +16,37 @@ import unittest +from requests import request +from urllib3.exceptions import InsecureRequestWarning + from base_vyostest_shim import VyOSUnitTestSHIM +from base_vyostest_shim import ignore_warning +from vyos.util import read_file from vyos.util import run base_path = ['service', 'https'] - pki_base = ['pki'] -cert_data = 'MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIwWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIxMDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu+JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3LftzngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93+dm/LDnp7C0=' -key_data = 'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww' + +cert_data = """ +MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIw +WTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNv +bWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIx +MDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNV +BAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlP +UzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3 +QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu ++JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3Lftz +ngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93 ++dm/LDnp7C0= +""" + +key_data = """ +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx +2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7 +u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww +""" class TestHTTPSService(VyOSUnitTestSHIM.TestCase): def setUp(self): @@ -61,9 +84,13 @@ class TestHTTPSService(VyOSUnitTestSHIM.TestCase): ret = run('sudo /usr/sbin/nginx -t') self.assertEqual(ret, 0) + nginx_config = read_file('/etc/nginx/sites-enabled/default') + self.assertIn(f'listen {address}:{port} ssl;', nginx_config) + self.assertIn(f'ssl_protocols TLSv1.2 TLSv1.3;', nginx_config) + def test_certificate(self): - self.cli_set(pki_base + ['certificate', 'test_https', 'certificate', cert_data]) - self.cli_set(pki_base + ['certificate', 'test_https', 'private', 'key', key_data]) + self.cli_set(pki_base + ['certificate', 'test_https', 'certificate', cert_data.replace('\n','')]) + self.cli_set(pki_base + ['certificate', 'test_https', 'private', 'key', key_data.replace('\n','')]) self.cli_set(base_path + ['certificates', 'certificate', 'test_https']) @@ -72,5 +99,44 @@ class TestHTTPSService(VyOSUnitTestSHIM.TestCase): ret = run('sudo /usr/sbin/nginx -t') self.assertEqual(ret, 0) + @ignore_warning(InsecureRequestWarning) + def test_api_auth(self): + vhost_id = 'example' + address = '127.0.0.1' + port = '443' + name = 'localhost' + + self.cli_set(base_path + ['api', 'socket']) + key = 'MySuperSecretVyOS' + self.cli_set(base_path + ['api', 'keys', 'id', 'key-01', 'key', key]) + + test_path = base_path + ['virtual-host', vhost_id] + self.cli_set(test_path + ['listen-address', address]) + self.cli_set(test_path + ['listen-port', port]) + self.cli_set(test_path + ['server-name', name]) + + self.cli_commit() + + nginx_config = read_file('/etc/nginx/sites-enabled/default') + self.assertIn(f'listen {address}:{port} ssl;', nginx_config) + self.assertIn(f'ssl_protocols TLSv1.2 TLSv1.3;', nginx_config) + + url = f'https://{address}/retrieve' + payload = {'data': '{"op": "showConfig", "path": []}', 'key': f'{key}'} + headers = {} + r = request('POST', url, verify=False, headers=headers, data=payload) + # Must get HTTP code 200 on success + self.assertEqual(r.status_code, 200) + + payload_invalid = {'data': '{"op": "showConfig", "path": []}', 'key': 'invalid'} + r = request('POST', url, verify=False, headers=headers, data=payload_invalid) + # Must get HTTP code 401 on invalid key (Unauthorized) + self.assertEqual(r.status_code, 401) + + payload_no_key = {'data': '{"op": "showConfig", "path": []}'} + r = request('POST', url, verify=False, headers=headers, data=payload_no_key) + # Must get HTTP code 401 on missing key (Unauthorized) + self.assertEqual(r.status_code, 401) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_ids.py b/smoketest/scripts/cli/test_service_ids.py new file mode 100755 index 000000000..18f1b8ec5 --- /dev/null +++ b/smoketest/scripts/cli/test_service_ids.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import unittest + +from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.configsession import ConfigSessionError +from vyos.util import process_named_running +from vyos.util import read_file + +PROCESS_NAME = 'fastnetmon' +FASTNETMON_CONF = '/etc/fastnetmon.conf' +base_path = ['service', 'ids', 'ddos-protection'] + +class TestServiceIDS(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestServiceIDS, 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) + + def tearDown(self): + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + + # delete test config + self.cli_delete(base_path) + self.cli_commit() + + self.assertFalse(os.path.exists(FASTNETMON_CONF)) + self.assertFalse(process_named_running(PROCESS_NAME)) + + def test_fastnetmon(self): + networks = ['10.0.0.0/24', '10.5.5.0/24'] + interfaces = ['eth0', 'eth1'] + fps = '3500' + mbps = '300' + pps = '60000' + + self.cli_set(base_path + ['mode', 'mirror']) + # Required network! + with self.assertRaises(ConfigSessionError): + self.cli_commit() + for tmp in networks: + self.cli_set(base_path + ['network', tmp]) + + # Required interface(s)! + with self.assertRaises(ConfigSessionError): + self.cli_commit() + for tmp in interfaces: + self.cli_set(base_path + ['listen-interface', tmp]) + + self.cli_set(base_path + ['direction', 'in']) + self.cli_set(base_path + ['threshold', 'fps', fps]) + self.cli_set(base_path + ['threshold', 'pps', pps]) + self.cli_set(base_path + ['threshold', 'mbps', mbps]) + + # commit changes + self.cli_commit() + + # Check configured port + config = read_file(FASTNETMON_CONF) + self.assertIn(f'mirror_afpacket = on', config) + self.assertIn(f'process_incoming_traffic = on', config) + self.assertIn(f'process_outgoing_traffic = off', config) + self.assertIn(f'ban_for_flows = on', config) + self.assertIn(f'threshold_flows = {fps}', config) + self.assertIn(f'ban_for_bandwidth = on', config) + self.assertIn(f'threshold_mbps = {mbps}', config) + self.assertIn(f'ban_for_pps = on', config) + self.assertIn(f'threshold_pps = {pps}', config) + + tmp = ','.join(interfaces) + self.assertIn(f'interfaces = {tmp}', config) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_lldp.py b/smoketest/scripts/cli/test_service_lldp.py new file mode 100755 index 000000000..439c96c33 --- /dev/null +++ b/smoketest/scripts/cli/test_service_lldp.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 re +import os +import unittest + +from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.configsession import ConfigSessionError +from vyos.ifconfig import Section +from vyos.util import cmd +from vyos.util import process_named_running +from vyos.util import read_file +from vyos.version import get_version_data + +PROCESS_NAME = 'lldpd' +LLDPD_CONF = '/etc/lldpd.d/01-vyos.conf' +base_path = ['service', 'lldp'] +mgmt_if = 'dum83513' +mgmt_addr = ['1.2.3.4', '1.2.3.5'] + +class TestServiceLLDP(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + # call base-classes classmethod + super(TestServiceLLDP, cls).setUpClass() + + # create a test interfaces + for addr in mgmt_addr: + cls.cli_set(cls, ['interfaces', 'dummy', mgmt_if, 'address', addr + '/32']) + + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + cls.cli_delete(cls, base_path) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['interfaces', 'dummy', mgmt_if]) + super(TestServiceLLDP, cls).tearDownClass() + + def tearDown(self): + # service must be running after it was configured + self.assertTrue(process_named_running(PROCESS_NAME)) + + # delete/stop LLDP service + self.cli_delete(base_path) + self.cli_commit() + + # service is no longer allowed to run after it was removed + self.assertFalse(process_named_running(PROCESS_NAME)) + + def test_01_lldp_basic(self): + self.cli_set(base_path) + self.cli_commit() + + config = read_file(LLDPD_CONF) + version_data = get_version_data() + version = version_data['version'] + self.assertIn(f'configure system platform VyOS', config) + self.assertIn(f'configure system description "VyOS {version}"', config) + + def test_02_lldp_mgmt_address(self): + for addr in mgmt_addr: + self.cli_set(base_path + ['management-address', addr]) + self.cli_commit() + + config = read_file(LLDPD_CONF) + self.assertIn(f'configure system ip management pattern {",".join(mgmt_addr)}', config) + + def test_03_lldp_interfaces(self): + for interface in Section.interfaces('ethernet'): + if not '.' in interface: + self.cli_set(base_path + ['interface', interface]) + + # commit changes + self.cli_commit() + + # verify configuration + config = read_file(LLDPD_CONF) + + interface_list = [] + for interface in Section.interfaces('ethernet'): + if not '.' in interface: + interface_list.append(interface) + tmp = ','.join(interface_list) + self.assertIn(f'configure system interface pattern "{tmp}"', config) + + def test_04_lldp_all_interfaces(self): + self.cli_set(base_path + ['interface', 'all']) + # commit changes + self.cli_commit() + + # verify configuration + config = read_file(LLDPD_CONF) + self.assertIn(f'configure system interface pattern "*"', config) + + def test_05_lldp_location(self): + interface = 'eth0' + elin = '1234567890' + self.cli_set(base_path + ['interface', interface, 'location', 'elin', elin]) + + # commit changes + self.cli_commit() + + # verify configuration + config = read_file(LLDPD_CONF) + + self.assertIn(f'configure ports {interface} med location elin "{elin}"', config) + self.assertIn(f'configure system interface pattern "{interface}"', config) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_monitoring_telegraf.py b/smoketest/scripts/cli/test_service_monitoring_telegraf.py new file mode 100755 index 000000000..09937513e --- /dev/null +++ b/smoketest/scripts/cli/test_service_monitoring_telegraf.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.configsession import ConfigSession +from vyos.configsession import ConfigSessionError +from vyos.util import process_named_running +from vyos.util import read_file + +PROCESS_NAME = 'telegraf' +TELEGRAF_CONF = '/run/telegraf/vyos-telegraf.conf' +base_path = ['service', 'monitoring', 'telegraf'] +org = 'log@in.local' +token = 'GuRJc12tIzfjnYdKRAIYbxdWd2aTpOT9PVYNddzDnFV4HkAcD7u7-kndTFXjGuXzJN6TTxmrvPODB4mnFcseDV==' +port = '8888' +url = 'https://foo.local' +bucket = 'main' +inputs = ['cpu', 'disk', 'mem', 'net', 'system', 'kernel', 'interrupts', 'syslog'] + +class TestMonitoringTelegraf(VyOSUnitTestSHIM.TestCase): + def tearDown(self): + self.cli_delete(base_path) + self.cli_commit() + + def test_01_basic_config(self): + self.cli_set(base_path + ['authentication', 'organization', org]) + self.cli_set(base_path + ['authentication', 'token', token]) + self.cli_set(base_path + ['port', port]) + self.cli_set(base_path + ['url', url]) + + # commit changes + self.cli_commit() + + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + + config = read_file(TELEGRAF_CONF) + + # Check telegraf config + self.assertIn(f'organization = "{org}"', config) + self.assertIn(f' token = "$INFLUX_TOKEN"', config) + self.assertIn(f'urls = ["{url}:{port}"]', config) + self.assertIn(f'bucket = "{bucket}"', config) + + for input in inputs: + self.assertIn(input, config) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_salt.py b/smoketest/scripts/cli/test_service_salt.py new file mode 100755 index 000000000..00a4f2020 --- /dev/null +++ b/smoketest/scripts/cli/test_service_salt.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 socket import gethostname +from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.util import process_named_running +from vyos.util import read_file +from vyos.util import cmd + +PROCESS_NAME = 'salt-minion' +SALT_CONF = '/etc/salt/minion' +base_path = ['service', 'salt-minion'] + +interface = 'dum4456' + +class TestServiceSALT(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestServiceSALT, 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, ['interfaces', 'dummy', interface, 'address', '100.64.0.1/16']) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['interfaces', 'dummy', interface]) + super(TestServiceSALT, cls).tearDownClass() + + def tearDown(self): + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + + # delete testing SALT config + self.cli_delete(base_path) + self.cli_commit() + + # For an unknown reason on QEMU systems (e.g. where smoketests are executed + # from the CI) salt-minion process is not killed by systemd. Apparently + # no issue on VMWare. + if cmd('systemd-detect-virt') != 'kvm': + self.assertFalse(process_named_running(PROCESS_NAME)) + + def test_default(self): + servers = ['192.0.2.1', '192.0.2.2'] + + for server in servers: + self.cli_set(base_path + ['master', server]) + + self.cli_commit() + + # commiconf = read_file() Check configured port + conf = read_file(SALT_CONF) + self.assertIn(f' - {server}', conf) + + # defaults + hostname = gethostname() + self.assertIn(f'hash_type: sha256', conf) + self.assertIn(f'id: {hostname}', conf) + self.assertIn(f'mine_interval: 60', conf) + + def test_options(self): + server = '192.0.2.3' + hash = 'sha1' + id = 'foo' + interval = '120' + + self.cli_set(base_path + ['master', server]) + self.cli_set(base_path + ['hash', hash]) + self.cli_set(base_path + ['id', id]) + self.cli_set(base_path + ['interval', interval]) + self.cli_set(base_path + ['source-interface', interface]) + + self.cli_commit() + + # commiconf = read_file() Check configured port + conf = read_file(SALT_CONF) + self.assertIn(f'- {server}', conf) + + # defaults + self.assertIn(f'hash_type: {hash}', conf) + self.assertIn(f'id: {id}', conf) + self.assertIn(f'mine_interval: {interval}', conf) + self.assertIn(f'source_interface_name: {interface}', conf) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_snmp.py b/smoketest/scripts/cli/test_service_snmp.py index 058835c72..e80c689cc 100755 --- a/smoketest/scripts/cli/test_service_snmp.py +++ b/smoketest/scripts/cli/test_service_snmp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2019-2021 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,14 +22,25 @@ from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSessionError from vyos.template import is_ipv4 from vyos.template import address_from_cidr +from vyos.util import call +from vyos.util import DEVNULL from vyos.util import read_file from vyos.util import process_named_running +from vyos.version import get_version_data PROCESS_NAME = 'snmpd' SNMPD_CONF = '/etc/snmp/snmpd.conf' base_path = ['service', 'snmp'] +snmpv3_group = 'default_group' +snmpv3_view = 'default_view' +snmpv3_view_oid = '1' +snmpv3_user = 'vyos' +snmpv3_auth_pw = 'vyos12345678' +snmpv3_priv_pw = 'vyos87654321' +snmpv3_engine_id = '000000000000000000000002' + def get_config_value(key): tmp = read_file(SNMPD_CONF) tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) @@ -38,20 +49,29 @@ def get_config_value(key): class TestSNMPService(VyOSUnitTestSHIM.TestCase): @classmethod def setUpClass(cls): - super(cls, cls).setUpClass() + super(TestSNMPService, 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) def tearDown(self): + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + # delete testing SNMP config self.cli_delete(base_path) self.cli_commit() + # Check for running process + self.assertFalse(process_named_running(PROCESS_NAME)) + def test_snmp_basic(self): dummy_if = 'dum7312' dummy_addr = '100.64.0.1/32' + contact = 'maintainers@vyos.io' + location = 'QEMU' + self.cli_set(['interfaces', 'dummy', dummy_if, 'address', dummy_addr]) # Check if SNMP can be configured and service runs @@ -71,8 +91,8 @@ class TestSNMPService(VyOSUnitTestSHIM.TestCase): for addr in listen: self.cli_set(base_path + ['listen-address', addr, 'port', port]) - self.cli_set(base_path + ['contact', 'maintainers@vyos.io']) - self.cli_set(base_path + ['location', 'qemu']) + self.cli_set(base_path + ['contact', contact]) + self.cli_set(base_path + ['location', location]) self.cli_commit() @@ -82,7 +102,6 @@ class TestSNMPService(VyOSUnitTestSHIM.TestCase): config = get_config_value('agentaddress') expected = 'unix:/run/snmpd.socket' self.assertIn(expected, config) - for addr in listen: if is_ipv4(addr): expected = f'udp:{addr}:{port}' @@ -90,6 +109,16 @@ class TestSNMPService(VyOSUnitTestSHIM.TestCase): expected = f'udp6:[{addr}]:{port}' self.assertIn(expected, config) + config = get_config_value('sysDescr') + version_data = get_version_data() + self.assertEqual('VyOS ' + version_data['version'], config) + + config = get_config_value('SysContact') + self.assertEqual(contact, config) + + config = get_config_value('SysLocation') + self.assertEqual(location, config) + # Check for running process self.assertTrue(process_named_running(PROCESS_NAME)) self.cli_delete(['interfaces', 'dummy', dummy_if]) @@ -98,8 +127,7 @@ class TestSNMPService(VyOSUnitTestSHIM.TestCase): def test_snmpv3_sha(self): # Check if SNMPv3 can be configured with SHA authentication # and service runs - - self.cli_set(base_path + ['v3', 'engineid', '000000000000000000000002']) + self.cli_set(base_path + ['v3', 'engineid', snmpv3_engine_id]) self.cli_set(base_path + ['v3', 'group', 'default', 'mode', 'ro']) # check validate() - a view must be created before this can be committed with self.assertRaises(ConfigSessionError): @@ -109,46 +137,52 @@ class TestSNMPService(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + ['v3', 'group', 'default', 'view', 'default']) # create user - self.cli_set(base_path + ['v3', 'user', 'vyos', 'auth', 'plaintext-password', 'vyos12345678']) - self.cli_set(base_path + ['v3', 'user', 'vyos', 'auth', 'type', 'sha']) - self.cli_set(base_path + ['v3', 'user', 'vyos', 'privacy', 'plaintext-password', 'vyos12345678']) - self.cli_set(base_path + ['v3', 'user', 'vyos', 'privacy', 'type', 'aes']) - self.cli_set(base_path + ['v3', 'user', 'vyos', 'group', 'default']) + self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'auth', 'plaintext-password', snmpv3_auth_pw]) + self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'auth', 'type', 'sha']) + self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'privacy', 'plaintext-password', snmpv3_priv_pw]) + self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'privacy', 'type', 'aes']) + self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'group', 'default']) self.cli_commit() # commit will alter the CLI values - check if they have been updated: hashed_password = '4e52fe55fd011c9c51ae2c65f4b78ca93dcafdfe' - tmp = self._session.show_config(base_path + ['v3', 'user', 'vyos', 'auth', 'encrypted-password']).split()[1] + tmp = self._session.show_config(base_path + ['v3', 'user', snmpv3_user, 'auth', 'encrypted-password']).split()[1] self.assertEqual(tmp, hashed_password) - tmp = self._session.show_config(base_path + ['v3', 'user', 'vyos', 'privacy', 'encrypted-password']).split()[1] + hashed_password = '54705c8de9e81fdf61ad7ac044fa8fe611ddff6b' + tmp = self._session.show_config(base_path + ['v3', 'user', snmpv3_user, 'privacy', 'encrypted-password']).split()[1] self.assertEqual(tmp, hashed_password) # TODO: read in config file and check values - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) + # Try SNMPv3 connection + tmp = call(f'snmpwalk -v 3 -u {snmpv3_user} -a SHA -A {snmpv3_auth_pw} -x AES -X {snmpv3_priv_pw} -l authPriv 127.0.0.1', stdout=DEVNULL) + self.assertEqual(tmp, 0) def test_snmpv3_md5(self): # Check if SNMPv3 can be configured with MD5 authentication # and service runs + self.cli_set(base_path + ['v3', 'engineid', snmpv3_engine_id]) - self.cli_set(base_path + ['v3', 'engineid', '000000000000000000000002']) - self.cli_set(base_path + ['v3', 'group', 'default', 'mode', 'ro']) - # check validate() - a view must be created before this can be comitted + # create user + self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'auth', 'plaintext-password', snmpv3_auth_pw]) + self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'auth', 'type', 'md5']) + self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'privacy', 'plaintext-password', snmpv3_priv_pw]) + self.cli_set(base_path + ['v3', 'user', snmpv3_user, 'privacy', 'type', 'des']) + + # check validate() - user requires a group to be created with self.assertRaises(ConfigSessionError): self.cli_commit() + self.cli_set(base_path + ['v3', 'user', 'vyos', 'group', snmpv3_group]) - self.cli_set(base_path + ['v3', 'view', 'default', 'oid', '1']) - self.cli_set(base_path + ['v3', 'group', 'default', 'view', 'default']) + self.cli_set(base_path + ['v3', 'group', snmpv3_group, 'mode', 'ro']) + # check validate() - a view must be created before this can be comitted + with self.assertRaises(ConfigSessionError): + self.cli_commit() - # create user - self.cli_set(base_path + ['v3', 'user', 'vyos', 'auth', 'plaintext-password', 'vyos12345678']) - self.cli_set(base_path + ['v3', 'user', 'vyos', 'auth', 'type', 'md5']) - self.cli_set(base_path + ['v3', 'user', 'vyos', 'privacy', 'plaintext-password', 'vyos12345678']) - self.cli_set(base_path + ['v3', 'user', 'vyos', 'privacy', 'type', 'des']) - self.cli_set(base_path + ['v3', 'user', 'vyos', 'group', 'default']) + self.cli_set(base_path + ['v3', 'view', snmpv3_view, 'oid', snmpv3_view_oid]) + self.cli_set(base_path + ['v3', 'group', snmpv3_group, 'view', snmpv3_view]) self.cli_commit() @@ -157,13 +191,21 @@ class TestSNMPService(VyOSUnitTestSHIM.TestCase): tmp = self._session.show_config(base_path + ['v3', 'user', 'vyos', 'auth', 'encrypted-password']).split()[1] self.assertEqual(tmp, hashed_password) + hashed_password = 'e11c83f2c510540a3c4de84ee66de440' tmp = self._session.show_config(base_path + ['v3', 'user', 'vyos', 'privacy', 'encrypted-password']).split()[1] self.assertEqual(tmp, hashed_password) - # TODO: read in config file and check values - - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) + tmp = read_file(SNMPD_CONF) + # views + self.assertIn(f'view {snmpv3_view} included .{snmpv3_view_oid}', tmp) + # group + self.assertIn(f'group {snmpv3_group} usm {snmpv3_user}', tmp) + # access + self.assertIn(f'access {snmpv3_group} "" usm auth exact {snmpv3_view} none none', tmp) + + # Try SNMPv3 connection + tmp = call(f'snmpwalk -v 3 -u {snmpv3_user} -a MD5 -A {snmpv3_auth_pw} -x DES -X {snmpv3_priv_pw} -l authPriv 127.0.0.1', stdout=DEVNULL) + self.assertEqual(tmp, 0) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_ssh.py b/smoketest/scripts/cli/test_service_ssh.py index a54c03919..0b029dd00 100755 --- a/smoketest/scripts/cli/test_service_ssh.py +++ b/smoketest/scripts/cli/test_service_ssh.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 @@ -15,13 +15,17 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os +import paramiko import re import unittest +from pwd import getpwall + from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSessionError from vyos.util import cmd +from vyos.util import is_systemd_service_running from vyos.util import process_named_running from vyos.util import read_file @@ -42,13 +46,16 @@ def get_config_value(key): class TestServiceSSH(VyOSUnitTestSHIM.TestCase): @classmethod def setUpClass(cls): - super(cls, cls).setUpClass() + super(TestServiceSSH, 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) def tearDown(self): + # Check for running process + self.assertTrue(process_named_running(PROCESS_NAME)) + # delete testing SSH config self.cli_delete(base_path) self.cli_commit() @@ -57,6 +64,11 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): self.assertTrue(os.path.isfile(key_dsa)) self.assertTrue(os.path.isfile(key_ed25519)) + # Established SSH connections remains running after service is stopped. + # We can not use process_named_running here - we rather need to check + # that the systemd service is no longer running + self.assertFalse(is_systemd_service_running(PROCESS_NAME)) + def test_ssh_default(self): # Check if SSH service runs with default settings - used for checking # behavior of <defaultValue> in XML definition @@ -69,9 +81,6 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): port = get_config_value('Port')[0] self.assertEqual('22', port) - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) - def test_ssh_single_listen_address(self): # Check if SSH service can be configured and runs self.cli_set(base_path + ['port', '1234']) @@ -108,9 +117,6 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): keepalive = get_config_value('ClientAliveInterval')[0] self.assertTrue("100" in keepalive) - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) - def test_ssh_multiple_listen_addresses(self): # Check if SSH service can be configured and runs with multiple # listen ports and listen-addresses @@ -135,9 +141,6 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): for address in addresses: self.assertIn(address, tmp) - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) - def test_ssh_vrf(self): # Check if SSH service can be bound to given VRF port = '22' @@ -157,9 +160,6 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): tmp = get_config_value('Port') self.assertIn(port, tmp) - # 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) @@ -167,5 +167,100 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): # delete VRF self.cli_delete(['vrf', 'name', vrf]) + def test_ssh_login(self): + # Perform SSH login and command execution with a predefined user. The + # result (output of uname -a) must match the output if the command is + # run natively. + # + # We also try to login as an invalid user - this is not allowed to work. + + def ssh_send_cmd(command, username, password, host='localhost'): + """ SSH command execution helper """ + # Try to login via SSH + ssh_client = paramiko.SSHClient() + ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh_client.connect(hostname='localhost', username=username, password=password) + _, stdout, stderr = ssh_client.exec_command(command) + output = stdout.read().decode().strip() + error = stderr.read().decode().strip() + ssh_client.close() + return output, error + + test_user = 'ssh_test' + test_pass = 'v2i57DZs8idUwMN3VC92' + test_command = 'uname -a' + + self.cli_set(base_path) + self.cli_set(['system', 'login', 'user', test_user, 'authentication', 'plaintext-password', test_pass]) + + # commit changes + self.cli_commit() + + # Login with proper credentials + output, error = ssh_send_cmd(test_command, test_user, test_pass) + # verify login + self.assertFalse(error) + self.assertEqual(output, cmd(test_command)) + + # Login with invalid credentials + with self.assertRaises(paramiko.ssh_exception.AuthenticationException): + output, error = ssh_send_cmd(test_command, 'invalid_user', 'invalid_password') + + self.cli_delete(['system', 'login', 'user', test_user]) + self.cli_commit() + + # After deletion the test user is not allowed to remain in /etc/passwd + usernames = [x[0] for x in getpwall()] + self.assertNotIn(test_user, usernames) + + def test_ssh_dynamic_protection(self): + # check sshguard service + + SSHGUARD_CONFIG = '/etc/sshguard/sshguard.conf' + SSHGUARD_WHITELIST = '/etc/sshguard/whitelist' + SSHGUARD_PROCESS = 'sshguard' + block_time = '123' + detect_time = '1804' + port = '22' + threshold = '10' + allow_list = ['192.0.2.0/24', '2001:db8::/48'] + + self.cli_set(base_path + ['dynamic-protection', 'block-time', block_time]) + self.cli_set(base_path + ['dynamic-protection', 'detect-time', detect_time]) + self.cli_set(base_path + ['dynamic-protection', 'threshold', threshold]) + for allow in allow_list: + self.cli_set(base_path + ['dynamic-protection', 'allow-from', allow]) + + # commit changes + self.cli_commit() + + # Check configured port + tmp = get_config_value('Port') + self.assertIn(port, tmp) + + # Check sshgurad service + self.assertTrue(process_named_running(SSHGUARD_PROCESS)) + + sshguard_lines = [ + f'THRESHOLD={threshold}', + f'BLOCK_TIME={block_time}', + f'DETECTION_TIME={detect_time}' + ] + + tmp_sshguard_conf = read_file(SSHGUARD_CONFIG) + for line in sshguard_lines: + self.assertIn(line, tmp_sshguard_conf) + + tmp_whitelist_conf = read_file(SSHGUARD_WHITELIST) + for allow in allow_list: + self.assertIn(allow, tmp_whitelist_conf) + + # Delete service ssh dynamic-protection + # but not service ssh itself + self.cli_delete(base_path + ['dynamic-protection']) + self.cli_commit() + + self.assertFalse(process_named_running(SSHGUARD_PROCESS)) + 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 1a1bf0cdf..b57c33f26 100755 --- a/smoketest/scripts/cli/test_service_tftp-server.py +++ b/smoketest/scripts/cli/test_service_tftp-server.py @@ -20,6 +20,7 @@ from psutil import process_iter from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSessionError +from vyos.util import cmd from vyos.util import read_file from vyos.util import process_named_running from vyos.template import is_ipv6 @@ -29,6 +30,7 @@ base_path = ['service', 'tftp-server'] dummy_if_path = ['interfaces', 'dummy', 'dum69'] address_ipv4 = '192.0.2.1' address_ipv6 = '2001:db8::1' +vrf = 'mgmt' class TestServiceTFTPD(VyOSUnitTestSHIM.TestCase): def setUp(self): @@ -97,5 +99,42 @@ class TestServiceTFTPD(VyOSUnitTestSHIM.TestCase): count += 1 self.assertEqual(count, len(address)) + def test_03_tftpd_vrf(self): + directory = '/tmp' + port = '69' # default port + + self.cli_set(base_path + ['allow-upload']) + self.cli_set(base_path + ['directory', directory]) + self.cli_set(base_path + ['listen-address', address_ipv4, 'vrf', vrf]) + + # VRF does yet not exist - an error must be thrown + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(['vrf', 'name', vrf, 'table', '1338']) + self.cli_set(dummy_if_path + ['vrf', vrf]) + + # commit changes + self.cli_commit() + + config = read_file('/etc/default/tftpd0') + # verify listen IP address + self.assertIn(f'{address_ipv4}:{port} -4', config) + # verify directory + self.assertIn(directory, config) + # 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) + + # delete VRF + self.cli_delete(dummy_if_path + ['vrf']) + self.cli_delete(['vrf', 'name', vrf]) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_upnp.py b/smoketest/scripts/cli/test_service_upnp.py new file mode 100755 index 000000000..e4df88c1e --- /dev/null +++ b/smoketest/scripts/cli/test_service_upnp.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021-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 +# 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 re +import unittest + +from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.configsession import ConfigSession +from vyos.configsession import ConfigSessionError +from vyos.template import ip_from_cidr +from vyos.util import read_file +from vyos.util import process_named_running + +UPNP_CONF = '/run/upnp/miniupnp.conf' +DAEMON = 'miniupnpd' +interface = 'eth0' +base_path = ['service', 'upnp'] +address_base = ['interfaces', 'ethernet', interface, 'address'] + +ipv4_addr = '100.64.0.1/24' +ipv6_addr = '2001:db8::1/64' + +class TestServiceUPnP(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestServiceUPnP, 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, address_base + [ipv4_addr]) + cls.cli_set(cls, address_base + [ipv6_addr]) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, address_base) + cls._session.commit() + + super(TestServiceUPnP, cls).tearDownClass() + + def tearDown(self): + # Check for running process + self.assertTrue(process_named_running(DAEMON)) + + self.cli_delete(base_path) + self.cli_commit() + + # Check for running process + self.assertFalse(process_named_running(DAEMON)) + + def test_ipv4_base(self): + self.cli_set(base_path + ['nat-pmp']) + self.cli_set(base_path + ['listen', interface]) + + # check validate() - WAN interface is mandatory + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(base_path + ['wan-interface', interface]) + + self.cli_commit() + + config = read_file(UPNP_CONF) + self.assertIn(f'ext_ifname={interface}', config) + self.assertIn(f'listening_ip={interface}', config) + self.assertIn(f'enable_natpmp=yes', config) + self.assertIn(f'enable_upnp=yes', config) + + def test_ipv6_base(self): + v6_addr = ip_from_cidr(ipv6_addr) + + self.cli_set(base_path + ['nat-pmp']) + self.cli_set(base_path + ['listen', interface]) + self.cli_set(base_path + ['listen', v6_addr]) + + # check validate() - WAN interface is mandatory + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(base_path + ['wan-interface', interface]) + + self.cli_commit() + + config = read_file(UPNP_CONF) + self.assertIn(f'ext_ifname={interface}', config) + self.assertIn(f'listening_ip={interface}', config) + self.assertIn(f'ipv6_listening_ip={v6_addr}', config) + self.assertIn(f'enable_natpmp=yes', config) + self.assertIn(f'enable_upnp=yes', config) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_webproxy.py b/smoketest/scripts/cli/test_service_webproxy.py index 8a1a03ce7..772d6ab16 100755 --- a/smoketest/scripts/cli/test_service_webproxy.py +++ b/smoketest/scripts/cli/test_service_webproxy.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -30,11 +30,19 @@ listen_if = 'dum3632' listen_ip = '192.0.2.1' class TestServiceWebProxy(VyOSUnitTestSHIM.TestCase): - def setUp(self): - self.cli_set(['interfaces', 'dummy', listen_if, 'address', listen_ip + '/32']) + @classmethod + def setUpClass(cls): + # call base-classes classmethod + super(TestServiceWebProxy, cls).setUpClass() + # create a test interfaces + cls.cli_set(cls, ['interfaces', 'dummy', listen_if, 'address', listen_ip + '/32']) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['interfaces', 'dummy', listen_if]) + super(TestServiceWebProxy, cls).tearDownClass() def tearDown(self): - self.cli_delete(['interfaces', 'dummy', listen_if]) self.cli_delete(base_path) self.cli_commit() diff --git a/smoketest/scripts/cli/test_system_conntrack.py b/smoketest/scripts/cli/test_system_conntrack.py index b2934cf04..95c2a6c55 100755 --- a/smoketest/scripts/cli/test_system_conntrack.py +++ b/smoketest/scripts/cli/test_system_conntrack.py @@ -15,10 +15,12 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os +import re import unittest from base_vyostest_shim import VyOSUnitTestSHIM +from vyos.firewall import find_nftables_rule from vyos.util import cmd from vyos.util import read_file @@ -156,8 +158,8 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase): 'driver' : ['nf_nat_h323', 'nf_conntrack_h323'], }, 'nfs' : { - 'iptables' : ['-A VYATTA_CT_HELPER -p udp -m udp --dport 111 -j CT --helper rpc', - '-A VYATTA_CT_HELPER -p tcp -m tcp --dport 111 -j CT --helper rpc'], + 'nftables' : ['ct helper set "rpc_tcp"', + 'ct helper set "rpc_udp"'] }, 'pptp' : { 'driver' : ['nf_nat_pptp', 'nf_conntrack_pptp'], @@ -166,9 +168,7 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase): 'driver' : ['nf_nat_sip', 'nf_conntrack_sip'], }, 'sqlnet' : { - 'iptables' : ['-A VYATTA_CT_HELPER -p tcp -m tcp --dport 1536 -j CT --helper tns', - '-A VYATTA_CT_HELPER -p tcp -m tcp --dport 1525 -j CT --helper tns', - '-A VYATTA_CT_HELPER -p tcp -m tcp --dport 1521 -j CT --helper tns'], + 'nftables' : ['ct helper set "tns_tcp"'] }, 'tftp' : { 'driver' : ['nf_nat_tftp', 'nf_conntrack_tftp'], @@ -187,10 +187,9 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase): if 'driver' in module_options: for driver in module_options['driver']: self.assertTrue(os.path.isdir(f'/sys/module/{driver}')) - if 'iptables' in module_options: - rules = cmd('sudo iptables-save -t raw') - for ruleset in module_options['iptables']: - self.assertIn(ruleset, rules) + if 'nftables' in module_options: + for rule in module_options['nftables']: + self.assertTrue(find_nftables_rule('raw', 'VYOS_CT_HELPER', [rule]) != None) # unload modules for module in modules: @@ -204,10 +203,9 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase): if 'driver' in module_options: for driver in module_options['driver']: self.assertFalse(os.path.isdir(f'/sys/module/{driver}')) - if 'iptables' in module_options: - rules = cmd('sudo iptables-save -t raw') - for ruleset in module_options['iptables']: - self.assertNotIn(ruleset, rules) + if 'nftables' in module_options: + for rule in module_options['nftables']: + self.assertTrue(find_nftables_rule('raw', 'VYOS_CT_HELPER', [rule]) == None) def test_conntrack_hash_size(self): hash_size = '65536' diff --git a/smoketest/scripts/cli/test_system_flow-accounting.py b/smoketest/scripts/cli/test_system_flow-accounting.py index a2b5b1481..a6eef3fb6 100755 --- a/smoketest/scripts/cli/test_system_flow-accounting.py +++ b/smoketest/scripts/cli/test_system_flow-accounting.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -20,6 +20,8 @@ from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSessionError from vyos.ifconfig import Section +from vyos.template import bracketize_ipv6 +from vyos.template import is_ipv6 from vyos.util import cmd from vyos.util import process_named_running from vyos.util import read_file @@ -27,18 +29,21 @@ from vyos.util import read_file PROCESS_NAME = 'uacctd' base_path = ['system', 'flow-accounting'] -uacctd_conf = '/etc/pmacct/uacctd.conf' +uacctd_conf = '/run/pmacct/uacctd.conf' class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase): @classmethod def setUpClass(cls): - super(cls, cls).setUpClass() + super(TestSystemFlowAccounting, 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) def tearDown(self): + # after service removal process must no longer run + self.assertTrue(process_named_running(PROCESS_NAME)) + self.cli_delete(base_path) self.cli_commit() @@ -47,7 +52,10 @@ class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase): def test_basic(self): buffer_size = '5' # MiB + syslog = 'all' + self.cli_set(base_path + ['buffer-size', buffer_size]) + self.cli_set(base_path + ['syslog-facility', syslog]) # You need to configure at least one interface for flow-accounting with self.assertRaises(ConfigSessionError): @@ -59,9 +67,20 @@ class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase): self.cli_commit() # verify configuration - tmp = cmd('sudo iptables-save -t raw') + nftables_output = cmd('sudo nft list chain raw VYOS_CT_PREROUTING_HOOK').splitlines() for interface in Section.interfaces('ethernet'): - self.assertIn(f'-A VYATTA_CT_PREROUTING_HOOK -i {interface} -m comment --comment FLOW_ACCOUNTING_RULE -j NFLOG --nflog-group 2 --nflog-size 128 --nflog-threshold 100', tmp) + rule_found = False + ifname_search = f'iifname "{interface}"' + + for nftables_line in nftables_output: + if 'FLOW_ACCOUNTING_RULE' in nftables_line and ifname_search in nftables_line: + self.assertIn('group 2', nftables_line) + self.assertIn('snaplen 128', nftables_line) + self.assertIn('queue-threshold 100', nftables_line) + rule_found = True + break + + self.assertTrue(rule_found) uacctd = read_file(uacctd_conf) # circular queue size - buffer_size @@ -73,8 +92,205 @@ class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase): tmp //= 1000 self.assertIn(f'plugin_buffer_size: {tmp}', uacctd) - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) + # when 'disable-imt' is not configured on the CLI it must be present + self.assertIn(f'imt_path: /tmp/uacctd.pipe', uacctd) + self.assertIn(f'imt_mem_pools_number: 169', uacctd) + self.assertIn(f'syslog: {syslog}', uacctd) + self.assertIn(f'plugins: memory', uacctd) + + def test_sflow(self): + sampling_rate = '4000' + source_address = '192.0.2.1' + dummy_if = 'dum3841' + agent_address = '192.0.2.2' + + sflow_server = { + '1.2.3.4' : { }, + '5.6.7.8' : { 'port' : '6000' }, + } + + self.cli_set(['interfaces', 'dummy', dummy_if, 'address', agent_address + '/32']) + self.cli_set(['interfaces', 'dummy', dummy_if, 'address', source_address + '/32']) + self.cli_set(base_path + ['disable-imt']) + + # You need to configure at least one interface for flow-accounting + with self.assertRaises(ConfigSessionError): + self.cli_commit() + for interface in Section.interfaces('ethernet'): + self.cli_set(base_path + ['interface', interface]) + + + # You need to configure at least one sFlow or NetFlow protocol, or not + # set "disable-imt" for flow-accounting + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(base_path + ['sflow', 'agent-address', agent_address]) + self.cli_set(base_path + ['sflow', 'sampling-rate', sampling_rate]) + self.cli_set(base_path + ['sflow', 'source-address', source_address]) + for server, server_config in sflow_server.items(): + self.cli_set(base_path + ['sflow', 'server', server]) + if 'port' in server_config: + self.cli_set(base_path + ['sflow', 'server', server, 'port', server_config['port']]) + + # commit changes + self.cli_commit() + + uacctd = read_file(uacctd_conf) + + # when 'disable-imt' is not configured on the CLI it must be present + self.assertNotIn(f'imt_path: /tmp/uacctd.pipe', uacctd) + self.assertNotIn(f'imt_mem_pools_number: 169', uacctd) + self.assertNotIn(f'plugins: memory', uacctd) + + for server, server_config in sflow_server.items(): + if 'port' in server_config: + self.assertIn(f'sfprobe_receiver[sf_{server}]: {server}', uacctd) + else: + self.assertIn(f'sfprobe_receiver[sf_{server}]: {server}:6343', uacctd) + + self.assertIn(f'sfprobe_agentip[sf_{server}]: {agent_address}', uacctd) + self.assertIn(f'sampling_rate[sf_{server}]: {sampling_rate}', uacctd) + self.assertIn(f'sfprobe_source_ip[sf_{server}]: {source_address}', uacctd) + + self.cli_delete(['interfaces', 'dummy', dummy_if]) + + def test_sflow_ipv6(self): + sampling_rate = '100' + sflow_server = { + '2001:db8::1' : { }, + '2001:db8::2' : { 'port' : '6000' }, + } + + self.cli_set(base_path + ['disable-imt']) + + # You need to configure at least one interface for flow-accounting + with self.assertRaises(ConfigSessionError): + self.cli_commit() + for interface in Section.interfaces('ethernet'): + self.cli_set(base_path + ['interface', interface]) + + + # You need to configure at least one sFlow or NetFlow protocol, or not + # set "disable-imt" for flow-accounting + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_set(base_path + ['sflow', 'sampling-rate', sampling_rate]) + for server, server_config in sflow_server.items(): + self.cli_set(base_path + ['sflow', 'server', server]) + if 'port' in server_config: + self.cli_set(base_path + ['sflow', 'server', server, 'port', server_config['port']]) + + # commit changes + self.cli_commit() + + uacctd = read_file(uacctd_conf) + + # when 'disable-imt' is not configured on the CLI it must be present + self.assertNotIn(f'imt_path: /tmp/uacctd.pipe', uacctd) + self.assertNotIn(f'imt_mem_pools_number: 169', uacctd) + self.assertNotIn(f'plugins: memory', uacctd) + + for server, server_config in sflow_server.items(): + tmp_srv = server + if is_ipv6(tmp_srv): + tmp_srv = tmp_srv.replace(':', '.') + + if 'port' in server_config: + self.assertIn(f'sfprobe_receiver[sf_{tmp_srv}]: {bracketize_ipv6(server)}', uacctd) + else: + self.assertIn(f'sfprobe_receiver[sf_{tmp_srv}]: {bracketize_ipv6(server)}:6343', uacctd) + self.assertIn(f'sampling_rate[sf_{tmp_srv}]: {sampling_rate}', uacctd) + + def test_netflow(self): + engine_id = '33' + max_flows = '667' + sampling_rate = '100' + source_address = '192.0.2.1' + dummy_if = 'dum3842' + agent_address = '192.0.2.10' + version = '10' + tmo_expiry = '120' + tmo_flow = '1200' + tmo_icmp = '60' + tmo_max = '50000' + tmo_tcp_fin = '100' + tmo_tcp_generic = '120' + tmo_tcp_rst = '99' + tmo_udp = '10' + + netflow_server = { + '11.22.33.44' : { }, + '55.66.77.88' : { 'port' : '6000' }, + '2001:db8::1' : { }, + } + + self.cli_set(['interfaces', 'dummy', dummy_if, 'address', agent_address + '/32']) + self.cli_set(['interfaces', 'dummy', dummy_if, 'address', source_address + '/32']) + + for interface in Section.interfaces('ethernet'): + self.cli_set(base_path + ['interface', interface]) + + self.cli_set(base_path + ['netflow', 'engine-id', engine_id]) + self.cli_set(base_path + ['netflow', 'max-flows', max_flows]) + self.cli_set(base_path + ['netflow', 'sampling-rate', sampling_rate]) + self.cli_set(base_path + ['netflow', 'source-address', source_address]) + self.cli_set(base_path + ['netflow', 'version', version]) + + # timeouts + self.cli_set(base_path + ['netflow', 'timeout', 'expiry-interval', tmo_expiry]) + self.cli_set(base_path + ['netflow', 'timeout', 'flow-generic', tmo_flow]) + self.cli_set(base_path + ['netflow', 'timeout', 'icmp', tmo_icmp]) + self.cli_set(base_path + ['netflow', 'timeout', 'max-active-life', tmo_max]) + self.cli_set(base_path + ['netflow', 'timeout', 'tcp-fin', tmo_tcp_fin]) + self.cli_set(base_path + ['netflow', 'timeout', 'tcp-generic', tmo_tcp_generic]) + self.cli_set(base_path + ['netflow', 'timeout', 'tcp-rst', tmo_tcp_rst]) + self.cli_set(base_path + ['netflow', 'timeout', 'udp', tmo_udp]) + + # You need to configure at least one netflow server + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + for server, server_config in netflow_server.items(): + self.cli_set(base_path + ['netflow', 'server', server]) + if 'port' in server_config: + self.cli_set(base_path + ['netflow', 'server', server, 'port', server_config['port']]) + + # commit changes + self.cli_commit() + + uacctd = read_file(uacctd_conf) + + tmp = [] + for server, server_config in netflow_server.items(): + tmp_srv = server + if is_ipv6(tmp_srv): + tmp_srv = tmp_srv.replace(':', '.') + tmp.append(f'nfprobe[nf_{tmp_srv}]') + tmp.append('memory') + self.assertIn('plugins: ' + ','.join(tmp), uacctd) + + for server, server_config in netflow_server.items(): + tmp_srv = server + if is_ipv6(tmp_srv): + tmp_srv = tmp_srv.replace(':', '.') + + self.assertIn(f'nfprobe_engine[nf_{tmp_srv}]: {engine_id}', uacctd) + self.assertIn(f'nfprobe_maxflows[nf_{tmp_srv}]: {max_flows}', uacctd) + self.assertIn(f'sampling_rate[nf_{tmp_srv}]: {sampling_rate}', uacctd) + self.assertIn(f'nfprobe_source_ip[nf_{tmp_srv}]: {source_address}', uacctd) + self.assertIn(f'nfprobe_version[nf_{tmp_srv}]: {version}', uacctd) + + if 'port' in server_config: + self.assertIn(f'nfprobe_receiver[nf_{tmp_srv}]: {bracketize_ipv6(server)}', uacctd) + else: + self.assertIn(f'nfprobe_receiver[nf_{tmp_srv}]: {bracketize_ipv6(server)}:2055', uacctd) + + self.assertIn(f'nfprobe_timeouts[nf_{tmp_srv}]: expint={tmo_expiry}:general={tmo_flow}:icmp={tmo_icmp}:maxlife={tmo_max}:tcp.fin={tmo_tcp_fin}:tcp={tmo_tcp_generic}:tcp.rst={tmo_tcp_rst}:udp={tmo_udp}', uacctd) + + + self.cli_delete(['interfaces', 'dummy', dummy_if]) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_ipv6.py b/smoketest/scripts/cli/test_system_ipv6.py index 1325d4b39..c8aea9100 100755 --- a/smoketest/scripts/cli/test_system_ipv6.py +++ b/smoketest/scripts/cli/test_system_ipv6.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -17,12 +17,16 @@ import unittest from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.template import is_ipv4 from vyos.util import read_file +from vyos.util import get_interface_config +from vyos.validate import is_intf_addr_assigned base_path = ['system', 'ipv6'] file_forwarding = '/proc/sys/net/ipv6/conf/all/forwarding' -file_disable = '/etc/modprobe.d/vyos_disable_ipv6.conf' +file_disable = '/proc/sys/net/ipv6/conf/all/disable_ipv6' file_dad = '/proc/sys/net/ipv6/conf/all/accept_dad' file_multipath = '/proc/sys/net/ipv6/fib_multipath_hash_policy' @@ -41,15 +45,6 @@ class TestSystemIPv6(VyOSUnitTestSHIM.TestCase): self.assertEqual(read_file(file_forwarding), '0') - def test_system_ipv6_disable(self): - # Do not assign any IPv6 address on interfaces, this requires a reboot - # which can not be tested, but we can read the config file :) - self.cli_set(base_path + ['disable']) - self.cli_commit() - - # Verify configuration file - self.assertEqual(read_file(file_disable), 'options ipv6 disable_ipv6=1') - def test_system_ipv6_strict_dad(self): # This defaults to 1 self.assertEqual(read_file(file_dad), '1') diff --git a/smoketest/scripts/cli/test_system_login.py b/smoketest/scripts/cli/test_system_login.py index 69a06eeac..1131b6f93 100755 --- a/smoketest/scripts/cli/test_system_login.py +++ b/smoketest/scripts/cli/test_system_login.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 @@ -23,6 +23,7 @@ from base_vyostest_shim import VyOSUnitTestSHIM from distutils.version import LooseVersion from platform import release as kernel_version from subprocess import Popen, PIPE +from pwd import getpwall from vyos.configsession import ConfigSessionError from vyos.util import cmd @@ -52,6 +53,11 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase): self.cli_commit() + # After deletion, a user is not allowed to remain in /etc/passwd + usernames = [x[0] for x in getpwall()] + for user in users: + self.assertNotIn(user, usernames) + def test_add_linux_system_user(self): # We are not allowed to re-use a username already taken by the Linux # base system @@ -235,4 +241,4 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase): self.assertTrue(tmp) if __name__ == '__main__': - unittest.main(verbosity=2, failfast=True) + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_logs.py b/smoketest/scripts/cli/test_system_logs.py new file mode 100755 index 000000000..92fa9c3d9 --- /dev/null +++ b/smoketest/scripts/cli/test_system_logs.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 re +import unittest +from base_vyostest_shim import VyOSUnitTestSHIM +from vyos.util import read_file + +# path to logrotate configs +logrotate_atop_file = '/etc/logrotate.d/vyos-atop' +logrotate_rsyslog_file = '/etc/logrotate.d/vyos-rsyslog' +# default values +default_atop_maxsize = '10M' +default_atop_rotate = '10' +default_rsyslog_size = '1M' +default_rsyslog_rotate = '10' + +base_path = ['system', 'logs'] + + +def logrotate_config_parse(file_path): + # read the file + logrotate_config = read_file(file_path) + # create regex for parsing options + regex_options = re.compile( + r'(^\s+(?P<option_name_script>postrotate|prerotate|firstaction|lastaction|preremove)\n(?P<option_value_script>((?!endscript).)*)\n\s+endscript\n)|(^\s+(?P<option_name>[\S]+)([ \t]+(?P<option_value>\S+))*$)', + re.M | re.S) + # create empty dict for config + logrotate_config_dict = {} + # fill dictionary with actual config + for option in regex_options.finditer(logrotate_config): + option_name = option.group('option_name') + option_value = option.group('option_value') + option_name_script = option.group('option_name_script') + option_value_script = option.group('option_value_script') + if option_name: + logrotate_config_dict[option_name] = option_value + if option_name_script: + logrotate_config_dict[option_name_script] = option_value_script + + # return config dictionary + return (logrotate_config_dict) + + +class TestSystemLogs(VyOSUnitTestSHIM.TestCase): + + def tearDown(self): + self.cli_delete(base_path) + self.cli_commit() + + def test_logs_defaults(self): + # test with empty section for default values + self.cli_set(base_path) + self.cli_commit() + + # read the config file and check content + logrotate_config_atop = logrotate_config_parse(logrotate_atop_file) + logrotate_config_rsyslog = logrotate_config_parse( + logrotate_rsyslog_file) + self.assertEqual(logrotate_config_atop['maxsize'], default_atop_maxsize) + self.assertEqual(logrotate_config_atop['rotate'], default_atop_rotate) + self.assertEqual(logrotate_config_rsyslog['size'], default_rsyslog_size) + self.assertEqual(logrotate_config_rsyslog['rotate'], + default_rsyslog_rotate) + + def test_logs_atop_maxsize(self): + # test for maxsize option + self.cli_set(base_path + ['logrotate', 'atop', 'max-size', '50']) + self.cli_commit() + + # read the config file and check content + logrotate_config = logrotate_config_parse(logrotate_atop_file) + self.assertEqual(logrotate_config['maxsize'], '50M') + + def test_logs_atop_rotate(self): + # test for rotate option + self.cli_set(base_path + ['logrotate', 'atop', 'rotate', '50']) + self.cli_commit() + + # read the config file and check content + logrotate_config = logrotate_config_parse(logrotate_atop_file) + self.assertEqual(logrotate_config['rotate'], '50') + + def test_logs_rsyslog_size(self): + # test for size option + self.cli_set(base_path + ['logrotate', 'messages', 'max-size', '50']) + self.cli_commit() + + # read the config file and check content + logrotate_config = logrotate_config_parse(logrotate_rsyslog_file) + self.assertEqual(logrotate_config['size'], '50M') + + def test_logs_rsyslog_rotate(self): + # test for rotate option + self.cli_set(base_path + ['logrotate', 'messages', 'rotate', '50']) + self.cli_commit() + + # read the config file and check content + logrotate_config = logrotate_config_parse(logrotate_rsyslog_file) + self.assertEqual(logrotate_config['rotate'], '50') + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_ntp.py b/smoketest/scripts/cli/test_system_ntp.py index e8cc64463..e2821687c 100755 --- a/smoketest/scripts/cli/test_system_ntp.py +++ b/smoketest/scripts/cli/test_system_ntp.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 @@ -14,7 +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 re import unittest from base_vyostest_shim import VyOSUnitTestSHIM @@ -29,17 +28,14 @@ PROCESS_NAME = 'ntpd' NTP_CONF = '/run/ntpd/ntpd.conf' base_path = ['system', 'ntp'] -def get_config_value(key): - tmp = read_file(NTP_CONF) - tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) - # remove possible trailing whitespaces - return [item.strip() for item in tmp] - class TestSystemNTP(VyOSUnitTestSHIM.TestCase): - def setUp(self): + @classmethod + def setUpClass(cls): + super(TestSystemNTP, cls).setUpClass() + # ensure we can also run this test on a live system - so lets clean # out the current configuration :) - self.cli_delete(base_path) + cls.cli_delete(cls, base_path) def tearDown(self): self.cli_delete(base_path) @@ -47,35 +43,38 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase): self.assertFalse(process_named_running(PROCESS_NAME)) - def test_ntp_options(self): + 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'] - ntp_pool = 'pool.vyos.io' + pools = ['pool.vyos.io'] for server in servers: for option in options: self.cli_set(base_path + ['server', server, option]) # Test NTP pool - self.cli_set(base_path + ['server', ntp_pool, 'pool']) + for pool in pools: + self.cli_set(base_path + ['server', pool, 'pool']) # commit changes self.cli_commit() # Check generated configuration - tmp = get_config_value('server') - for server in servers: - test = f'{server} iburst ' + ' '.join(options) - self.assertTrue(test in tmp) + 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) - tmp = get_config_value('pool') - self.assertTrue(f'{ntp_pool} iburst' in tmp) + for server in servers: + self.assertIn(f'server {server} iburst ' + ' '.join(options), config) - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) + for pool in pools: + self.assertIn(f'pool {pool} iburst', config) - def test_ntp_clients(self): + def test_02_ntp_clients(self): # Test the allowed-networks statement listen_address = ['127.0.0.1', '::1'] for listen in listen_address: @@ -96,23 +95,18 @@ class TestSystemNTP(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Check generated client address configuration + config = read_file(NTP_CONF) + self.assertIn('restrict default ignore', config) + for network in networks: network_address = address_from_cidr(network) network_netmask = netmask_from_cidr(network) - - tmp = get_config_value(f'restrict {network_address}')[0] - test = f'mask {network_netmask} nomodify notrap nopeer' - self.assertTrue(tmp in test) + self.assertIn(f'restrict {network_address} mask {network_netmask} nomodify notrap nopeer', config) # Check listen address - tmp = get_config_value('interface') - test = ['ignore wildcard'] + self.assertIn('interface ignore wildcard', config) for listen in listen_address: - test.append(f'listen {listen}') - self.assertEqual(tmp, test) - - # Check for running process - self.assertTrue(process_named_running(PROCESS_NAME)) + self.assertIn(f'interface listen {listen}', config) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py index c710aec6e..8a6514d57 100755 --- a/smoketest/scripts/cli/test_vpn_ipsec.py +++ b/smoketest/scripts/cli/test_vpn_ipsec.py @@ -28,6 +28,7 @@ vti_path = ['interfaces', 'vti'] nhrp_path = ['protocols', 'nhrp'] base_path = ['vpn', 'ipsec'] +charon_file = '/etc/strongswan.d/charon.conf' dhcp_waiting_file = '/tmp/ipsec_dhcp_waiting' swanctl_file = '/etc/swanctl/swanctl.conf' @@ -111,9 +112,21 @@ rgiyCHemtMepq57Pl1Nmj49eEA== """ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): - def setUp(self): - self.cli_set(base_path + ['interface', f'{interface}.{vif}']) + @classmethod + def setUpClass(cls): + super(TestVPNIPsec, 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, base_path + ['interface', f'{interface}.{vif}']) + @classmethod + def tearDownClass(cls): + super(TestVPNIPsec, cls).tearDownClass() + cls.cli_delete(cls, base_path + ['interface', f'{interface}.{vif}']) + + def setUp(self): # Set IKE/ESP Groups self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'encryption', 'aes128']) self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'hash', 'sha1']) @@ -127,7 +140,6 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): self.cli_delete(base_path) self.cli_delete(tunnel_path) - self.cli_delete(ethernet_path) self.cli_commit() # Check for no longer running process @@ -158,8 +170,14 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): # Site to site local_address = '192.0.2.10' + priority = '20' + life_bytes = '100000' + life_packets = '2000000' peer_base_path = base_path + ['site-to-site', 'peer', peer_ip] + self.cli_set(base_path + ['esp-group', esp_group, 'life-bytes', life_bytes]) + self.cli_set(base_path + ['esp-group', esp_group, 'life-packets', life_packets]) + self.cli_set(peer_base_path + ['authentication', 'mode', 'pre-shared-secret']) self.cli_set(peer_base_path + ['authentication', 'pre-shared-secret', secret]) self.cli_set(peer_base_path + ['ike-group', ike_group]) @@ -173,6 +191,10 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): self.cli_set(peer_base_path + ['tunnel', '1', 'remote', 'prefix', '172.17.11.0/24']) self.cli_set(peer_base_path + ['tunnel', '1', 'remote', 'port', '443']) + self.cli_set(peer_base_path + ['tunnel', '2', 'local', 'prefix', '10.1.0.0/16']) + self.cli_set(peer_base_path + ['tunnel', '2', 'remote', 'prefix', '10.2.0.0/16']) + self.cli_set(peer_base_path + ['tunnel', '2', 'priority', priority]) + self.cli_commit() # Verify strongSwan configuration @@ -180,6 +202,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): swanctl_conf_lines = [ f'version = 2', f'auth = psk', + f'life_bytes = {life_bytes}', + f'life_packets = {life_packets}', f'rekey_time = 28800s', # default value f'proposals = aes128-sha1-modp1024', f'esp_proposals = aes128-sha1-modp1024', @@ -187,8 +211,15 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): f'local_addrs = {local_address} # dhcp:no', f'remote_addrs = {peer_ip}', f'mode = tunnel', + f'peer_{peer_ip.replace(".","-")}_tunnel_1', f'local_ts = 172.16.10.0/24[tcp/443],172.16.11.0/24[tcp/443]', - f'remote_ts = 172.17.10.0/24[tcp/443],172.17.11.0/24[tcp/443]' + f'remote_ts = 172.17.10.0/24[tcp/443],172.17.11.0/24[tcp/443]', + f'mode = tunnel', + f'peer_{peer_ip.replace(".","-")}_tunnel_2', + f'local_ts = 10.1.0.0/16', + f'remote_ts = 10.2.0.0/16', + f'priority = {priority}', + f'mode = tunnel', ] for line in swanctl_conf_lines: self.assertIn(line, swanctl_conf) @@ -213,6 +244,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): peer_base_path = base_path + ['site-to-site', 'peer', peer_ip] self.cli_set(peer_base_path + ['authentication', 'mode', 'pre-shared-secret']) self.cli_set(peer_base_path + ['authentication', 'pre-shared-secret', secret]) + self.cli_set(peer_base_path + ['connection-type', 'none']) self.cli_set(peer_base_path + ['ike-group', ike_group]) self.cli_set(peer_base_path + ['default-esp-group', esp_group]) self.cli_set(peer_base_path + ['local-address', local_address]) @@ -241,6 +273,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): f'mode = tunnel', f'local_ts = 172.16.10.0/24,172.16.11.0/24', f'remote_ts = 172.17.10.0/24,172.17.11.0/24', + f'start_action = none', f'if_id_in = {if_id}', # will be 11 for vti10 - shifted by one f'if_id_out = {if_id}', f'updown = "/etc/ipsec.d/vti-up-down {vti}"' @@ -392,5 +425,75 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): # There is only one VTI test so no need to delete this globally in tearDown() self.cli_delete(vti_path) + + def test_06_flex_vpn_vips(self): + local_address = '192.0.2.5' + local_id = 'vyos-r1' + remote_id = 'vyos-r2' + peer_base_path = base_path + ['site-to-site', 'peer', peer_ip] + + self.cli_set(tunnel_path + ['tun1', 'encapsulation', 'gre']) + self.cli_set(tunnel_path + ['tun1', 'source-address', local_address]) + + self.cli_set(base_path + ['interface', interface]) + self.cli_set(base_path + ['options', 'flexvpn']) + self.cli_set(base_path + ['options', 'interface', 'tun1']) + self.cli_set(base_path + ['ike-group', ike_group, 'ikev2-reauth', 'no']) + self.cli_set(base_path + ['ike-group', ike_group, 'key-exchange', 'ikev2']) + + self.cli_set(peer_base_path + ['authentication', 'id', local_id]) + self.cli_set(peer_base_path + ['authentication', 'mode', 'pre-shared-secret']) + self.cli_set(peer_base_path + ['authentication', 'pre-shared-secret', secret]) + self.cli_set(peer_base_path + ['authentication', 'remote-id', remote_id]) + self.cli_set(peer_base_path + ['connection-type', 'initiate']) + self.cli_set(peer_base_path + ['ike-group', ike_group]) + self.cli_set(peer_base_path + ['default-esp-group', esp_group]) + self.cli_set(peer_base_path + ['local-address', local_address]) + self.cli_set(peer_base_path + ['tunnel', '1', 'protocol', 'gre']) + + self.cli_set(peer_base_path + ['virtual-address', '203.0.113.55']) + self.cli_set(peer_base_path + ['virtual-address', '203.0.113.56']) + + self.cli_commit() + + # Verify strongSwan configuration + swanctl_conf = read_file(swanctl_file) + swanctl_conf_lines = [ + f'version = 2', + f'vips = 203.0.113.55, 203.0.113.56', + f'life_time = 3600s', # default value + f'local_addrs = {local_address} # dhcp:no', + f'remote_addrs = {peer_ip}', + f'peer_{peer_ip.replace(".","-")}_tunnel_1', + f'mode = tunnel', + ] + + for line in swanctl_conf_lines: + self.assertIn(line, swanctl_conf) + + swanctl_secrets_lines = [ + f'id-local = {local_address} # dhcp:no', + f'id-remote = {peer_ip}', + f'id-localid = {local_id}', + f'id-remoteid = {remote_id}', + f'secret = "{secret}"', + ] + + for line in swanctl_secrets_lines: + self.assertIn(line, swanctl_conf) + + # Verify charon configuration + charon_conf = read_file(charon_file) + charon_conf_lines = [ + f'# Cisco FlexVPN', + f'cisco_flexvpn = yes', + f'install_virtual_ip = yes', + f'install_virtual_ip_on = tun1', + ] + + for line in charon_conf_lines: + self.assertIn(line, charon_conf) + + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_vpn_openconnect.py b/smoketest/scripts/cli/test_vpn_openconnect.py index b0e859b5c..bda279342 100755 --- a/smoketest/scripts/cli/test_vpn_openconnect.py +++ b/smoketest/scripts/cli/test_vpn_openconnect.py @@ -24,8 +24,27 @@ OCSERV_CONF = '/run/ocserv/ocserv.conf' base_path = ['vpn', 'openconnect'] pki_path = ['pki'] -cert_data = 'MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIwWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIxMDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu+JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3LftzngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93+dm/LDnp7C0=' -key_data = 'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww' + +cert_data = """ +MIICFDCCAbugAwIBAgIUfMbIsB/ozMXijYgUYG80T1ry+mcwCgYIKoZIzj0EAwIw +WTELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNv +bWUtQ2l0eTENMAsGA1UECgwEVnlPUzESMBAGA1UEAwwJVnlPUyBUZXN0MB4XDTIx +MDcyMDEyNDUxMloXDTI2MDcxOTEyNDUxMlowWTELMAkGA1UEBhMCR0IxEzARBgNV +BAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlP +UzESMBAGA1UEAwwJVnlPUyBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +01HrLcNttqq4/PtoMua8rMWEkOdBu7vP94xzDO7A8C92ls1v86eePy4QllKCzIw3 +QxBIoCuH2peGRfWgPRdFsKNhMF8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdDgQWBBSu ++JnU5ZC4mkuEpqg2+Mk4K79oeDAKBggqhkjOPQQDAgNHADBEAiBEFdzQ/Bc3Lftz +ngrY605UhA6UprHhAogKgROv7iR4QgIgEFUxTtW3xXJcnUPWhhUFhyZoqfn8dE93 ++dm/LDnp7C0= +""" + +key_data = """ +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPLpD0Ohhoq0g4nhx +2KMIuze7ucKUt/lBEB2wc03IxXyhRANCAATTUestw222qrj8+2gy5rysxYSQ50G7 +u8/3jHMM7sDwL3aWzW/zp54/LhCWUoLMjDdDEEigK4fal4ZF9aA9F0Ww +""" class TestVpnOpenconnect(VyOSUnitTestSHIM.TestCase): def tearDown(self): @@ -37,18 +56,21 @@ class TestVpnOpenconnect(VyOSUnitTestSHIM.TestCase): def test_vpn(self): user = 'vyos_user' password = 'vyos_pass' + otp = '37500000026900000000200000000000' + self.cli_delete(pki_path) self.cli_delete(base_path) - self.cli_set(pki_path + ['ca', 'openconnect', 'certificate', cert_data]) - self.cli_set(pki_path + ['certificate', 'openconnect', 'certificate', cert_data]) - self.cli_set(pki_path + ['certificate', 'openconnect', 'private', 'key', key_data]) + self.cli_set(pki_path + ['ca', 'openconnect', 'certificate', cert_data.replace('\n','')]) + self.cli_set(pki_path + ['certificate', 'openconnect', 'certificate', cert_data.replace('\n','')]) + self.cli_set(pki_path + ['certificate', 'openconnect', 'private', 'key', key_data.replace('\n','')]) - self.cli_set(base_path + ["authentication", "local-users", "username", user, "password", password]) - self.cli_set(base_path + ["authentication", "mode", "local"]) - self.cli_set(base_path + ["network-settings", "client-ip-settings", "subnet", "192.0.2.0/24"]) - self.cli_set(base_path + ["ssl", "ca-certificate", 'openconnect']) - self.cli_set(base_path + ["ssl", "certificate", 'openconnect']) + self.cli_set(base_path + ['authentication', 'local-users', 'username', user, 'password', password]) + self.cli_set(base_path + ['authentication', 'local-users', 'username', user, 'otp', 'key', otp]) + self.cli_set(base_path + ['authentication', 'mode', 'local', 'password-otp']) + self.cli_set(base_path + ['network-settings', 'client-ip-settings', 'subnet', '192.0.2.0/24']) + self.cli_set(base_path + ['ssl', 'ca-certificate', 'openconnect']) + self.cli_set(base_path + ['ssl', 'certificate', 'openconnect']) self.cli_commit() diff --git a/smoketest/scripts/cli/test_vrf.py b/smoketest/scripts/cli/test_vrf.py index 5ffa9c086..176c095fb 100755 --- a/smoketest/scripts/cli/test_vrf.py +++ b/smoketest/scripts/cli/test_vrf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -25,9 +25,10 @@ from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSessionError from vyos.ifconfig import Interface from vyos.ifconfig import Section -from vyos.template import is_ipv6 +from vyos.template import is_ipv4 from vyos.util import cmd from vyos.util import read_file +from vyos.util import get_interface_config from vyos.validate import is_intf_addr_assigned base_path = ['vrf'] @@ -48,7 +49,7 @@ class VRFTest(VyOSUnitTestSHIM.TestCase): if not '.' in tmp: cls._interfaces.append(tmp) # call base-classes classmethod - super(cls, cls).setUpClass() + super(VRFTest, cls).setUpClass() def tearDown(self): # delete all VRFs @@ -105,10 +106,13 @@ class VRFTest(VyOSUnitTestSHIM.TestCase): frrconfig = self.getFRRconfig(f'vrf {vrf}') self.assertIn(f' vni {table}', frrconfig) + tmp = get_interface_config(vrf) + self.assertEqual(int(table), tmp['linkinfo']['info_data']['table']) + # Increment table ID for the next run table = str(int(table) + 1) - def test_vrf_loopback_ips(self): + def test_vrf_loopbacks_ips(self): table = '2000' for vrf in vrfs: base = base_path + ['name', vrf] @@ -119,10 +123,16 @@ class VRFTest(VyOSUnitTestSHIM.TestCase): self.cli_commit() # Verify VRF configuration + loopbacks = ['127.0.0.1', '::1'] for vrf in vrfs: - self.assertTrue(vrf in interfaces()) - self.assertTrue(is_intf_addr_assigned(vrf, '127.0.0.1')) - self.assertTrue(is_intf_addr_assigned(vrf, '::1')) + # Ensure VRF was created + self.assertIn(vrf, interfaces()) + # Verify IP forwarding is 1 (enabled) + self.assertEqual(read_file(f'/proc/sys/net/ipv4/conf/{vrf}/forwarding'), '1') + self.assertEqual(read_file(f'/proc/sys/net/ipv6/conf/{vrf}/forwarding'), '1') + # Test for proper loopback IP assignment + for addr in loopbacks: + self.assertTrue(is_intf_addr_assigned(vrf, addr)) def test_vrf_bind_all(self): table = '2000' @@ -174,11 +184,11 @@ class VRFTest(VyOSUnitTestSHIM.TestCase): # commit changes self.cli_commit() - # Verify & cleanup + # Verify VRF assignmant for interface in self._interfaces: - # os.readlink resolves to: '../../../../../virtual/net/foovrf' - tmp = os.readlink(f'/sys/class/net/{interface}/master').split('/')[-1] - self.assertEqual(tmp, vrf) + tmp = get_interface_config(interface) + self.assertEqual(vrf, tmp['master']) + # cleanup section = Section.section(interface) self.cli_delete(['interfaces', section, interface, 'vrf']) @@ -220,5 +230,66 @@ class VRFTest(VyOSUnitTestSHIM.TestCase): # Increment table ID for the next run table = str(int(table) + 1) + def test_vrf_link_local_ip_addresses(self): + # Testcase for issue T4331 + table = '100' + vrf = 'orange' + interface = 'dum9998' + addresses = ['192.0.2.1/26', '2001:db8:9998::1/64', 'fe80::1/64'] + + for address in addresses: + self.cli_set(['interfaces', 'dummy', interface, 'address', address]) + + # Create dummy interfaces + self.cli_commit() + + # ... and verify IP addresses got assigned + for address in addresses: + self.assertTrue(is_intf_addr_assigned(interface, address)) + + # Move interface to VRF + self.cli_set(base_path + ['name', vrf, 'table', table]) + self.cli_set(['interfaces', 'dummy', interface, 'vrf', vrf]) + + # Apply VRF config + self.cli_commit() + # Ensure VRF got created + self.assertIn(vrf, interfaces()) + # ... and IP addresses are still assigned + for address in addresses: + self.assertTrue(is_intf_addr_assigned(interface, address)) + # Verify VRF table ID + tmp = get_interface_config(vrf) + self.assertEqual(int(table), tmp['linkinfo']['info_data']['table']) + + # Verify interface is assigned to VRF + tmp = get_interface_config(interface) + self.assertEqual(vrf, tmp['master']) + + # Delete Interface + self.cli_delete(['interfaces', 'dummy', interface]) + self.cli_commit() + + def test_vrf_disable_forwarding(self): + table = '2000' + for vrf in vrfs: + base = base_path + ['name', vrf] + self.cli_set(base + ['table', table]) + self.cli_set(base + ['ip', 'disable-forwarding']) + self.cli_set(base + ['ipv6', 'disable-forwarding']) + table = str(int(table) + 1) + + # commit changes + self.cli_commit() + + # Verify VRF configuration + loopbacks = ['127.0.0.1', '::1'] + for vrf in vrfs: + # Ensure VRF was created + self.assertIn(vrf, interfaces()) + # Verify IP forwarding is 0 (disabled) + self.assertEqual(read_file(f'/proc/sys/net/ipv4/conf/{vrf}/forwarding'), '0') + self.assertEqual(read_file(f'/proc/sys/net/ipv6/conf/{vrf}/forwarding'), '0') + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_zone_policy.py b/smoketest/scripts/cli/test_zone_policy.py new file mode 100755 index 000000000..2c580e2f1 --- /dev/null +++ b/smoketest/scripts/cli/test_zone_policy.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021-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 +# 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 base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.util import cmd + +class TestZonePolicy(VyOSUnitTestSHIM.TestCase): + @classmethod + def setUpClass(cls): + super(TestZonePolicy, cls).setUpClass() + cls.cli_set(cls, ['firewall', 'name', 'smoketest', 'default-action', 'drop']) + + @classmethod + def tearDownClass(cls): + cls.cli_delete(cls, ['firewall']) + super(TestZonePolicy, cls).tearDownClass() + + def tearDown(self): + self.cli_delete(['zone-policy']) + self.cli_commit() + + def test_basic_zone(self): + self.cli_set(['zone-policy', 'zone', 'smoketest-eth0', 'interface', 'eth0']) + self.cli_set(['zone-policy', 'zone', 'smoketest-eth0', 'from', 'smoketest-local', 'firewall', 'name', 'smoketest']) + self.cli_set(['zone-policy', 'zone', 'smoketest-local', 'local-zone']) + self.cli_set(['zone-policy', 'zone', 'smoketest-local', 'from', 'smoketest-eth0', 'firewall', 'name', 'smoketest']) + + self.cli_commit() + + nftables_search = [ + ['chain VZONE_smoketest-eth0'], + ['chain VZONE_smoketest-local_IN'], + ['chain VZONE_smoketest-local_OUT'], + ['oifname { "eth0" }', 'jump VZONE_smoketest-eth0'], + ['jump VZONE_smoketest-local_IN'], + ['jump VZONE_smoketest-local_OUT'], + ['iifname { "eth0" }', 'jump NAME_smoketest'], + ['oifname { "eth0" }', 'jump NAME_smoketest'] + ] + + nftables_output = cmd('sudo nft list table ip filter') + + for search in nftables_search: + matched = False + for line in nftables_output.split("\n"): + if all(item in line for item in search): + matched = True + break + self.assertTrue(matched) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/src/conf_mode/arp.py b/src/conf_mode/arp.py index aac07bd80..1cd8f5451 100755 --- a/src/conf_mode/arp.py +++ b/src/conf_mode/arp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -13,92 +13,62 @@ # # 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 sys -import os -import re -import syslog as sl +from sys import exit from vyos.config import Config +from vyos.configdict import node_changed from vyos.util import call from vyos import ConfigError - from vyos import airbag airbag.enable() -arp_cmd = '/usr/sbin/arp' - -def get_config(): - c = Config() - if not c.exists('protocols static arp'): - return None - - c.set_level('protocols static') - config_data = {} - - for ip_addr in c.list_nodes('arp'): - config_data.update( - { - ip_addr : c.return_value('arp ' + ip_addr + ' hwaddr') - } - ) +def get_config(config=None): + if config: + conf = config + else: + conf = Config() - return config_data + base = ['protocols', 'static', 'arp'] + arp = conf.get_config_dict(base, get_first_key=True) -def generate(c): - c_eff = Config() - c_eff.set_level('protocols static') - c_eff_cnf = {} - for ip_addr in c_eff.list_effective_nodes('arp'): - c_eff_cnf.update( - { - ip_addr : c_eff.return_effective_value('arp ' + ip_addr + ' hwaddr') - } - ) + if 'interface' in arp: + for interface in arp['interface']: + tmp = node_changed(conf, base + ['interface', interface, 'address'], recursive=True) + if tmp: arp['interface'][interface].update({'address_old' : tmp}) - config_data = { - 'remove' : [], - 'update' : {} - } - ### removal - if c == None: - for ip_addr in c_eff_cnf: - config_data['remove'].append(ip_addr) - else: - for ip_addr in c_eff_cnf: - if not ip_addr in c or c[ip_addr] == None: - config_data['remove'].append(ip_addr) + return arp - ### add/update - if c != None: - for ip_addr in c: - if not ip_addr in c_eff_cnf: - config_data['update'][ip_addr] = c[ip_addr] - if ip_addr in c_eff_cnf: - if c[ip_addr] != c_eff_cnf[ip_addr] and c[ip_addr] != None: - config_data['update'][ip_addr] = c[ip_addr] +def verify(arp): + pass - return config_data +def generate(arp): + pass -def apply(c): - for ip_addr in c['remove']: - sl.syslog(sl.LOG_NOTICE, "arp -d " + ip_addr) - call(f'{arp_cmd} -d {ip_addr} >/dev/null 2>&1') +def apply(arp): + if not arp: + return None - for ip_addr in c['update']: - sl.syslog(sl.LOG_NOTICE, "arp -s " + ip_addr + " " + c['update'][ip_addr]) - updated = c['update'][ip_addr] - call(f'{arp_cmd} -s {ip_addr} {updated}') + if 'interface' in arp: + for interface, interface_config in arp['interface'].items(): + # Delete old static ARP assignments first + if 'address_old' in interface_config: + for address in interface_config['address_old']: + call(f'ip neigh del {address} dev {interface}') + # Add new static ARP entries to interface + if 'address' not in interface_config: + continue + for address, address_config in interface_config['address'].items(): + mac = address_config['mac'] + call(f'ip neigh add {address} lladdr {mac} dev {interface}') if __name__ == '__main__': - try: - c = get_config() - ## syntax verification is done via cli - config = generate(c) - apply(config) - except ConfigError as e: - print(e) - sys.exit(1) + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + exit(1) diff --git a/src/conf_mode/bcast_relay.py b/src/conf_mode/bcast_relay.py index d93a2a8f4..39a2971ce 100755 --- a/src/conf_mode/bcast_relay.py +++ b/src/conf_mode/bcast_relay.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2017-2020 VyOS maintainers and contributors +# Copyright (C) 2017-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 @@ -78,7 +78,7 @@ def generate(relay): continue config['instance'] = instance - render(config_file_base + instance, 'bcast-relay/udp-broadcast-relay.tmpl', + render(config_file_base + instance, 'bcast-relay/udp-broadcast-relay.j2', config) return None diff --git a/src/conf_mode/conntrack.py b/src/conf_mode/conntrack.py index 68877f794..82289526f 100755 --- a/src/conf_mode/conntrack.py +++ b/src/conf_mode/conntrack.py @@ -15,11 +15,14 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os +import re from sys import exit from vyos.config import Config from vyos.configdict import dict_merge +from vyos.firewall import find_nftables_rule +from vyos.firewall import remove_nftables_rule from vyos.util import cmd from vyos.util import run from vyos.util import process_named_running @@ -32,6 +35,7 @@ airbag.enable() conntrack_config = r'/etc/modprobe.d/vyatta_nf_conntrack.conf' sysctl_file = r'/run/sysctl/10-vyos-conntrack.conf' +nftables_ct_file = r'/run/nftables-ct.conf' # Every ALG (Application Layer Gateway) consists of either a Kernel Object # also called a Kernel Module/Driver or some rules present in iptables @@ -43,8 +47,8 @@ module_map = { 'ko' : ['nf_nat_h323', 'nf_conntrack_h323'], }, 'nfs' : { - 'iptables' : ['VYATTA_CT_HELPER --table raw --proto tcp --dport 111 --jump CT --helper rpc', - 'VYATTA_CT_HELPER --table raw --proto udp --dport 111 --jump CT --helper rpc'], + 'nftables' : ['ct helper set "rpc_tcp" tcp dport "{111}" return', + 'ct helper set "rpc_udp" udp dport "{111}" return'] }, 'pptp' : { 'ko' : ['nf_nat_pptp', 'nf_conntrack_pptp'], @@ -53,9 +57,7 @@ module_map = { 'ko' : ['nf_nat_sip', 'nf_conntrack_sip'], }, 'sqlnet' : { - 'iptables' : ['VYATTA_CT_HELPER --table raw --proto tcp --dport 1521 --jump CT --helper tns', - 'VYATTA_CT_HELPER --table raw --proto tcp --dport 1525 --jump CT --helper tns', - 'VYATTA_CT_HELPER --table raw --proto tcp --dport 1536 --jump CT --helper tns'], + 'nftables' : ['ct helper set "tns_tcp" tcp dport "{1521,1525,1536}" return'] }, 'tftp' : { 'ko' : ['nf_nat_tftp', 'nf_conntrack_tftp'], @@ -80,19 +82,49 @@ def get_config(config=None): # We have gathered the dict representation of the CLI, but there are default # options which we need to update into the dictionary retrived. default_values = defaults(base) + # XXX: T2665: we can not safely rely on the defaults() when there are + # tagNodes in place, it is better to blend in the defaults manually. + if 'timeout' in default_values and 'custom' in default_values['timeout']: + del default_values['timeout']['custom'] conntrack = dict_merge(default_values, conntrack) return conntrack def verify(conntrack): + if dict_search('ignore.rule', conntrack) != None: + for rule, rule_config in conntrack['ignore']['rule'].items(): + if dict_search('destination.port', rule_config) or \ + dict_search('source.port', rule_config): + if 'protocol' not in rule_config or rule_config['protocol'] not in ['tcp', 'udp']: + raise ConfigError(f'Port requires tcp or udp as protocol in rule {rule}') + return None def generate(conntrack): - render(conntrack_config, 'conntrack/vyos_nf_conntrack.conf.tmpl', conntrack) - render(sysctl_file, 'conntrack/sysctl.conf.tmpl', conntrack) + render(conntrack_config, 'conntrack/vyos_nf_conntrack.conf.j2', conntrack) + render(sysctl_file, 'conntrack/sysctl.conf.j2', conntrack) + render(nftables_ct_file, 'conntrack/nftables-ct.j2', conntrack) + + # dry-run newly generated configuration + tmp = run(f'nft -c -f {nftables_ct_file}') + if tmp > 0: + if os.path.exists(nftables_ct_file): + os.unlink(nftables_ct_file) + raise ConfigError('Configuration file errors encountered!') return None +def find_nftables_ct_rule(rule): + helper_search = re.search('ct helper set "(\w+)"', rule) + if helper_search: + rule = helper_search[1] + return find_nftables_rule('raw', 'VYOS_CT_HELPER', [rule]) + +def find_remove_rule(rule): + handle = find_nftables_ct_rule(rule) + if handle: + remove_nftables_rule('raw', 'VYOS_CT_HELPER', handle) + def apply(conntrack): # Depending on the enable/disable state of the ALG (Application Layer Gateway) # modules we need to either insmod or rmmod the helpers. @@ -103,20 +135,20 @@ def apply(conntrack): # Only remove the module if it's loaded if os.path.exists(f'/sys/module/{mod}'): cmd(f'rmmod {mod}') - if 'iptables' in module_config: - for rule in module_config['iptables']: - # Only install iptables rule if it does not exist - tmp = run(f'iptables --check {rule}') - if tmp == 0: cmd(f'iptables --delete {rule}') + if 'nftables' in module_config: + for rule in module_config['nftables']: + find_remove_rule(rule) else: if 'ko' in module_config: for mod in module_config['ko']: cmd(f'modprobe {mod}') - if 'iptables' in module_config: - for rule in module_config['iptables']: - # Only install iptables rule if it does not exist - tmp = run(f'iptables --check {rule}') - if tmp > 0: cmd(f'iptables --insert {rule}') + if 'nftables' in module_config: + for rule in module_config['nftables']: + if not find_nftables_ct_rule(rule): + cmd(f'nft insert rule ip raw VYOS_CT_HELPER {rule}') + + # Load new nftables ruleset + cmd(f'nft -f {nftables_ct_file}') if process_named_running('conntrackd'): # Reload conntrack-sync daemon to fetch new sysctl values diff --git a/src/conf_mode/conntrack_sync.py b/src/conf_mode/conntrack_sync.py index f82a077e6..c4b2bb488 100755 --- a/src/conf_mode/conntrack_sync.py +++ b/src/conf_mode/conntrack_sync.py @@ -36,7 +36,7 @@ airbag.enable() config_file = '/run/conntrackd/conntrackd.conf' def resync_vrrp(): - tmp = run('/usr/libexec/vyos/conf_mode/vrrp.py') + tmp = run('/usr/libexec/vyos/conf_mode/high-availability.py') if tmp > 0: print('ERROR: error restarting VRRP daemon!') @@ -93,9 +93,9 @@ def verify(conntrack): raise ConfigError('Can not configure expect-sync "all" with other protocols!') if 'listen_address' in conntrack: - address = conntrack['listen_address'] - if not is_addr_assigned(address): - raise ConfigError(f'Specified listen-address {address} not assigned to any interface!') + for address in conntrack['listen_address']: + if not is_addr_assigned(address): + raise ConfigError(f'Specified listen-address {address} not assigned to any interface!') vrrp_group = dict_search('failover_mechanism.vrrp.sync_group', conntrack) if vrrp_group == None: @@ -111,11 +111,12 @@ def generate(conntrack): os.unlink(config_file) return None - render(config_file, 'conntrackd/conntrackd.conf.tmpl', conntrack) + render(config_file, 'conntrackd/conntrackd.conf.j2', conntrack) return None def apply(conntrack): + systemd_service = 'conntrackd.service' if not conntrack: # Failover mechanism daemon should be indicated that it no longer needs # to execute conntrackd actions on transition. This is only required @@ -123,7 +124,7 @@ def apply(conntrack): if process_named_running('conntrackd'): resync_vrrp() - call('systemctl stop conntrackd.service') + call(f'systemctl stop {systemd_service}') return None # Failover mechanism daemon should be indicated that it needs to execute @@ -132,7 +133,7 @@ def apply(conntrack): if not process_named_running('conntrackd'): resync_vrrp() - call('systemctl restart conntrackd.service') + call(f'systemctl reload-or-restart {systemd_service}') return None if __name__ == '__main__': diff --git a/src/conf_mode/containers.py b/src/conf_mode/container.py index 2e14e0b25..2110fd9e0 100755 --- a/src/conf_mode/containers.py +++ b/src/conf_mode/container.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -15,20 +15,19 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -import json from ipaddress import ip_address from ipaddress import ip_network from time import sleep from json import dumps as json_write +from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge from vyos.configdict import node_changed from vyos.util import call from vyos.util import cmd from vyos.util import run -from vyos.util import read_file from vyos.util import write_file from vyos.template import inc_ip from vyos.template import is_ipv4 @@ -42,6 +41,20 @@ airbag.enable() config_containers_registry = '/etc/containers/registries.conf' config_containers_storage = '/etc/containers/storage.conf' +def _run_rerun(container_cmd): + counter = 0 + while True: + if counter >= 10: + break + try: + _cmd(container_cmd) + break + except: + counter = counter +1 + sleep(0.5) + + return None + def _cmd(command): if os.path.exists('/tmp/vyos.container.debug'): print(command) @@ -77,10 +90,10 @@ def get_config(config=None): container['name'][name] = dict_merge(default_values, container['name'][name]) # Delete container network, delete containers - tmp = node_changed(conf, ['container', 'network']) + tmp = node_changed(conf, base + ['container', 'network']) if tmp: container.update({'network_remove' : tmp}) - tmp = node_changed(conf, ['container', 'name']) + tmp = node_changed(conf, base + ['container', 'name']) if tmp: container.update({'container_remove' : tmp}) return container @@ -93,6 +106,26 @@ def verify(container): # Add new container if 'name' in container: for name, container_config in container['name'].items(): + # Container image is a mandatory option + if 'image' not in container_config: + raise ConfigError(f'Container image for "{name}" is mandatory!') + + # Check if requested container image exists locally. If it does not + # exist locally - inform the user. This is required as there is a + # shared container image storage accross all VyOS images. A user can + # delete a container image from the system, boot into another version + # of VyOS and then it would fail to boot. This is to prevent any + # configuration error when container images are deleted from the + # global storage. A per image local storage would be a super waste + # of diskspace as there will be a full copy (up tu several GB/image) + # on upgrade. This is the "cheapest" and fastest solution in terms + # of image upgrade and deletion. + image = container_config['image'] + if run(f'podman image exists {image}') != 0: + Warning(f'Image "{image}" used in contianer "{name}" does not exist '\ + f'locally. Please use "add container image {image}" to add it '\ + f'to the system! Container "{name}" will not be started!') + if 'network' in container_config: if len(container_config['network']) > 1: raise ConfigError(f'Only one network can be specified for container "{name}"!') @@ -122,6 +155,18 @@ def verify(container): raise ConfigError(f'IP address "{address}" can not be used for a container, '\ 'reserved for the container engine!') + if 'device' in container_config: + for dev, dev_config in container_config['device'].items(): + if 'source' not in dev_config: + raise ConfigError(f'Device "{dev}" has no source path configured!') + + if 'destination' not in dev_config: + raise ConfigError(f'Device "{dev}" has no destination path configured!') + + source = dev_config['source'] + if not os.path.exists(source): + raise ConfigError(f'Device "{dev}" source path "{source}" does not exist!') + if 'environment' in container_config: for var, cfg in container_config['environment'].items(): if 'value' not in cfg: @@ -139,10 +184,6 @@ def verify(container): if not os.path.exists(source): raise ConfigError(f'Volume "{volume}" source path "{source}" does not exist!') - # Container image is a mandatory option - if 'image' not in container_config: - raise ConfigError(f'Container image for "{name}" is mandatory!') - # If 'allow-host-networks' or 'network' not set. if 'allow_host_networks' not in container_config and 'network' not in container_config: raise ConfigError(f'Must either set "network" or "allow-host-networks" for container "{name}"!') @@ -182,6 +223,10 @@ def verify(container): def generate(container): # bail out early - looks like removal from running config if not container: + if os.path.exists(config_containers_registry): + os.unlink(config_containers_registry) + if os.path.exists(config_containers_storage): + os.unlink(config_containers_storage) return None if 'network' in container: @@ -215,8 +260,8 @@ def generate(container): write_file(f'/etc/cni/net.d/{network}.conflist', json_write(tmp, indent=2)) - render(config_containers_registry, 'containers/registry.tmpl', container) - render(config_containers_storage, 'containers/storage.tmpl', container) + render(config_containers_registry, 'container/registries.conf.j2', container) + render(config_containers_storage, 'container/storage.conf.j2', container) return None @@ -240,6 +285,11 @@ def apply(container): for name, container_config in container['name'].items(): image = container_config['image'] + if run(f'podman image exists {image}') != 0: + # container image does not exist locally - user already got + # informed by a WARNING in verfiy() - bail out early + continue + if 'disable' in container_config: # check if there is a container by that name running tmp = _cmd('podman ps -a --format "{{.Names}}"') @@ -251,13 +301,6 @@ def apply(container): memory = container_config['memory'] restart = container_config['restart'] - # Check if requested container image exists locally. If it does not, we - # pull it. print() is the best way to have a good response from the - # polling process to the user to display progress. If the image exists - # locally, a user can update it running `update container image <name>` - tmp = run(f'podman image exists {image}') - if tmp != 0: print(os.system(f'podman pull {image}')) - # Add capability options. Should be in uppercase cap_add = '' if 'cap_add' in container_config: @@ -266,6 +309,14 @@ def apply(container): c = c.replace('-', '_') cap_add += f' --cap-add={c}' + # Add a host device to the container /dev/x:/dev/x + device = '' + if 'device' in container_config: + for dev, dev_config in container_config['device'].items(): + source_dev = dev_config['source'] + dest_dev = dev_config['destination'] + device += f' --device={source_dev}:{dest_dev}' + # Check/set environment options "-e foo=bar" env_opt = '' if 'environment' in container_config: @@ -296,9 +347,9 @@ def apply(container): container_base_cmd = f'podman run --detach --interactive --tty --replace {cap_add} ' \ f'--memory {memory}m --memory-swap 0 --restart {restart} ' \ - f'--name {name} {port} {volume} {env_opt}' + f'--name {name} {device} {port} {volume} {env_opt}' if 'allow_host_networks' in container_config: - _cmd(f'{container_base_cmd} --net host {image}') + _run_rerun(f'{container_base_cmd} --net host {image}') else: for network in container_config['network']: ipparam = '' @@ -306,16 +357,7 @@ def apply(container): address = container_config['network'][network]['address'] ipparam = f'--ip {address}' - counter = 0 - while True: - if counter >= 10: - break - try: - _cmd(f'{container_base_cmd} --net {network} {ipparam} {image}') - break - except: - counter = counter +1 - sleep(0.5) + _run_rerun(f'{container_base_cmd} --net {network} {ipparam} {image}') return None diff --git a/src/conf_mode/dhcp_relay.py b/src/conf_mode/dhcp_relay.py index 6352e0b4a..4de2ca2f3 100755 --- a/src/conf_mode/dhcp_relay.py +++ b/src/conf_mode/dhcp_relay.py @@ -66,18 +66,19 @@ def generate(relay): if not relay: return None - render(config_file, 'dhcp-relay/dhcrelay.conf.tmpl', relay) + render(config_file, 'dhcp-relay/dhcrelay.conf.j2', relay) return None def apply(relay): # bail out early - looks like removal from running config + service_name = 'isc-dhcp-relay.service' if not relay: - call('systemctl stop isc-dhcp-relay.service') + call(f'systemctl stop {service_name}') if os.path.exists(config_file): os.unlink(config_file) return None - call('systemctl restart isc-dhcp-relay.service') + call(f'systemctl restart {service_name}') return None diff --git a/src/conf_mode/dhcp_server.py b/src/conf_mode/dhcp_server.py index a8cef5ebf..52b682d6d 100755 --- a/src/conf_mode/dhcp_server.py +++ b/src/conf_mode/dhcp_server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2021 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -109,7 +109,7 @@ def get_config(config=None): if not conf.exists(base): return None - dhcp = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + dhcp = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) # T2665: defaults include lease time per TAG node which need to be added to # individual subnet definitions default_values = defaults(base + ['shared-network-name', 'subnet']) @@ -286,7 +286,7 @@ def generate(dhcp): # Please see: https://phabricator.vyos.net/T1129 for quoting of the raw # parameters we can pass to ISC DHCPd tmp_file = '/tmp/dhcpd.conf' - render(tmp_file, 'dhcp-server/dhcpd.conf.tmpl', dhcp, + render(tmp_file, 'dhcp-server/dhcpd.conf.j2', dhcp, formater=lambda _: _.replace(""", '"')) # XXX: as we have the ability for a user to pass in "raw" options via VyOS # CLI (see T3544) we now ask ISC dhcpd to test the newly rendered @@ -299,7 +299,7 @@ def generate(dhcp): # Now that we know that the newly rendered configuration is "good" we can # render the "real" configuration - render(config_file, 'dhcp-server/dhcpd.conf.tmpl', dhcp, + render(config_file, 'dhcp-server/dhcpd.conf.j2', dhcp, formater=lambda _: _.replace(""", '"')) return None diff --git a/src/conf_mode/dhcpv6_relay.py b/src/conf_mode/dhcpv6_relay.py index aea2c3b73..c1bd51f62 100755 --- a/src/conf_mode/dhcpv6_relay.py +++ b/src/conf_mode/dhcpv6_relay.py @@ -82,19 +82,20 @@ def generate(relay): if not relay: return None - render(config_file, 'dhcp-relay/dhcrelay6.conf.tmpl', relay) + render(config_file, 'dhcp-relay/dhcrelay6.conf.j2', relay) return None def apply(relay): # bail out early - looks like removal from running config + service_name = 'isc-dhcp-relay6.service' if not relay: # DHCPv6 relay support is removed in the commit - call('systemctl stop isc-dhcp-relay6.service') + call(f'systemctl stop {service_name}') if os.path.exists(config_file): os.unlink(config_file) return None - call('systemctl restart isc-dhcp-relay6.service') + call(f'systemctl restart {service_name}') return None diff --git a/src/conf_mode/dhcpv6_server.py b/src/conf_mode/dhcpv6_server.py index e6a2e4486..078ff327c 100755 --- a/src/conf_mode/dhcpv6_server.py +++ b/src/conf_mode/dhcpv6_server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -41,7 +41,9 @@ def get_config(config=None): if not conf.exists(base): return None - dhcpv6 = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + dhcpv6 = conf.get_config_dict(base, key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True) return dhcpv6 def verify(dhcpv6): @@ -51,7 +53,7 @@ def verify(dhcpv6): # If DHCP is enabled we need one share-network if 'shared_network_name' not in dhcpv6: - raise ConfigError('No DHCPv6 shared networks configured. At least\n' \ + raise ConfigError('No DHCPv6 shared networks configured. At least '\ 'one DHCPv6 shared network must be configured.') # Inspect shared-network/subnet @@ -60,8 +62,9 @@ def verify(dhcpv6): for network, network_config in dhcpv6['shared_network_name'].items(): # A shared-network requires a subnet definition if 'subnet' not in network_config: - raise ConfigError(f'No DHCPv6 lease subnets configured for "{network}". At least one\n' \ - 'lease subnet must be configured for each shared network!') + raise ConfigError(f'No DHCPv6 lease subnets configured for "{network}". '\ + 'At least one lease subnet must be configured for '\ + 'each shared network!') for subnet, subnet_config in network_config['subnet'].items(): if 'address_range' in subnet_config: @@ -83,20 +86,20 @@ def verify(dhcpv6): # Stop address must be greater or equal to start address if not ip_address(stop) >= ip_address(start): - raise ConfigError(f'address-range stop address "{stop}" must be greater or equal\n' \ + raise ConfigError(f'address-range stop address "{stop}" must be greater then or equal ' \ f'to the range start address "{start}"!') # DHCPv6 range start address must be unique - two ranges can't # start with the same address - makes no sense if start in range6_start: - raise ConfigError(f'Conflicting DHCPv6 lease range:\n' \ + raise ConfigError(f'Conflicting DHCPv6 lease range: '\ f'Pool start address "{start}" defined multipe times!') range6_start.append(start) # DHCPv6 range stop address must be unique - two ranges can't # end with the same address - makes no sense if stop in range6_stop: - raise ConfigError(f'Conflicting DHCPv6 lease range:\n' \ + raise ConfigError(f'Conflicting DHCPv6 lease range: '\ f'Pool stop address "{stop}" defined multipe times!') range6_stop.append(stop) @@ -112,7 +115,7 @@ def verify(dhcpv6): for prefix, prefix_config in subnet_config['prefix_delegation']['start'].items(): if 'stop' not in prefix_config: - raise ConfigError(f'Stop address of delegated IPv6 prefix range "{prefix}"\n' + raise ConfigError(f'Stop address of delegated IPv6 prefix range "{prefix}" '\ f'must be configured') if 'prefix_length' not in prefix_config: @@ -126,6 +129,10 @@ def verify(dhcpv6): if ip_address(mapping_config['ipv6_address']) not in ip_network(subnet): raise ConfigError(f'static-mapping address for mapping "{mapping}" is not in subnet "{subnet}"!') + if 'vendor_option' in subnet_config: + if len(dict_search('vendor_option.cisco.tftp_server', subnet_config)) > 2: + raise ConfigError(f'No more then two Cisco tftp-servers should be defined for subnet "{subnet}"!') + # Subnets must be unique if subnet in subnets: raise ConfigError(f'DHCPv6 subnets must be unique! Subnet {subnet} defined multiple times!') @@ -149,8 +156,8 @@ def verify(dhcpv6): raise ConfigError('DHCPv6 conflicting subnet ranges: {0} overlaps {1}'.format(net, net2)) if not listen_ok: - raise ConfigError('None of the DHCPv6 subnets are connected to a subnet6 on\n' \ - 'this machine. At least one subnet6 must be connected such that\n' \ + raise ConfigError('None of the DHCPv6 subnets are connected to a subnet6 on '\ + 'this machine. At least one subnet6 must be connected such that '\ 'DHCPv6 listens on an interface!') @@ -161,20 +168,20 @@ def generate(dhcpv6): if not dhcpv6 or 'disable' in dhcpv6: return None - render(config_file, 'dhcp-server/dhcpdv6.conf.tmpl', dhcpv6) + render(config_file, 'dhcp-server/dhcpdv6.conf.j2', dhcpv6) return None def apply(dhcpv6): # bail out early - looks like removal from running config + service_name = 'isc-dhcp-server6.service' if not dhcpv6 or 'disable' in dhcpv6: # DHCP server is removed in the commit - call('systemctl stop isc-dhcp-server6.service') + call(f'systemctl stop {service_name}') if os.path.exists(config_file): os.unlink(config_file) - return None - call('systemctl restart isc-dhcp-server6.service') + call(f'systemctl restart {service_name}') return None if __name__ == '__main__': diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py index 06366362a..f1c2d1f43 100755 --- a/src/conf_mode/dns_forwarding.py +++ b/src/conf_mode/dns_forwarding.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -16,7 +16,9 @@ import os +from netifaces import interfaces from sys import exit +from glob import glob from vyos.config import Config from vyos.configdict import dict_merge @@ -50,10 +52,12 @@ def get_config(config=None): if not conf.exists(base): return None - dns = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + dns = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) # We have gathered the dict representation of the CLI, but there are default - # options which we need to update into the dictionary retrived. + # options which we need to update into the dictionary retrieved. default_values = defaults(base) + # T2665 due to how defaults under tag nodes work, we must clear these out before we merge + del default_values['authoritative_domain'] dns = dict_merge(default_values, dns) # some additions to the default dictionary @@ -62,9 +66,182 @@ def get_config(config=None): if conf.exists(base_nameservers): dns.update({'system_name_server': conf.return_values(base_nameservers)}) - base_nameservers_dhcp = ['system', 'name-servers-dhcp'] - if conf.exists(base_nameservers_dhcp): - dns.update({'system_name_server_dhcp': conf.return_values(base_nameservers_dhcp)}) + if 'authoritative_domain' in dns: + dns['authoritative_zones'] = [] + dns['authoritative_zone_errors'] = [] + for node in dns['authoritative_domain']: + zonedata = dns['authoritative_domain'][node] + if ('disable' in zonedata) or (not 'records' in zonedata): + continue + zone = { + 'name': node, + 'file': "{}/zone.{}.conf".format(pdns_rec_run_dir, node), + 'records': [], + } + + recorddata = zonedata['records'] + + for rtype in [ 'a', 'aaaa', 'cname', 'mx', 'ptr', 'txt', 'spf', 'srv', 'naptr' ]: + if rtype not in recorddata: + continue + for subnode in recorddata[rtype]: + if 'disable' in recorddata[rtype][subnode]: + continue + + rdata = recorddata[rtype][subnode] + + if rtype in [ 'a', 'aaaa' ]: + rdefaults = defaults(base + ['authoritative-domain', 'records', rtype]) # T2665 + rdata = dict_merge(rdefaults, rdata) + + if not 'address' in rdata: + dns['authoritative_zone_errors'].append('{}.{}: at least one address is required'.format(subnode, node)) + continue + + for address in rdata['address']: + zone['records'].append({ + 'name': subnode, + 'type': rtype.upper(), + 'ttl': rdata['ttl'], + 'value': address + }) + elif rtype in ['cname', 'ptr']: + rdefaults = defaults(base + ['authoritative-domain', 'records', rtype]) # T2665 + rdata = dict_merge(rdefaults, rdata) + + if not 'target' in rdata: + dns['authoritative_zone_errors'].append('{}.{}: target is required'.format(subnode, node)) + continue + + zone['records'].append({ + 'name': subnode, + 'type': rtype.upper(), + 'ttl': rdata['ttl'], + 'value': '{}.'.format(rdata['target']) + }) + elif rtype == 'mx': + rdefaults = defaults(base + ['authoritative-domain', 'records', rtype]) # T2665 + del rdefaults['server'] + rdata = dict_merge(rdefaults, rdata) + + if not 'server' in rdata: + dns['authoritative_zone_errors'].append('{}.{}: at least one server is required'.format(subnode, node)) + continue + + for servername in rdata['server']: + serverdata = rdata['server'][servername] + serverdefaults = defaults(base + ['authoritative-domain', 'records', rtype, 'server']) # T2665 + serverdata = dict_merge(serverdefaults, serverdata) + zone['records'].append({ + 'name': subnode, + 'type': rtype.upper(), + 'ttl': rdata['ttl'], + 'value': '{} {}.'.format(serverdata['priority'], servername) + }) + elif rtype == 'txt': + rdefaults = defaults(base + ['authoritative-domain', 'records', rtype]) # T2665 + rdata = dict_merge(rdefaults, rdata) + + if not 'value' in rdata: + dns['authoritative_zone_errors'].append('{}.{}: at least one value is required'.format(subnode, node)) + continue + + for value in rdata['value']: + zone['records'].append({ + 'name': subnode, + 'type': rtype.upper(), + 'ttl': rdata['ttl'], + 'value': "\"{}\"".format(value.replace("\"", "\\\"")) + }) + elif rtype == 'spf': + rdefaults = defaults(base + ['authoritative-domain', 'records', rtype]) # T2665 + rdata = dict_merge(rdefaults, rdata) + + if not 'value' in rdata: + dns['authoritative_zone_errors'].append('{}.{}: value is required'.format(subnode, node)) + continue + + zone['records'].append({ + 'name': subnode, + 'type': rtype.upper(), + 'ttl': rdata['ttl'], + 'value': '"{}"'.format(rdata['value'].replace("\"", "\\\"")) + }) + elif rtype == 'srv': + rdefaults = defaults(base + ['authoritative-domain', 'records', rtype]) # T2665 + del rdefaults['entry'] + rdata = dict_merge(rdefaults, rdata) + + if not 'entry' in rdata: + dns['authoritative_zone_errors'].append('{}.{}: at least one entry is required'.format(subnode, node)) + continue + + for entryno in rdata['entry']: + entrydata = rdata['entry'][entryno] + entrydefaults = defaults(base + ['authoritative-domain', 'records', rtype, 'entry']) # T2665 + entrydata = dict_merge(entrydefaults, entrydata) + + if not 'hostname' in entrydata: + dns['authoritative_zone_errors'].append('{}.{}: hostname is required for entry {}'.format(subnode, node, entryno)) + continue + + if not 'port' in entrydata: + dns['authoritative_zone_errors'].append('{}.{}: port is required for entry {}'.format(subnode, node, entryno)) + continue + + zone['records'].append({ + 'name': subnode, + 'type': rtype.upper(), + 'ttl': rdata['ttl'], + 'value': '{} {} {} {}.'.format(entrydata['priority'], entrydata['weight'], entrydata['port'], entrydata['hostname']) + }) + elif rtype == 'naptr': + rdefaults = defaults(base + ['authoritative-domain', 'records', rtype]) # T2665 + del rdefaults['rule'] + rdata = dict_merge(rdefaults, rdata) + + + if not 'rule' in rdata: + dns['authoritative_zone_errors'].append('{}.{}: at least one rule is required'.format(subnode, node)) + continue + + for ruleno in rdata['rule']: + ruledata = rdata['rule'][ruleno] + ruledefaults = defaults(base + ['authoritative-domain', 'records', rtype, 'rule']) # T2665 + ruledata = dict_merge(ruledefaults, ruledata) + flags = "" + if 'lookup-srv' in ruledata: + flags += "S" + if 'lookup-a' in ruledata: + flags += "A" + if 'resolve-uri' in ruledata: + flags += "U" + if 'protocol-specific' in ruledata: + flags += "P" + + if 'order' in ruledata: + order = ruledata['order'] + else: + order = ruleno + + if 'regexp' in ruledata: + regexp= ruledata['regexp'].replace("\"", "\\\"") + else: + regexp = '' + + if ruledata['replacement']: + replacement = '{}.'.format(ruledata['replacement']) + else: + replacement = '' + + zone['records'].append({ + 'name': subnode, + 'type': rtype.upper(), + 'ttl': rdata['ttl'], + 'value': '{} {} "{}" "{}" "{}" {}'.format(order, ruledata['preference'], flags, ruledata['service'], regexp, replacement) + }) + + dns['authoritative_zones'].append(zone) return dns @@ -86,10 +263,14 @@ def verify(dns): if 'server' not in dns['domain'][domain]: raise ConfigError(f'No server configured for domain {domain}!') + if ('authoritative_zone_errors' in dns) and dns['authoritative_zone_errors']: + for error in dns['authoritative_zone_errors']: + print(error) + raise ConfigError('Invalid authoritative records have been defined') + if 'system' in dns: - if not ('system_name_server' in dns or 'system_name_server_dhcp' in dns): - print("Warning: No 'system name-server' or 'system " \ - "name-servers-dhcp' configured") + if not 'system_name_server' in dns: + print('Warning: No "system name-server" configured') return None @@ -98,12 +279,21 @@ def generate(dns): if not dns: return None - render(pdns_rec_config_file, 'dns-forwarding/recursor.conf.tmpl', + render(pdns_rec_config_file, 'dns-forwarding/recursor.conf.j2', dns, user=pdns_rec_user, group=pdns_rec_group) - render(pdns_rec_lua_conf_file, 'dns-forwarding/recursor.conf.lua.tmpl', + render(pdns_rec_lua_conf_file, 'dns-forwarding/recursor.conf.lua.j2', dns, user=pdns_rec_user, group=pdns_rec_group) + for zone_filename in glob(f'{pdns_rec_run_dir}/zone.*.conf'): + os.unlink(zone_filename) + + if 'authoritative_zones' in dns: + for zone in dns['authoritative_zones']: + render(zone['file'], 'dns-forwarding/recursor.zone.conf.j2', + zone, user=pdns_rec_user, group=pdns_rec_group) + + # if vyos-hostsd didn't create its files yet, create them (empty) for file in [pdns_rec_hostsd_lua_conf_file, pdns_rec_hostsd_zones_file]: with open(file, 'a'): @@ -119,6 +309,9 @@ def apply(dns): if os.path.isfile(pdns_rec_config_file): os.unlink(pdns_rec_config_file) + + for zone_filename in glob(f'{pdns_rec_run_dir}/zone.*.conf'): + os.unlink(zone_filename) else: ### first apply vyos-hostsd config hc = hostsd_client() @@ -142,10 +335,15 @@ def apply(dns): hc.delete_name_server_tags_recursor(['system']) # add dhcp nameserver tags for configured interfaces - if 'system_name_server_dhcp' in dns: - for interface in dns['system_name_server_dhcp']: - hc.add_name_server_tags_recursor(['dhcp-' + interface, - 'dhcpv6-' + interface ]) + if 'system_name_server' in dns: + for interface in dns['system_name_server']: + # system_name_server key contains both IP addresses and interface + # names (DHCP) to use DNS servers. We need to check if the + # value is an interface name - only if this is the case, add the + # interface based DNS forwarder. + if interface in interfaces(): + hc.add_name_server_tags_recursor(['dhcp-' + interface, + 'dhcpv6-' + interface ]) # hostsd will generate the forward-zones file # the list and keys() are required as get returns a dict, not list @@ -153,6 +351,12 @@ def apply(dns): if 'domain' in dns: hc.add_forward_zones(dns['domain']) + # hostsd generates NTAs for the authoritative zones + # the list and keys() are required as get returns a dict, not list + hc.delete_authoritative_zones(list(hc.get_authoritative_zones())) + if 'authoritative_zones' in dns: + hc.add_authoritative_zones(list(map(lambda zone: zone['name'], dns['authoritative_zones']))) + # call hostsd to generate forward-zones and its lua-config-file hc.apply() diff --git a/src/conf_mode/dynamic_dns.py b/src/conf_mode/dynamic_dns.py index a31e5ed75..06a2f7e15 100755 --- a/src/conf_mode/dynamic_dns.py +++ b/src/conf_mode/dynamic_dns.py @@ -131,7 +131,7 @@ def generate(dyndns): if not dyndns: return None - render(config_file, 'dynamic-dns/ddclient.conf.tmpl', dyndns) + render(config_file, 'dynamic-dns/ddclient.conf.j2', dyndns) return None def apply(dyndns): diff --git a/src/conf_mode/firewall-interface.py b/src/conf_mode/firewall-interface.py new file mode 100755 index 000000000..9a5d278e9 --- /dev/null +++ b/src/conf_mode/firewall-interface.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import re + +from sys import argv +from sys import exit + +from vyos.config import Config +from vyos.configdict import leaf_node_changed +from vyos.ifconfig import Section +from vyos.template import render +from vyos.util import cmd +from vyos.util import dict_search_args +from vyos.util import run +from vyos import ConfigError +from vyos import airbag +airbag.enable() + +NAME_PREFIX = 'NAME_' +NAME6_PREFIX = 'NAME6_' + +NFT_CHAINS = { + 'in': 'VYOS_FW_FORWARD', + 'out': 'VYOS_FW_FORWARD', + 'local': 'VYOS_FW_LOCAL' +} +NFT6_CHAINS = { + 'in': 'VYOS_FW6_FORWARD', + 'out': 'VYOS_FW6_FORWARD', + 'local': 'VYOS_FW6_LOCAL' +} + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + + ifname = argv[1] + ifpath = Section.get_config_path(ifname) + if_firewall_path = f'interfaces {ifpath} firewall' + + if_firewall = conf.get_config_dict(if_firewall_path, key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + + if_firewall['ifname'] = ifname + if_firewall['firewall'] = conf.get_config_dict(['firewall'], key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + + return if_firewall + +def verify(if_firewall): + # bail out early - looks like removal from running config + if not if_firewall: + return None + + for direction in ['in', 'out', 'local']: + if direction in if_firewall: + if 'name' in if_firewall[direction]: + name = if_firewall[direction]['name'] + + if 'name' not in if_firewall['firewall']: + raise ConfigError('Firewall name not configured') + + if name not in if_firewall['firewall']['name']: + raise ConfigError(f'Invalid firewall name "{name}"') + + if 'ipv6_name' in if_firewall[direction]: + name = if_firewall[direction]['ipv6_name'] + + if 'ipv6_name' not in if_firewall['firewall']: + raise ConfigError('Firewall ipv6-name not configured') + + if name not in if_firewall['firewall']['ipv6_name']: + raise ConfigError(f'Invalid firewall ipv6-name "{name}"') + + return None + +def generate(if_firewall): + return None + +def cleanup_rule(table, chain, prefix, ifname, new_name=None): + results = cmd(f'nft -a list chain {table} {chain}').split("\n") + retval = None + for line in results: + if f'{prefix}ifname "{ifname}"' in line: + if new_name and f'jump {new_name}' in line: + # new_name is used to clear rules for any previously referenced chains + # returns true when rule exists and doesn't need to be created + retval = True + continue + + handle_search = re.search('handle (\d+)', line) + if handle_search: + run(f'nft delete rule {table} {chain} handle {handle_search[1]}') + return retval + +def state_policy_handle(table, chain): + # Find any state-policy rule to ensure interface rules are only inserted afterwards + results = cmd(f'nft -a list chain {table} {chain}').split("\n") + for line in results: + if 'jump VYOS_STATE_POLICY' in line: + handle_search = re.search('handle (\d+)', line) + if handle_search: + return handle_search[1] + return None + +def apply(if_firewall): + ifname = if_firewall['ifname'] + + for direction in ['in', 'out', 'local']: + chain = NFT_CHAINS[direction] + ipv6_chain = NFT6_CHAINS[direction] + if_prefix = 'i' if direction in ['in', 'local'] else 'o' + + name = dict_search_args(if_firewall, direction, 'name') + if name: + rule_exists = cleanup_rule('ip filter', chain, if_prefix, ifname, f'{NAME_PREFIX}{name}') + + if not rule_exists: + rule_action = 'insert' + rule_prefix = '' + + handle = state_policy_handle('ip filter', chain) + if handle: + rule_action = 'add' + rule_prefix = f'position {handle}' + + run(f'nft {rule_action} rule ip filter {chain} {rule_prefix} {if_prefix}ifname {ifname} counter jump {NAME_PREFIX}{name}') + else: + cleanup_rule('ip filter', chain, if_prefix, ifname) + + ipv6_name = dict_search_args(if_firewall, direction, 'ipv6_name') + if ipv6_name: + rule_exists = cleanup_rule('ip6 filter', ipv6_chain, if_prefix, ifname, f'{NAME6_PREFIX}{ipv6_name}') + + if not rule_exists: + rule_action = 'insert' + rule_prefix = '' + + handle = state_policy_handle('ip6 filter', ipv6_chain) + if handle: + rule_action = 'add' + rule_prefix = f'position {handle}' + + run(f'nft {rule_action} rule ip6 filter {ipv6_chain} {rule_prefix} {if_prefix}ifname {ifname} counter jump {NAME6_PREFIX}{ipv6_name}') + else: + cleanup_rule('ip6 filter', ipv6_chain, if_prefix, ifname) + + 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/firewall.py b/src/conf_mode/firewall.py index 8e6ce5b14..6924bf555 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -15,51 +15,413 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os +import re +from glob import glob +from json import loads from sys import exit +from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge from vyos.configdict import node_changed -from vyos.configdict import leaf_node_changed +from vyos.configdiff import get_config_diff, Diff from vyos.template import render -from vyos.util import call +from vyos.util import cmd +from vyos.util import dict_search_args +from vyos.util import process_named_running +from vyos.util import run +from vyos.xml import defaults from vyos import ConfigError from vyos import airbag -from pprint import pprint airbag.enable() +policy_route_conf_script = '/usr/libexec/vyos/conf_mode/policy-route.py' -def get_config(config=None): +nftables_conf = '/run/nftables.conf' +nftables_defines_conf = '/run/nftables_defines.conf' + +sysfs_config = { + 'all_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_all', 'enable': '0', 'disable': '1'}, + 'broadcast_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts', 'enable': '0', 'disable': '1'}, + 'ip_src_route': {'sysfs': '/proc/sys/net/ipv4/conf/*/accept_source_route'}, + 'ipv6_receive_redirects': {'sysfs': '/proc/sys/net/ipv6/conf/*/accept_redirects'}, + 'ipv6_src_route': {'sysfs': '/proc/sys/net/ipv6/conf/*/accept_source_route', 'enable': '0', 'disable': '-1'}, + 'log_martians': {'sysfs': '/proc/sys/net/ipv4/conf/all/log_martians'}, + 'receive_redirects': {'sysfs': '/proc/sys/net/ipv4/conf/*/accept_redirects'}, + 'send_redirects': {'sysfs': '/proc/sys/net/ipv4/conf/*/send_redirects'}, + 'source_validation': {'sysfs': '/proc/sys/net/ipv4/conf/*/rp_filter', 'disable': '0', 'strict': '1', 'loose': '2'}, + 'syn_cookies': {'sysfs': '/proc/sys/net/ipv4/tcp_syncookies'}, + 'twa_hazards_protection': {'sysfs': '/proc/sys/net/ipv4/tcp_rfc1337'} +} + +NAME_PREFIX = 'NAME_' +NAME6_PREFIX = 'NAME6_' + +preserve_chains = [ + 'INPUT', + 'FORWARD', + 'OUTPUT', + 'VYOS_FW_FORWARD', + 'VYOS_FW_LOCAL', + 'VYOS_FW_OUTPUT', + 'VYOS_POST_FW', + 'VYOS_FRAG_MARK', + 'VYOS_FW6_FORWARD', + 'VYOS_FW6_LOCAL', + 'VYOS_FW6_OUTPUT', + 'VYOS_POST_FW6', + 'VYOS_FRAG6_MARK' +] + +nft_iface_chains = ['VYOS_FW_FORWARD', 'VYOS_FW_OUTPUT', 'VYOS_FW_LOCAL'] +nft6_iface_chains = ['VYOS_FW6_FORWARD', 'VYOS_FW6_OUTPUT', 'VYOS_FW6_LOCAL'] +valid_groups = [ + 'address_group', + 'network_group', + 'port_group' +] + +snmp_change_type = { + 'unknown': 0, + 'add': 1, + 'delete': 2, + 'change': 3 +} +snmp_event_source = 1 +snmp_trap_mib = 'VYATTA-TRAP-MIB' +snmp_trap_name = 'mgmtEventTrap' + +def get_firewall_interfaces(conf): + out = {} + interfaces = conf.get_config_dict(['interfaces'], key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + def find_interfaces(iftype_conf, output={}, prefix=''): + for ifname, if_conf in iftype_conf.items(): + if 'firewall' in if_conf: + output[prefix + ifname] = if_conf['firewall'] + for vif in ['vif', 'vif_s', 'vif_c']: + if vif in if_conf: + output.update(find_interfaces(if_conf[vif], output, f'{prefix}{ifname}.')) + return output + for iftype, iftype_conf in interfaces.items(): + out.update(find_interfaces(iftype_conf)) + return out + +def get_firewall_zones(conf): + used_v4 = [] + used_v6 = [] + zone_policy = conf.get_config_dict(['zone-policy'], key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + + if 'zone' in zone_policy: + for zone, zone_conf in zone_policy['zone'].items(): + if 'from' in zone_conf: + for from_zone, from_conf in zone_conf['from'].items(): + name = dict_search_args(from_conf, 'firewall', 'name') + if name: + used_v4.append(name) + + ipv6_name = dict_search_args(from_conf, 'firewall', 'ipv6_name') + if ipv6_name: + used_v6.append(ipv6_name) + + if 'intra_zone_filtering' in zone_conf: + name = dict_search_args(zone_conf, 'intra_zone_filtering', 'firewall', 'name') + if name: + used_v4.append(name) + + ipv6_name = dict_search_args(zone_conf, 'intra_zone_filtering', 'firewall', 'ipv6_name') + if ipv6_name: + used_v6.append(ipv6_name) + + return {'name': used_v4, 'ipv6_name': used_v6} + +def get_config(config=None): if config: conf = config else: conf = Config() - base = ['nfirewall'] + base = ['firewall'] + firewall = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) - pprint(firewall) + default_values = defaults(base) + firewall = dict_merge(default_values, firewall) + + firewall['policy_resync'] = bool('group' in firewall or node_changed(conf, base + ['group'])) + firewall['interfaces'] = get_firewall_interfaces(conf) + firewall['zone_policy'] = get_firewall_zones(conf) + + if 'config_trap' in firewall and firewall['config_trap'] == 'enable': + diff = get_config_diff(conf) + firewall['trap_diff'] = diff.get_child_nodes_diff_str(base) + firewall['trap_targets'] = conf.get_config_dict(['service', 'snmp', 'trap-target'], + key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + return firewall +def verify_rule(firewall, rule_conf, ipv6): + if 'action' not in rule_conf: + raise ConfigError('Rule action must be defined') + + if 'fragment' in rule_conf: + if {'match_frag', 'match_non_frag'} <= set(rule_conf['fragment']): + raise ConfigError('Cannot specify both "match-frag" and "match-non-frag"') + + if 'limit' in rule_conf: + if 'rate' in rule_conf['limit']: + rate_int = re.sub(r'\D', '', rule_conf['limit']['rate']) + if int(rate_int) < 1: + raise ConfigError('Limit rate integer cannot be less than 1') + + if 'ipsec' in rule_conf: + if {'match_ipsec', 'match_non_ipsec'} <= set(rule_conf['ipsec']): + raise ConfigError('Cannot specify both "match-ipsec" and "match-non-ipsec"') + + if 'recent' in rule_conf: + if not {'count', 'time'} <= set(rule_conf['recent']): + raise ConfigError('Recent "count" and "time" values must be defined') + + tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags') + if tcp_flags: + if dict_search_args(rule_conf, 'protocol') != 'tcp': + raise ConfigError('Protocol must be tcp when specifying tcp flags') + + not_flags = dict_search_args(rule_conf, 'tcp', 'flags', 'not') + if not_flags: + duplicates = [flag for flag in tcp_flags if flag in not_flags] + if duplicates: + raise ConfigError(f'Cannot match a tcp flag as set and not set') + + if 'protocol' in rule_conf: + if rule_conf['protocol'] == 'icmp' and ipv6: + raise ConfigError(f'Cannot match IPv4 ICMP protocol on IPv6, use ipv6-icmp') + if rule_conf['protocol'] == 'ipv6-icmp' and not ipv6: + raise ConfigError(f'Cannot match IPv6 ICMP protocol on IPv4, use icmp') + + for side in ['destination', 'source']: + if side in rule_conf: + side_conf = rule_conf[side] + + if 'group' in side_conf: + if {'address_group', 'network_group'} <= set(side_conf['group']): + raise ConfigError('Only one address-group or network-group can be specified') + + for group in valid_groups: + if group in side_conf['group']: + group_name = side_conf['group'][group] + + if group_name and group_name[0] == '!': + group_name = group_name[1:] + + fw_group = f'ipv6_{group}' if ipv6 and group in ['address_group', 'network_group'] else group + error_group = fw_group.replace("_", "-") + group_obj = dict_search_args(firewall, 'group', fw_group, group_name) + + if group_obj is None: + raise ConfigError(f'Invalid {error_group} "{group_name}" on firewall rule') + + if not group_obj: + Warning(f'{error_group} "{group_name}" has no members!') + + if 'port' in side_conf or dict_search_args(side_conf, 'group', 'port_group'): + if 'protocol' not in rule_conf: + raise ConfigError('Protocol must be defined if specifying a port or port-group') + + if rule_conf['protocol'] not in ['tcp', 'udp', 'tcp_udp']: + raise ConfigError('Protocol must be tcp, udp, or tcp_udp when specifying a port or port-group') + def verify(firewall): - # bail out early - looks like removal from running config - if not firewall: - return None + if 'config_trap' in firewall and firewall['config_trap'] == 'enable': + if not firewall['trap_targets']: + raise ConfigError(f'Firewall config-trap enabled but "service snmp trap-target" is not defined') + + for name in ['name', 'ipv6_name']: + if name in firewall: + for name_id, name_conf in firewall[name].items(): + if name_id in preserve_chains: + raise ConfigError(f'Firewall name "{name_id}" is reserved for VyOS') + + if name_id.startswith("VZONE"): + raise ConfigError(f'Firewall name "{name_id}" uses reserved prefix') + + if 'rule' in name_conf: + for rule_id, rule_conf in name_conf['rule'].items(): + verify_rule(firewall, rule_conf, name == 'ipv6_name') + + for ifname, if_firewall in firewall['interfaces'].items(): + for direction in ['in', 'out', 'local']: + name = dict_search_args(if_firewall, direction, 'name') + ipv6_name = dict_search_args(if_firewall, direction, 'ipv6_name') + + if name and dict_search_args(firewall, 'name', name) == None: + raise ConfigError(f'Firewall name "{name}" is still referenced on interface {ifname}') + + if ipv6_name and dict_search_args(firewall, 'ipv6_name', ipv6_name) == None: + raise ConfigError(f'Firewall ipv6-name "{ipv6_name}" is still referenced on interface {ifname}') + + for fw_name, used_names in firewall['zone_policy'].items(): + for name in used_names: + if dict_search_args(firewall, fw_name, name) == None: + raise ConfigError(f'Firewall {fw_name.replace("_", "-")} "{name}" is still referenced in zone-policy') return None +def cleanup_rule(table, jump_chain): + commands = [] + chains = nft_iface_chains if table == 'ip filter' else nft6_iface_chains + for chain in chains: + results = cmd(f'nft -a list chain {table} {chain}').split("\n") + for line in results: + if f'jump {jump_chain}' in line: + handle_search = re.search('handle (\d+)', line) + if handle_search: + commands.append(f'delete rule {table} {chain} handle {handle_search[1]}') + return commands + +def cleanup_commands(firewall): + commands = [] + commands_end = [] + for table in ['ip filter', 'ip6 filter']: + state_chain = 'VYOS_STATE_POLICY' if table == 'ip filter' else 'VYOS_STATE_POLICY6' + json_str = cmd(f'nft -j list table {table}') + obj = loads(json_str) + if 'nftables' not in obj: + continue + for item in obj['nftables']: + if 'chain' in item: + chain = item['chain']['name'] + if chain in ['VYOS_STATE_POLICY', 'VYOS_STATE_POLICY6']: + if 'state_policy' not in firewall: + commands.append(f'delete chain {table} {chain}') + else: + commands.append(f'flush chain {table} {chain}') + elif chain not in preserve_chains and not chain.startswith("VZONE"): + if table == 'ip filter' and dict_search_args(firewall, 'name', chain.replace(NAME_PREFIX, "", 1)) != None: + commands.append(f'flush chain {table} {chain}') + elif table == 'ip6 filter' and dict_search_args(firewall, 'ipv6_name', chain.replace(NAME6_PREFIX, "", 1)) != None: + commands.append(f'flush chain {table} {chain}') + else: + commands += cleanup_rule(table, chain) + commands.append(f'delete chain {table} {chain}') + elif 'rule' in item: + rule = item['rule'] + if rule['chain'] in ['VYOS_FW_FORWARD', 'VYOS_FW_OUTPUT', 'VYOS_FW_LOCAL', 'VYOS_FW6_FORWARD', 'VYOS_FW6_OUTPUT', 'VYOS_FW6_LOCAL']: + if 'expr' in rule and any([True for expr in rule['expr'] if dict_search_args(expr, 'jump', 'target') == state_chain]): + if 'state_policy' not in firewall: + chain = rule['chain'] + handle = rule['handle'] + commands.append(f'delete rule {table} {chain} handle {handle}') + elif 'set' in item: + set_name = item['set']['name'] + commands_end.append(f'delete set {table} {set_name}') + return commands + commands_end + def generate(firewall): - if not firewall: - return None + if not os.path.exists(nftables_conf): + firewall['first_install'] = True + else: + firewall['cleanup_commands'] = cleanup_commands(firewall) + render(nftables_conf, 'firewall/nftables.j2', firewall) + render(nftables_defines_conf, 'firewall/nftables-defines.j2', firewall) return None -def apply(firewall): - if not firewall: +def apply_sysfs(firewall): + for name, conf in sysfs_config.items(): + paths = glob(conf['sysfs']) + value = None + + if name in firewall: + conf_value = firewall[name] + + if conf_value in conf: + value = conf[conf_value] + elif conf_value == 'enable': + value = '1' + elif conf_value == 'disable': + value = '0' + + if value: + for path in paths: + with open(path, 'w') as f: + f.write(value) + +def post_apply_trap(firewall): + if 'first_install' in firewall: + return None + + if 'config_trap' not in firewall or firewall['config_trap'] != 'enable': return None + if not process_named_running('snmpd'): + return None + + trap_username = os.getlogin() + + for host, target_conf in firewall['trap_targets'].items(): + community = target_conf['community'] if 'community' in target_conf else 'public' + port = int(target_conf['port']) if 'port' in target_conf else 162 + + base_cmd = f'snmptrap -v2c -c {community} {host}:{port} 0 {snmp_trap_mib}::{snmp_trap_name} ' + + for change_type, changes in firewall['trap_diff'].items(): + for path_str, value in changes.items(): + objects = [ + f'mgmtEventUser s "{trap_username}"', + f'mgmtEventSource i {snmp_event_source}', + f'mgmtEventType i {snmp_change_type[change_type]}' + ] + + if change_type == 'add': + objects.append(f'mgmtEventCurrCfg s "{path_str} {value}"') + elif change_type == 'delete': + objects.append(f'mgmtEventPrevCfg s "{path_str} {value}"') + elif change_type == 'change': + objects.append(f'mgmtEventPrevCfg s "{path_str} {value[0]}"') + objects.append(f'mgmtEventCurrCfg s "{path_str} {value[1]}"') + + cmd(base_cmd + ' '.join(objects)) + +def state_policy_rule_exists(): + # Determine if state policy rules already exist in nft + search_str = cmd(f'nft list chain ip filter VYOS_FW_FORWARD') + return 'VYOS_STATE_POLICY' in search_str + +def resync_policy_route(): + # Update policy route as firewall groups were updated + tmp = run(policy_route_conf_script) + if tmp > 0: + Warning('Failed to re-apply policy route configuration!') + +def apply(firewall): + if 'first_install' in firewall: + run('nfct helper add rpc inet tcp') + run('nfct helper add rpc inet udp') + run('nfct helper add tns inet tcp') + + install_result = run(f'nft -f {nftables_conf}') + if install_result == 1: + raise ConfigError('Failed to apply firewall') + + if 'state_policy' in firewall and not state_policy_rule_exists(): + for chain in ['VYOS_FW_FORWARD', 'VYOS_FW_OUTPUT', 'VYOS_FW_LOCAL']: + cmd(f'nft insert rule ip filter {chain} jump VYOS_STATE_POLICY') + + for chain in ['VYOS_FW6_FORWARD', 'VYOS_FW6_OUTPUT', 'VYOS_FW6_LOCAL']: + cmd(f'nft insert rule ip6 filter {chain} jump VYOS_STATE_POLICY6') + + apply_sysfs(firewall) + + if firewall['policy_resync']: + resync_policy_route() + + post_apply_trap(firewall) + return None if __name__ == '__main__': diff --git a/src/conf_mode/flow_accounting_conf.py b/src/conf_mode/flow_accounting_conf.py index 0a4559ade..7750c1247 100755 --- a/src/conf_mode/flow_accounting_conf.py +++ b/src/conf_mode/flow_accounting_conf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -16,121 +16,87 @@ import os import re + from sys import exit import ipaddress from ipaddress import ip_address -from jinja2 import FileSystemLoader, Environment +from vyos.base import Warning +from vyos.config import Config +from vyos.configdict import dict_merge from vyos.ifconfig import Section from vyos.ifconfig import Interface -from vyos.config import Config -from vyos import ConfigError -from vyos.util import cmd from vyos.template import render - +from vyos.util import call +from vyos.util import cmd +from vyos.validate import is_addr_assigned +from vyos.xml import defaults +from vyos import ConfigError from vyos import airbag airbag.enable() -# default values -default_sflow_server_port = 6343 -default_netflow_server_port = 2055 -default_plugin_pipe_size = 10 -default_captured_packet_size = 128 -default_netflow_version = '9' -default_sflow_agentip = 'auto' -uacctd_conf_path = '/etc/pmacct/uacctd.conf' -iptables_nflog_table = 'raw' -iptables_nflog_chain = 'VYATTA_CT_PREROUTING_HOOK' -egress_iptables_nflog_table = 'mangle' -egress_iptables_nflog_chain = 'FORWARD' - -# helper functions -# check if node exists and return True if this is true -def _node_exists(path): - vyos_config = Config() - if vyos_config.exists(path): - return True - -# get sFlow agent-ip if agent-address is "auto" (default behaviour) -def _sflow_default_agentip(config): - # check if any of BGP, OSPF, OSPFv3 protocols are configured and use router-id from there - if config.exists('protocols bgp'): - bgp_router_id = config.return_value("protocols bgp {} parameters router-id".format(config.list_nodes('protocols bgp')[0])) - if bgp_router_id: - return bgp_router_id - if config.return_value('protocols ospf parameters router-id'): - return config.return_value('protocols ospf parameters router-id') - if config.return_value('protocols ospfv3 parameters router-id'): - return config.return_value('protocols ospfv3 parameters router-id') - - # if router-id was not found, use first available ip of any interface - for iface in Section.interfaces(): - for address in Interface(iface).get_addr(): - # return an IP, if this is not loopback - regex_filter = re.compile('^(?!(127)|(::1)|(fe80))(?P<ipaddr>[a-f\d\.:]+)/\d+$') - if regex_filter.search(address): - return regex_filter.search(address).group('ipaddr') - - # return nothing by default - return None - -# get iptables rule dict for chain in table -def _iptables_get_nflog(chain, table): +uacctd_conf_path = '/run/pmacct/uacctd.conf' +systemd_service = 'uacctd.service' +systemd_override = f'/etc/systemd/system/{systemd_service}.d/override.conf' +nftables_nflog_table = 'raw' +nftables_nflog_chain = 'VYOS_CT_PREROUTING_HOOK' +egress_nftables_nflog_table = 'inet mangle' +egress_nftables_nflog_chain = 'FORWARD' + +# get nftables rule dict for chain in table +def _nftables_get_nflog(chain, table): # define list with rules rules = [] # prepare regex for parsing rules - rule_pattern = "^-A (?P<rule_definition>{0} (\-i|\-o) (?P<interface>[\w\.\*\-]+).*--comment FLOW_ACCOUNTING_RULE.* -j NFLOG.*$)".format(chain) + rule_pattern = '[io]ifname "(?P<interface>[\w\.\*\-]+)".*handle (?P<handle>[\d]+)' rule_re = re.compile(rule_pattern) - for iptables_variant in ['iptables', 'ip6tables']: - # run iptables, save output and split it by lines - iptables_command = f'{iptables_variant} -t {table} -S {chain}' - tmp = cmd(iptables_command, message='Failed to get flows list') - - # parse each line and add information to list - for current_rule in tmp.splitlines(): - current_rule_parsed = rule_re.search(current_rule) - if current_rule_parsed: - rules.append({ 'interface': current_rule_parsed.groupdict()["interface"], 'iptables_variant': iptables_variant, 'table': table, 'rule_definition': current_rule_parsed.groupdict()["rule_definition"] }) + # run nftables, save output and split it by lines + nftables_command = f'nft -a list chain {table} {chain}' + tmp = cmd(nftables_command, message='Failed to get flows list') + # parse each line and add information to list + for current_rule in tmp.splitlines(): + if 'FLOW_ACCOUNTING_RULE' not in current_rule: + continue + current_rule_parsed = rule_re.search(current_rule) + if current_rule_parsed: + groups = current_rule_parsed.groupdict() + rules.append({ 'interface': groups["interface"], 'table': table, 'handle': groups["handle"] }) # return list with rules return rules -# modify iptables rules -def _iptables_config(configured_ifaces, direction): - # define list of iptables commands to modify settings - iptable_commands = [] - iptables_chain = iptables_nflog_chain - iptables_table = iptables_nflog_table +def _nftables_config(configured_ifaces, direction, length=None): + # define list of nftables commands to modify settings + nftable_commands = [] + nftables_chain = nftables_nflog_chain + nftables_table = nftables_nflog_table if direction == "egress": - iptables_chain = egress_iptables_nflog_chain - iptables_table = egress_iptables_nflog_table + nftables_chain = egress_nftables_nflog_chain + nftables_table = egress_nftables_nflog_table # prepare extended list with configured interfaces configured_ifaces_extended = [] for iface in configured_ifaces: - configured_ifaces_extended.append({ 'iface': iface, 'iptables_variant': 'iptables' }) - configured_ifaces_extended.append({ 'iface': iface, 'iptables_variant': 'ip6tables' }) + configured_ifaces_extended.append({ 'iface': iface }) - # get currently configured interfaces with iptables rules - active_nflog_rules = _iptables_get_nflog(iptables_chain, iptables_table) + # get currently configured interfaces with nftables rules + active_nflog_rules = _nftables_get_nflog(nftables_chain, nftables_table) # compare current active list with configured one and delete excessive interfaces, add missed active_nflog_ifaces = [] for rule in active_nflog_rules: - iptables = rule['iptables_variant'] interface = rule['interface'] if interface not in configured_ifaces: table = rule['table'] - rule = rule['rule_definition'] - iptable_commands.append(f'{iptables} -t {table} -D {rule}') + handle = rule['handle'] + nftable_commands.append(f'nft delete rule {table} {nftables_chain} handle {handle}') else: active_nflog_ifaces.append({ 'iface': interface, - 'iptables_variant': iptables, }) # do not create new rules for already configured interfaces @@ -141,244 +107,178 @@ def _iptables_config(configured_ifaces, direction): # create missed rules for iface_extended in configured_ifaces_extended: iface = iface_extended['iface'] - iptables = iface_extended['iptables_variant'] - iptables_op = "-i" - if direction == "egress": - iptables_op = "-o" - - rule_definition = f'{iptables_chain} {iptables_op} {iface} -m comment --comment FLOW_ACCOUNTING_RULE -j NFLOG --nflog-group 2 --nflog-size {default_captured_packet_size} --nflog-threshold 100' - iptable_commands.append(f'{iptables} -t {iptables_table} -I {rule_definition}') - - # change iptables - for command in iptable_commands: + iface_prefix = "o" if direction == "egress" else "i" + rule_definition = f'{iface_prefix}ifname "{iface}" counter log group 2 snaplen {length} queue-threshold 100 comment "FLOW_ACCOUNTING_RULE"' + nftable_commands.append(f'nft insert rule {nftables_table} {nftables_chain} {rule_definition}') + # Also add IPv6 ingres logging + if nftables_table == nftables_nflog_table: + nftable_commands.append(f'nft insert rule ip6 {nftables_table} {nftables_chain} {rule_definition}') + + # change nftables + for command in nftable_commands: cmd(command, raising=ConfigError) -def get_config(): - vc = Config() - vc.set_level('') - # Convert the VyOS config to an abstract internal representation - flow_config = { - 'flow-accounting-configured': vc.exists('system flow-accounting'), - 'buffer-size': vc.return_value('system flow-accounting buffer-size'), - 'enable-egress': _node_exists('system flow-accounting enable-egress'), - 'disable-imt': _node_exists('system flow-accounting disable-imt'), - 'syslog-facility': vc.return_value('system flow-accounting syslog-facility'), - 'interfaces': None, - 'sflow': { - 'configured': vc.exists('system flow-accounting sflow'), - 'agent-address': vc.return_value('system flow-accounting sflow agent-address'), - 'sampling-rate': vc.return_value('system flow-accounting sflow sampling-rate'), - 'servers': None - }, - 'netflow': { - 'configured': vc.exists('system flow-accounting netflow'), - 'engine-id': vc.return_value('system flow-accounting netflow engine-id'), - 'max-flows': vc.return_value('system flow-accounting netflow max-flows'), - 'sampling-rate': vc.return_value('system flow-accounting netflow sampling-rate'), - 'source-ip': vc.return_value('system flow-accounting netflow source-ip'), - 'version': vc.return_value('system flow-accounting netflow version'), - 'timeout': { - 'expint': vc.return_value('system flow-accounting netflow timeout expiry-interval'), - 'general': vc.return_value('system flow-accounting netflow timeout flow-generic'), - 'icmp': vc.return_value('system flow-accounting netflow timeout icmp'), - 'maxlife': vc.return_value('system flow-accounting netflow timeout max-active-life'), - 'tcp.fin': vc.return_value('system flow-accounting netflow timeout tcp-fin'), - 'tcp': vc.return_value('system flow-accounting netflow timeout tcp-generic'), - 'tcp.rst': vc.return_value('system flow-accounting netflow timeout tcp-rst'), - 'udp': vc.return_value('system flow-accounting netflow timeout udp') - }, - 'servers': None - } - } - - # get interfaces list - if vc.exists('system flow-accounting interface'): - flow_config['interfaces'] = vc.return_values('system flow-accounting interface') - - # get sFlow collectors list - if vc.exists('system flow-accounting sflow server'): - flow_config['sflow']['servers'] = [] - sflow_collectors = vc.list_nodes('system flow-accounting sflow server') - for collector in sflow_collectors: - port = default_sflow_server_port - if vc.return_value("system flow-accounting sflow server {} port".format(collector)): - port = vc.return_value("system flow-accounting sflow server {} port".format(collector)) - flow_config['sflow']['servers'].append({ 'address': collector, 'port': port }) - - # get NetFlow collectors list - if vc.exists('system flow-accounting netflow server'): - flow_config['netflow']['servers'] = [] - netflow_collectors = vc.list_nodes('system flow-accounting netflow server') - for collector in netflow_collectors: - port = default_netflow_server_port - if vc.return_value("system flow-accounting netflow server {} port".format(collector)): - port = vc.return_value("system flow-accounting netflow server {} port".format(collector)) - flow_config['netflow']['servers'].append({ 'address': collector, 'port': port }) - - # get sflow agent-id - if flow_config['sflow']['agent-address'] == None or flow_config['sflow']['agent-address'] == 'auto': - flow_config['sflow']['agent-address'] = _sflow_default_agentip(vc) - - # get NetFlow version - if not flow_config['netflow']['version']: - flow_config['netflow']['version'] = default_netflow_version - - # convert NetFlow engine-id format, if this is necessary - if flow_config['netflow']['engine-id'] and flow_config['netflow']['version'] == '5': - regex_filter = re.compile('^\d+$') - if regex_filter.search(flow_config['netflow']['engine-id']): - flow_config['netflow']['engine-id'] = "{}:0".format(flow_config['netflow']['engine-id']) - - # return dict with flow-accounting configuration - return flow_config - -def verify(config): - # Verify that configuration is valid - # skip all checks if flow-accounting was removed - if not config['flow-accounting-configured']: - return True +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + base = ['system', 'flow-accounting'] + if not conf.exists(base): + return None + + flow_accounting = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + default_values = defaults(base) + + # delete individual flow type default - should only be added if user uses + # this feature + for flow_type in ['sflow', 'netflow']: + if flow_type in default_values: + del default_values[flow_type] + flow_accounting = dict_merge(default_values, flow_accounting) + + for flow_type in ['sflow', 'netflow']: + if flow_type in flow_accounting: + default_values = defaults(base + [flow_type]) + # we need to merge individual server configurations + if 'server' in default_values: + del default_values['server'] + flow_accounting[flow_type] = dict_merge(default_values, flow_accounting[flow_type]) + + if 'server' in flow_accounting[flow_type]: + default_values = defaults(base + [flow_type, 'server']) + for server in flow_accounting[flow_type]['server']: + flow_accounting[flow_type]['server'][server] = dict_merge( + default_values,flow_accounting[flow_type]['server'][server]) + + return flow_accounting + +def verify(flow_config): + if not flow_config: + return None # check if at least one collector is enabled - if not (config['sflow']['configured'] or config['netflow']['configured'] or not config['disable-imt']): - raise ConfigError("You need to configure at least one sFlow or NetFlow protocol, or not set \"disable-imt\" for flow-accounting") + if 'sflow' not in flow_config and 'netflow' not in flow_config and 'disable_imt' in flow_config: + raise ConfigError('You need to configure at least sFlow or NetFlow, ' \ + 'or not set "disable-imt" for flow-accounting!') # Check if at least one interface is configured - if not config['interfaces']: - raise ConfigError("You need to configure at least one interface for flow-accounting") + if 'interface' not in flow_config: + raise ConfigError('Flow accounting requires at least one interface to ' \ + 'be configured!') # check that all configured interfaces exists in the system - for iface in config['interfaces']: - if not iface in Section.interfaces(): - # chnged from error to warning to allow adding dynamic interfaces and interface templates - # raise ConfigError("The {} interface is not presented in the system".format(iface)) - print("Warning: the {} interface is not presented in the system".format(iface)) + for interface in flow_config['interface']: + if interface not in Section.interfaces(): + # Changed from error to warning to allow adding dynamic interfaces + # and interface templates + Warning(f'Interface "{interface}" is not presented in the system') # check sFlow configuration - if config['sflow']['configured']: - # check if at least one sFlow collector is configured if sFlow configuration is presented - if not config['sflow']['servers']: - raise ConfigError("You need to configure at least one sFlow server") + if 'sflow' in flow_config: + # check if at least one sFlow collector is configured + if 'server' not in flow_config['sflow']: + raise ConfigError('You need to configure at least one sFlow server!') # check that all sFlow collectors use the same IP protocol version sflow_collector_ipver = None - for sflow_collector in config['sflow']['servers']: + for server in flow_config['sflow']['server']: if sflow_collector_ipver: - if sflow_collector_ipver != ip_address(sflow_collector['address']).version: + if sflow_collector_ipver != ip_address(server).version: raise ConfigError("All sFlow servers must use the same IP protocol") else: - sflow_collector_ipver = ip_address(sflow_collector['address']).version - + sflow_collector_ipver = ip_address(server).version # check agent-id for sFlow: we should avoid mixing IPv4 agent-id with IPv6 collectors and vice-versa - for sflow_collector in config['sflow']['servers']: - if ip_address(sflow_collector['address']).version != ip_address(config['sflow']['agent-address']).version: - raise ConfigError("Different IP address versions cannot be mixed in \"sflow agent-address\" and \"sflow server\". You need to set manually the same IP version for \"agent-address\" as for all sFlow servers") - - # check if configured sFlow agent-id exist in the system - agent_id_presented = None - for iface in Section.interfaces(): - for address in Interface(iface).get_addr(): - # check an IP, if this is not loopback - regex_filter = re.compile('^(?!(127)|(::1)|(fe80))(?P<ipaddr>[a-f\d\.:]+)/\d+$') - if regex_filter.search(address): - if regex_filter.search(address).group('ipaddr') == config['sflow']['agent-address']: - agent_id_presented = True - break - if not agent_id_presented: - raise ConfigError("Your \"sflow agent-address\" does not exist in the system") + for server in flow_config['sflow']['server']: + if 'agent_address' in flow_config['sflow']: + if ip_address(server).version != ip_address(flow_config['sflow']['agent_address']).version: + raise ConfigError('IPv4 and IPv6 addresses can not be mixed in "sflow agent-address" and "sflow '\ + 'server". You need to set the same IP version for both "agent-address" and '\ + 'all sFlow servers') + + if 'agent_address' in flow_config['sflow']: + tmp = flow_config['sflow']['agent_address'] + if not is_addr_assigned(tmp): + raise ConfigError(f'Configured "sflow agent-address {tmp}" does not exist in the system!') + + # Check if configured netflow source-address exist in the system + if 'source_address' in flow_config['sflow']: + if not is_addr_assigned(flow_config['sflow']['source_address']): + tmp = flow_config['sflow']['source_address'] + raise ConfigError(f'Configured "sflow source-address {tmp}" does not exist on the system!') # check NetFlow configuration - if config['netflow']['configured']: + if 'netflow' in flow_config: # check if at least one NetFlow collector is configured if NetFlow configuration is presented - if not config['netflow']['servers']: - raise ConfigError("You need to configure at least one NetFlow server") - - # check if configured netflow source-ip exist in the system - if config['netflow']['source-ip']: - source_ip_presented = None - for iface in Section.interfaces(): - for address in Interface(iface).get_addr(): - # check an IP - regex_filter = re.compile('^(?!(127)|(::1)|(fe80))(?P<ipaddr>[a-f\d\.:]+)/\d+$') - if regex_filter.search(address): - if regex_filter.search(address).group('ipaddr') == config['netflow']['source-ip']: - source_ip_presented = True - break - if not source_ip_presented: - print("Warning: your \"netflow source-ip\" does not exist in the system") - - # check if engine-id compatible with selected protocol version - if config['netflow']['engine-id']: + if 'server' not in flow_config['netflow']: + raise ConfigError('You need to configure at least one NetFlow server!') + + # Check if configured netflow source-address exist in the system + if 'source_address' in flow_config['netflow']: + if not is_addr_assigned(flow_config['netflow']['source_address']): + tmp = flow_config['netflow']['source_address'] + raise ConfigError(f'Configured "netflow source-address {tmp}" does not exist on the system!') + + # Check if engine-id compatible with selected protocol version + if 'engine_id' in flow_config['netflow']: v5_filter = '^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]):(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$' v9v10_filter = '^(\d|[1-9]\d{1,8}|[1-3]\d{9}|4[01]\d{8}|42[0-8]\d{7}|429[0-3]\d{6}|4294[0-8]\d{5}|42949[0-5]\d{4}|429496[0-6]\d{3}|4294967[01]\d{2}|42949672[0-8]\d|429496729[0-5])$' - if config['netflow']['version'] == '5': + engine_id = flow_config['netflow']['engine_id'] + version = flow_config['netflow']['version'] + + if flow_config['netflow']['version'] == '5': regex_filter = re.compile(v5_filter) - if not regex_filter.search(config['netflow']['engine-id']): - raise ConfigError("You cannot use NetFlow engine-id {} together with NetFlow protocol version {}".format(config['netflow']['engine-id'], config['netflow']['version'])) + if not regex_filter.search(engine_id): + raise ConfigError(f'You cannot use NetFlow engine-id "{engine_id}" '\ + f'together with NetFlow protocol version "{version}"!') else: regex_filter = re.compile(v9v10_filter) - if not regex_filter.search(config['netflow']['engine-id']): - raise ConfigError("You cannot use NetFlow engine-id {} together with NetFlow protocol version {}".format(config['netflow']['engine-id'], config['netflow']['version'])) + if not regex_filter.search(flow_config['netflow']['engine_id']): + raise ConfigError(f'Can not use NetFlow engine-id "{engine_id}" together '\ + f'with NetFlow protocol version "{version}"!') # return True if all checks were passed return True -def generate(config): - # skip all checks if flow-accounting was removed - if not config['flow-accounting-configured']: - return True - - # Calculate all necessary values - if config['buffer-size']: - # circular queue size - config['plugin_pipe_size'] = int(config['buffer-size']) * 1024**2 - else: - config['plugin_pipe_size'] = default_plugin_pipe_size * 1024**2 - # transfer buffer size - # recommended value from pmacct developers 1/1000 of pipe size - config['plugin_buffer_size'] = int(config['plugin_pipe_size'] / 1000) - - # Prepare a timeouts string - timeout_string = '' - for timeout_type, timeout_value in config['netflow']['timeout'].items(): - if timeout_value: - if timeout_string == '': - timeout_string = "{}{}={}".format(timeout_string, timeout_type, timeout_value) - else: - timeout_string = "{}:{}={}".format(timeout_string, timeout_type, timeout_value) - config['netflow']['timeout_string'] = timeout_string - - render(uacctd_conf_path, 'netflow/uacctd.conf.tmpl', { - 'templatecfg': config, - 'snaplen': default_captured_packet_size, - }) +def generate(flow_config): + if not flow_config: + return None + render(uacctd_conf_path, 'pmacct/uacctd.conf.j2', flow_config) + render(systemd_override, 'pmacct/override.conf.j2', flow_config) + # Reload systemd manager configuration + call('systemctl daemon-reload') -def apply(config): - # define variables - command = None +def apply(flow_config): + action = 'restart' # Check if flow-accounting was removed and define command - if not config['flow-accounting-configured']: - command = 'systemctl stop uacctd.service' - else: - command = 'systemctl restart uacctd.service' + if not flow_config: + _nftables_config([], 'ingress') + _nftables_config([], 'egress') + + # Stop flow-accounting daemon and remove configuration file + call(f'systemctl stop {systemd_service}') + if os.path.exists(uacctd_conf_path): + os.unlink(uacctd_conf_path) + return - # run command to start or stop flow-accounting - cmd(command, raising=ConfigError, message='Failed to start/stop flow-accounting') + # Start/reload flow-accounting daemon + call(f'systemctl restart {systemd_service}') - # configure iptables rules for defined interfaces - if config['interfaces']: - _iptables_config(config['interfaces'], 'ingress') + # configure nftables rules for defined interfaces + if 'interface' in flow_config: + _nftables_config(flow_config['interface'], 'ingress', flow_config['packet_length']) # configure egress the same way if configured otherwise remove it - if config['enable-egress']: - _iptables_config(config['interfaces'], 'egress') + if 'enable_egress' in flow_config: + _nftables_config(flow_config['interface'], 'egress', flow_config['packet_length']) else: - _iptables_config([], 'egress') - else: - _iptables_config([], 'ingress') - _iptables_config([], 'egress') + _nftables_config([], 'egress') if __name__ == '__main__': try: diff --git a/src/conf_mode/vrrp.py b/src/conf_mode/high-availability.py index c72efc61f..e14050dd3 100755 --- a/src/conf_mode/vrrp.py +++ b/src/conf_mode/high-availability.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2021 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -28,7 +28,6 @@ from vyos.template import render from vyos.template import is_ipv4 from vyos.template import is_ipv6 from vyos.util import call -from vyos.util import is_systemd_service_running from vyos.xml import defaults from vyos import ConfigError from vyos import airbag @@ -40,33 +39,41 @@ def get_config(config=None): else: conf = Config() - base = ['high-availability', 'vrrp'] + base = ['high-availability'] + base_vrrp = ['high-availability', 'vrrp'] if not conf.exists(base): return None - vrrp = conf.get_config_dict(base, key_mangling=('-', '_'), + ha = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) # We have gathered the dict representation of the CLI, but there are default # options which we need to update into the dictionary retrived. - if 'group' in vrrp: - default_values = defaults(base + ['group']) - for group in vrrp['group']: - vrrp['group'][group] = dict_merge(default_values, vrrp['group'][group]) + if 'vrrp' in ha: + if 'group' in ha['vrrp']: + default_values_vrrp = defaults(base_vrrp + ['group']) + for group in ha['vrrp']['group']: + ha['vrrp']['group'][group] = dict_merge(default_values_vrrp, ha['vrrp']['group'][group]) + + # Merge per virtual-server default values + if 'virtual_server' in ha: + default_values = defaults(base + ['virtual-server']) + for vs in ha['virtual_server']: + ha['virtual_server'][vs] = dict_merge(default_values, ha['virtual_server'][vs]) ## Get the sync group used for conntrack-sync conntrack_path = ['service', 'conntrack-sync', 'failover-mechanism', 'vrrp', 'sync-group'] if conf.exists(conntrack_path): - vrrp['conntrack_sync_group'] = conf.return_value(conntrack_path) + ha['conntrack_sync_group'] = conf.return_value(conntrack_path) - return vrrp + return ha -def verify(vrrp): - if not vrrp: +def verify(ha): + if not ha: return None used_vrid_if = [] - if 'group' in vrrp: - for group, group_config in vrrp['group'].items(): + if 'vrrp' in ha and 'group' in ha['vrrp']: + for group, group_config in ha['vrrp']['group'].items(): # Check required fields if 'vrid' not in group_config: raise ConfigError(f'VRID is required but not set in VRRP group "{group}"') @@ -119,33 +126,41 @@ def verify(vrrp): if is_ipv4(group_config['peer_address']): raise ConfigError(f'VRRP group "{group}" uses IPv6 but peer-address is IPv4!') # Check sync groups - if 'sync_group' in vrrp: - for sync_group, sync_config in vrrp['sync_group'].items(): + if 'vrrp' in ha and 'sync_group' in ha['vrrp']: + for sync_group, sync_config in ha['vrrp']['sync_group'].items(): if 'member' in sync_config: for member in sync_config['member']: - if member not in vrrp['group']: + if member not in ha['vrrp']['group']: raise ConfigError(f'VRRP sync-group "{sync_group}" refers to VRRP group "{member}", '\ 'but it does not exist!') -def generate(vrrp): - if not vrrp: + # 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 'real_server' not in vs_config: + raise ConfigError(f'Real-server ip is required but not set for virtual-server "{vs}"') + # Real-server + for rs, rs_config in vs_config['real_server'].items(): + if 'port' not in rs_config: + raise ConfigError(f'Port is required but not set for virtual-server "{vs}" real-server "{rs}"') + + +def generate(ha): + if not ha: return None - render(VRRP.location['config'], 'vrrp/keepalived.conf.tmpl', vrrp) + render(VRRP.location['config'], 'high-availability/keepalived.conf.j2', ha) return None -def apply(vrrp): +def apply(ha): service_name = 'keepalived.service' - if not vrrp: + if not ha: call(f'systemctl stop {service_name}') return None - # XXX: T3944 - reload keepalived configuration if service is already running - # to not cause any service disruption when applying changes. - if is_systemd_service_running(service_name): - call(f'systemctl reload {service_name}') - else: - call(f'systemctl restart {service_name}') + call(f'systemctl reload-or-restart {service_name}') return None if __name__ == '__main__': diff --git a/src/conf_mode/host_name.py b/src/conf_mode/host_name.py index 87bad0dc6..93f244f42 100755 --- a/src/conf_mode/host_name.py +++ b/src/conf_mode/host_name.py @@ -21,13 +21,14 @@ import copy import vyos.util import vyos.hostsd_client -from vyos import ConfigError +from vyos.base import Warning from vyos.config import Config from vyos.ifconfig import Section from vyos.template import is_ip from vyos.util import cmd from vyos.util import call from vyos.util import process_named_running +from vyos import ConfigError from vyos import airbag airbag.enable() @@ -113,7 +114,7 @@ def verify(hosts): for interface, interface_config in hosts['nameservers_dhcp_interfaces'].items(): # Warnin user if interface does not have DHCP or DHCPv6 configured if not set(interface_config).intersection(['dhcp', 'dhcpv6']): - print(f'WARNING: "{interface}" is not a DHCP interface but uses DHCP name-server option!') + Warning(f'"{interface}" is not a DHCP interface but uses DHCP name-server option!') return None diff --git a/src/conf_mode/http-api.py b/src/conf_mode/http-api.py index 7e4b117c8..4a7906c17 100755 --- a/src/conf_mode/http-api.py +++ b/src/conf_mode/http-api.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019 VyOS maintainers and contributors +# Copyright (C) 2019-2021 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 @@ -13,25 +13,26 @@ # # 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 sys import os import json -import time + +from time import sleep from copy import deepcopy import vyos.defaults + from vyos.config import Config -from vyos import ConfigError +from vyos.template import render from vyos.util import cmd from vyos.util import call - +from vyos import ConfigError from vyos import airbag airbag.enable() -config_file = '/etc/vyos/http-api.conf' +api_conf_file = '/etc/vyos/http-api.conf' +systemd_service = '/run/systemd/system/vyos-http-api.service' vyos_conf_scripts_dir=vyos.defaults.directories['conf_mode'] @@ -49,21 +50,44 @@ def get_config(config=None): else: conf = Config() - if not conf.exists('service https api'): + base = ['service', 'https', 'api'] + if not conf.exists(base): return None - else: - conf.set_level('service https api') + # Do we run inside a VRF context? + vrf_path = ['service', 'https', 'vrf'] + if conf.exists(vrf_path): + http_api['vrf'] = conf.return_value(vrf_path) + + conf.set_level('service https api') if conf.exists('strict'): - http_api['strict'] = 'true' + http_api['strict'] = True if conf.exists('debug'): - http_api['debug'] = 'true' + http_api['debug'] = True + + # this node is not available by CLI by default, and is reserved for + # the graphql tools. One can enable it for testing, with the warning + # that this will open an unauthenticated server. To do so + # mkdir /opt/vyatta/share/vyatta-cfg/templates/service/https/api/gql + # touch /opt/vyatta/share/vyatta-cfg/templates/service/https/api/gql/node.def + # and configure; editing the config alone is insufficient. + if conf.exists('gql'): + http_api['gql'] = True + + if conf.exists('socket'): + http_api['socket'] = True if conf.exists('port'): port = conf.return_value('port') http_api['port'] = port + if conf.exists('cors'): + http_api['cors'] = {} + if conf.exists('cors allow-origin'): + origins = conf.return_values('cors allow-origin') + http_api['cors']['origins'] = origins[:] + if conf.exists('keys'): for name in conf.list_nodes('keys id'): if conf.exists('keys id {0} key'.format(name)): @@ -83,24 +107,31 @@ def verify(http_api): def generate(http_api): if http_api is None: + if os.path.exists(systemd_service): + os.unlink(systemd_service) return None if not os.path.exists('/etc/vyos'): os.mkdir('/etc/vyos') - with open(config_file, 'w') as f: + with open(api_conf_file, 'w') as f: json.dump(http_api, f, indent=2) + render(systemd_service, 'https/vyos-http-api.service.j2', http_api) return None def apply(http_api): + # Reload systemd manager configuration + call('systemctl daemon-reload') + service_name = 'vyos-http-api.service' + if http_api is not None: - call('systemctl restart vyos-http-api.service') + call(f'systemctl restart {service_name}') else: - call('systemctl stop vyos-http-api.service') + call(f'systemctl stop {service_name}') # Let uvicorn settle before restarting Nginx - time.sleep(2) + sleep(1) cmd(f'{vyos_conf_scripts_dir}/https.py', raising=ConfigError) diff --git a/src/conf_mode/https.py b/src/conf_mode/https.py index 92dc4a410..3057357fc 100755 --- a/src/conf_mode/https.py +++ b/src/conf_mode/https.py @@ -23,6 +23,7 @@ import vyos.defaults import vyos.certbot_util from vyos.config import Config +from vyos.configverify import verify_vrf from vyos import ConfigError from vyos.pki import wrap_certificate from vyos.pki import wrap_private_key @@ -34,6 +35,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' cert_dir = '/etc/ssl/certs' key_dir = '/etc/ssl/private' certbot_dir = vyos.defaults.directories['certbot'] @@ -59,10 +61,11 @@ def get_config(config=None): else: conf = Config() - if not conf.exists('service https'): + base = ['service', 'https'] + if not conf.exists(base): return None - https = conf.get_config_dict('service https', get_first_key=True) + https = conf.get_config_dict(base, get_first_key=True) if https: https['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'), @@ -103,6 +106,8 @@ def verify(https): if not domains_found: raise ConfigError("At least one 'virtual-host <id> server-name' " "matching the 'certbot domain-name' is required.") + + verify_vrf(https) return None def generate(https): @@ -143,7 +148,6 @@ def generate(https): server_cert = str(wrap_certificate(pki_cert['certificate'])) if 'ca-certificate' in cert_dict: ca_cert = cert_dict['ca-certificate'] - print(ca_cert) server_cert += '\n' + str(wrap_certificate(https['pki']['ca'][ca_cert]['certificate'])) write_file(cert_path, server_cert) @@ -188,6 +192,8 @@ def generate(https): vhosts = https.get('api-restrict', {}).get('virtual-host', []) if vhosts: api_data['vhost'] = vhosts[:] + if 'socket' in list(api_settings): + api_data['socket'] = True if api_data: vhost_list = api_data.get('vhost', []) @@ -208,11 +214,13 @@ def generate(https): 'certbot': certbot } - render(config_file, 'https/nginx.default.tmpl', data) - + render(config_file, 'https/nginx.default.j2', data) + render(systemd_override, 'https/override.conf.j2', https) return None def apply(https): + # Reload systemd manager configuration + call('systemctl daemon-reload') if https is not None: call('systemctl restart nginx.service') else: diff --git a/src/conf_mode/igmp_proxy.py b/src/conf_mode/igmp_proxy.py index fb030c9f3..de6a51c64 100755 --- a/src/conf_mode/igmp_proxy.py +++ b/src/conf_mode/igmp_proxy.py @@ -19,6 +19,7 @@ import os from sys import exit from netifaces import interfaces +from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render @@ -92,10 +93,10 @@ def generate(igmp_proxy): # bail out early - service is disabled, but inform user if 'disable' in igmp_proxy: - print('WARNING: IGMP Proxy will be deactivated because it is disabled') + Warning('IGMP Proxy will be deactivated because it is disabled') return None - render(config_file, 'igmp-proxy/igmpproxy.conf.tmpl', igmp_proxy) + render(config_file, 'igmp-proxy/igmpproxy.conf.j2', igmp_proxy) return None diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index 431d65f1f..4167594e3 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -27,8 +27,9 @@ from vyos.configdict import is_source_interface from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_dhcpv6 -from vyos.configverify import verify_source_interface +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_source_interface from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ifconfig import BondIf @@ -67,7 +68,7 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'bonding'] - bond = get_interface_dict(conf, base) + ifname, bond = get_interface_dict(conf, base) # To make our own life easier transfor the list of member interfaces # into a dictionary - we will use this to add additional information @@ -80,14 +81,14 @@ def get_config(config=None): if 'mode' in bond: bond['mode'] = get_bond_mode(bond['mode']) - tmp = leaf_node_changed(conf, ['mode']) + tmp = leaf_node_changed(conf, base + [ifname, 'mode']) if tmp: bond.update({'shutdown_required': {}}) - tmp = leaf_node_changed(conf, ['lacp-rate']) + tmp = leaf_node_changed(conf, base + [ifname, 'lacp-rate']) if tmp: bond.update({'shutdown_required': {}}) # determine which members have been removed - interfaces_removed = leaf_node_changed(conf, ['member', 'interface']) + interfaces_removed = leaf_node_changed(conf, base + [ifname, 'member', 'interface']) if interfaces_removed: bond.update({'shutdown_required': {}}) if 'member' not in bond: @@ -132,10 +133,10 @@ def verify(bond): return None if 'arp_monitor' in bond: - if 'target' in bond['arp_monitor'] and len(int(bond['arp_monitor']['target'])) > 16: + if 'target' in bond['arp_monitor'] and len(bond['arp_monitor']['target']) > 16: raise ConfigError('The maximum number of arp-monitor targets is 16') - if 'interval' in bond['arp_monitor'] and len(int(bond['arp_monitor']['interval'])) > 0: + if 'interval' in bond['arp_monitor'] and int(bond['arp_monitor']['interval']) > 0: if bond['mode'] in ['802.3ad', 'balance-tlb', 'balance-alb']: raise ConfigError('ARP link monitoring does not work for mode 802.3ad, ' \ 'transmit-load-balance or adaptive-load-balance') @@ -149,6 +150,7 @@ def verify(bond): verify_address(bond) verify_dhcpv6(bond) verify_vrf(bond) + verify_mirror_redirect(bond) # use common function to verify VLAN configuration verify_vlan_config(bond) diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py index 4d3ebc587..38ae727c1 100755 --- a/src/conf_mode/interfaces-bridge.py +++ b/src/conf_mode/interfaces-bridge.py @@ -22,12 +22,12 @@ from netifaces import interfaces from vyos.config import Config from vyos.configdict import get_interface_dict from vyos.configdict import node_changed -from vyos.configdict import leaf_node_changed from vyos.configdict import is_member from vyos.configdict import is_source_interface from vyos.configdict import has_vlan_subinterface_configured from vyos.configdict import dict_merge from vyos.configverify import verify_dhcpv6 +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.ifconfig import BridgeIf from vyos.validate import has_address_configured @@ -50,15 +50,15 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'bridge'] - bridge = get_interface_dict(conf, base) + ifname, bridge = get_interface_dict(conf, base) # determine which members have been removed - tmp = node_changed(conf, ['member', 'interface'], key_mangling=('-', '_')) + tmp = node_changed(conf, base + [ifname, 'member', 'interface'], key_mangling=('-', '_')) if tmp: if 'member' in bridge: - bridge['member'].update({'interface_remove': tmp }) + bridge['member'].update({'interface_remove' : tmp }) else: - bridge.update({'member': {'interface_remove': tmp }}) + bridge.update({'member' : {'interface_remove' : tmp }}) if dict_search('member.interface', bridge): # XXX: T2665: we need a copy of the dict keys for iteration, else we will get: @@ -106,6 +106,7 @@ def verify(bridge): verify_dhcpv6(bridge) verify_vrf(bridge) + verify_mirror_redirect(bridge) ifname = bridge['ifname'] diff --git a/src/conf_mode/interfaces-dummy.py b/src/conf_mode/interfaces-dummy.py index 55c783f38..e771581e1 100755 --- a/src/conf_mode/interfaces-dummy.py +++ b/src/conf_mode/interfaces-dummy.py @@ -21,6 +21,7 @@ from vyos.configdict import get_interface_dict from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import DummyIf from vyos import ConfigError from vyos import airbag @@ -36,7 +37,7 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'dummy'] - dummy = get_interface_dict(conf, base) + _, dummy = get_interface_dict(conf, base) return dummy def verify(dummy): @@ -46,6 +47,7 @@ def verify(dummy): verify_vrf(dummy) verify_address(dummy) + verify_mirror_redirect(dummy) return None diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py index e7250fb49..fec4456fb 100755 --- a/src/conf_mode/interfaces-ethernet.py +++ b/src/conf_mode/interfaces-ethernet.py @@ -19,20 +19,23 @@ import os from glob import glob from sys import exit +from vyos.base import Warning from vyos.config import Config from vyos.configdict import get_interface_dict from vyos.configverify import verify_address from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_eapol from vyos.configverify import verify_interface_exists -from vyos.configverify import verify_mirror +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_mtu from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ethtool import Ethtool from vyos.ifconfig import EthernetIf -from vyos.pki import wrap_certificate +from vyos.pki import find_chain +from vyos.pki import encode_certificate +from vyos.pki import load_certificate from vyos.pki import wrap_private_key from vyos.template import render from vyos.util import call @@ -62,7 +65,7 @@ def get_config(config=None): get_first_key=True, no_tag_node_value_mangle=True) base = ['interfaces', 'ethernet'] - ethernet = get_interface_dict(conf, base) + _, ethernet = get_interface_dict(conf, base) if 'deleted' not in ethernet: if pki: ethernet['pki'] = pki @@ -81,7 +84,7 @@ def verify(ethernet): verify_address(ethernet) verify_vrf(ethernet) verify_eapol(ethernet) - verify_mirror(ethernet) + verify_mirror_redirect(ethernet) ethtool = Ethtool(ifname) # No need to check speed and duplex keys as both have default values. @@ -140,8 +143,8 @@ def verify(ethernet): raise ConfigError('XDP requires additional TX queues, too few available!') if {'is_bond_member', 'mac'} <= set(ethernet): - print(f'WARNING: changing mac address "{mac}" will be ignored as "{ifname}" ' - f'is a member of bond "{is_bond_member}"'.format(**ethernet)) + Warning(f'changing mac address "{mac}" will be ignored as "{ifname}" ' \ + f'is a member of bond "{is_bond_member}"'.format(**ethernet)) # use common function to verify VLAN configuration verify_vlan_config(ethernet) @@ -150,7 +153,7 @@ def verify(ethernet): def generate(ethernet): if 'eapol' in ethernet: render(wpa_suppl_conf.format(**ethernet), - 'ethernet/wpa_supplicant.conf.tmpl', ethernet) + 'ethernet/wpa_supplicant.conf.j2', ethernet) ifname = ethernet['ifname'] cert_file_path = os.path.join(cfg_dir, f'{ifname}_cert.pem') @@ -159,16 +162,26 @@ def generate(ethernet): cert_name = ethernet['eapol']['certificate'] pki_cert = ethernet['pki']['certificate'][cert_name] - write_file(cert_file_path, wrap_certificate(pki_cert['certificate'])) + loaded_pki_cert = load_certificate(pki_cert['certificate']) + loaded_ca_certs = {load_certificate(c['certificate']) + for c in ethernet['pki']['ca'].values()} + + cert_full_chain = find_chain(loaded_pki_cert, loaded_ca_certs) + + write_file(cert_file_path, + '\n'.join(encode_certificate(c) for c in cert_full_chain)) write_file(cert_key_path, wrap_private_key(pki_cert['private']['key'])) if 'ca_certificate' in ethernet['eapol']: ca_cert_file_path = os.path.join(cfg_dir, f'{ifname}_ca.pem') ca_cert_name = ethernet['eapol']['ca_certificate'] - pki_ca_cert = ethernet['pki']['ca'][cert_name] + pki_ca_cert = ethernet['pki']['ca'][ca_cert_name] + + loaded_ca_cert = load_certificate(pki_ca_cert['certificate']) + ca_full_chain = find_chain(loaded_ca_cert, loaded_ca_certs) write_file(ca_cert_file_path, - wrap_certificate(pki_ca_cert['certificate'])) + '\n'.join(encode_certificate(c) for c in ca_full_chain)) else: # delete configuration on interface removal if os.path.isfile(wpa_suppl_conf.format(**ethernet)): diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py index 2a63b60aa..b9cf2fa3c 100755 --- a/src/conf_mode/interfaces-geneve.py +++ b/src/conf_mode/interfaces-geneve.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 @@ -21,9 +21,12 @@ from netifaces import interfaces from vyos.config import Config from vyos.configdict import get_interface_dict +from vyos.configdict import leaf_node_changed +from vyos.configdict import is_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import GeneveIf from vyos import ConfigError @@ -40,7 +43,18 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'geneve'] - geneve = get_interface_dict(conf, base) + ifname, geneve = get_interface_dict(conf, base) + + # GENEVE interfaces are picky and require recreation if certain parameters + # change. But a GENEVE interface should - of course - not be re-created if + # it's description or IP address is adjusted. Feels somehow logic doesn't it? + for cli_option in ['remote', 'vni']: + if leaf_node_changed(conf, base + [ifname, cli_option]): + geneve.update({'rebuild_required': {}}) + + if is_node_changed(conf, base + [ifname, 'parameters']): + geneve.update({'rebuild_required': {}}) + return geneve def verify(geneve): @@ -50,6 +64,7 @@ def verify(geneve): verify_mtu_ipv6(geneve) verify_address(geneve) + verify_mirror_redirect(geneve) if 'remote' not in geneve: raise ConfigError('Remote side must be configured') @@ -65,11 +80,12 @@ def generate(geneve): def apply(geneve): # Check if GENEVE interface already exists - if geneve['ifname'] in interfaces(): - g = GeneveIf(geneve['ifname']) - # GENEVE is super picky and the tunnel always needs to be recreated, - # thus we can simply always delete it first. - g.remove() + if 'rebuild_required' in geneve or 'delete' in geneve: + if geneve['ifname'] in interfaces(): + g = GeneveIf(geneve['ifname']) + # GENEVE is super picky and the tunnel always needs to be recreated, + # thus we can simply always delete it first. + g.remove() if 'deleted' not in geneve: # Finally create the new interface diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py index 9b6ddd5aa..6a486f969 100755 --- a/src/conf_mode/interfaces-l2tpv3.py +++ b/src/conf_mode/interfaces-l2tpv3.py @@ -25,6 +25,7 @@ from vyos.configdict import leaf_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import L2TPv3If from vyos.util import check_kmod from vyos.validate import is_addr_assigned @@ -44,15 +45,15 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'l2tpv3'] - l2tpv3 = get_interface_dict(conf, base) + ifname, l2tpv3 = get_interface_dict(conf, base) # To delete an l2tpv3 interface we need the current tunnel and session-id if 'deleted' in l2tpv3: - tmp = leaf_node_changed(conf, ['tunnel-id']) + tmp = leaf_node_changed(conf, base + [ifname, 'tunnel-id']) # leaf_node_changed() returns a list l2tpv3.update({'tunnel_id': tmp[0]}) - tmp = leaf_node_changed(conf, ['session-id']) + tmp = leaf_node_changed(conf, base + [ifname, 'session-id']) l2tpv3.update({'session_id': tmp[0]}) return l2tpv3 @@ -76,6 +77,7 @@ def verify(l2tpv3): verify_mtu_ipv6(l2tpv3) verify_address(l2tpv3) + verify_mirror_redirect(l2tpv3) return None def generate(l2tpv3): diff --git a/src/conf_mode/interfaces-loopback.py b/src/conf_mode/interfaces-loopback.py index 193334443..08d34477a 100755 --- a/src/conf_mode/interfaces-loopback.py +++ b/src/conf_mode/interfaces-loopback.py @@ -20,6 +20,7 @@ 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 LoopbackIf from vyos import ConfigError from vyos import airbag @@ -35,10 +36,11 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'loopback'] - loopback = get_interface_dict(conf, base) + _, loopback = get_interface_dict(conf, base) return loopback def verify(loopback): + verify_mirror_redirect(loopback) return None def generate(loopback): diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index eab69f36e..279dd119b 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -29,6 +29,7 @@ from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_source_interface from vyos import ConfigError from vyos import airbag @@ -47,7 +48,7 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'macsec'] - macsec = get_interface_dict(conf, base) + ifname, macsec = get_interface_dict(conf, base) # Check if interface has been removed if 'deleted' in macsec: @@ -66,6 +67,7 @@ def verify(macsec): verify_vrf(macsec) verify_mtu_ipv6(macsec) verify_address(macsec) + verify_mirror_redirect(macsec) if not (('security' in macsec) and ('cipher' in macsec['security'])): @@ -96,7 +98,7 @@ def verify(macsec): def generate(macsec): render(wpa_suppl_conf.format(**macsec), - 'macsec/wpa_supplicant.conf.tmpl', macsec) + 'macsec/wpa_supplicant.conf.j2', macsec) return None diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 3b8fae710..4750ca3e8 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2021 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 @@ -32,8 +32,10 @@ from shutil import rmtree from vyos.config import Config from vyos.configdict import get_interface_dict +from vyos.configdict import is_node_changed from vyos.configverify import verify_vrf from vyos.configverify import verify_bridge_delete +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import VTunIf from vyos.pki import load_dh_parameters from vyos.pki import load_private_key @@ -47,6 +49,7 @@ from vyos.template import is_ipv4 from vyos.template import is_ipv6 from vyos.util import call from vyos.util import chown +from vyos.util import cmd from vyos.util import dict_search from vyos.util import dict_search_args from vyos.util import makedir @@ -82,10 +85,12 @@ def get_config(config=None): tmp_pki = conf.get_config_dict(['pki'], key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) - openvpn = get_interface_dict(conf, base) + ifname, openvpn = get_interface_dict(conf, base) if 'deleted' not in openvpn: openvpn['pki'] = tmp_pki + if is_node_changed(conf, base + [ifname, 'openvpn-option']): + openvpn.update({'restart_required': {}}) # We have to get the dict using 'get_config_dict' instead of 'get_interface_dict' # as 'get_interface_dict' merges the defaults in, so we can not check for defaults in there. @@ -225,11 +230,12 @@ def verify(openvpn): if 'local_address' not in openvpn and 'is_bridge_member' not in openvpn: raise ConfigError('Must specify "local-address" or add interface to bridge') - if len([addr for addr in openvpn['local_address'] if is_ipv4(addr)]) > 1: - raise ConfigError('Only one IPv4 local-address can be specified') + if 'local_address' in openvpn: + if len([addr for addr in openvpn['local_address'] if is_ipv4(addr)]) > 1: + raise ConfigError('Only one IPv4 local-address can be specified') - if len([addr for addr in openvpn['local_address'] if is_ipv6(addr)]) > 1: - raise ConfigError('Only one IPv6 local-address can be specified') + if len([addr for addr in openvpn['local_address'] if is_ipv6(addr)]) > 1: + raise ConfigError('Only one IPv6 local-address can be specified') if openvpn['device_type'] == 'tun': if 'remote_address' not in openvpn: @@ -268,7 +274,7 @@ def verify(openvpn): if dict_search('remote_host', openvpn) in dict_search('remote_address', openvpn): raise ConfigError('"remote-address" and "remote-host" can not be the same') - if openvpn['device_type'] == 'tap': + if openvpn['device_type'] == 'tap' and 'local_address' in openvpn: # we can only have one local_address, this is ensured above v4addr = None for laddr in openvpn['local_address']: @@ -423,8 +429,8 @@ def verify(openvpn): # verify specified IP address is present on any interface on this system if 'local_host' in openvpn: if not is_addr_assigned(openvpn['local_host']): - raise ConfigError('local-host IP address "{local_host}" not assigned' \ - ' to any interface'.format(**openvpn)) + print('local-host IP address "{local_host}" not assigned' \ + ' to any interface'.format(**openvpn)) # TCP active if openvpn['protocol'] == 'tcp-active': @@ -489,6 +495,7 @@ def verify(openvpn): raise ConfigError('Username for authentication is missing') verify_vrf(openvpn) + verify_mirror_redirect(openvpn) return None @@ -600,7 +607,7 @@ def generate(openvpn): # Generate User/Password authentication file if 'authentication' in openvpn: - render(openvpn['auth_user_pass_file'], 'openvpn/auth.pw.tmpl', openvpn, + render(openvpn['auth_user_pass_file'], 'openvpn/auth.pw.j2', openvpn, user=user, group=group, permission=0o600) else: # delete old auth file if present @@ -616,16 +623,16 @@ def generate(openvpn): # Our client need's to know its subnet mask ... client_config['server_subnet'] = dict_search('server.subnet', openvpn) - render(client_file, 'openvpn/client.conf.tmpl', client_config, + render(client_file, 'openvpn/client.conf.j2', client_config, user=user, group=group) # we need to support quoting of raw parameters from OpenVPN CLI # see https://phabricator.vyos.net/T1632 - render(cfg_file.format(**openvpn), 'openvpn/server.conf.tmpl', openvpn, + render(cfg_file.format(**openvpn), 'openvpn/server.conf.j2', openvpn, formater=lambda _: _.replace(""", '"'), user=user, group=group) # Render 20-override.conf for OpenVPN service - render(service_file.format(**openvpn), 'openvpn/service-override.conf.tmpl', openvpn, + render(service_file.format(**openvpn), 'openvpn/service-override.conf.j2', openvpn, formater=lambda _: _.replace(""", '"'), user=user, group=group) # Reload systemd services config to apply an override call(f'systemctl daemon-reload') @@ -647,9 +654,19 @@ def apply(openvpn): return None + # verify specified IP address is present on any interface on this system + # Allow to bind service to nonlocal address, if it virtaual-vrrp address + # or if address will be assign later + if 'local_host' in openvpn: + if not is_addr_assigned(openvpn['local_host']): + cmd('sysctl -w net.ipv4.ip_nonlocal_bind=1') + # No matching OpenVPN process running - maybe it got killed or none # existed - nevertheless, spawn new OpenVPN process - call(f'systemctl reload-or-restart openvpn@{interface}.service') + action = 'reload-or-restart' + if 'restart_required' in openvpn: + action = 'restart' + call(f'systemctl {action} openvpn@{interface}.service') o = VTunIf(**openvpn) o.update(openvpn) diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py index 584adc75e..e2fdc7a42 100755 --- a/src/conf_mode/interfaces-pppoe.py +++ b/src/conf_mode/interfaces-pppoe.py @@ -22,12 +22,15 @@ from netifaces import interfaces from vyos.config import Config from vyos.configdict import get_interface_dict +from vyos.configdict import is_node_changed from vyos.configdict import leaf_node_changed +from vyos.configdict import get_pppoe_interfaces from vyos.configverify import verify_authentication from vyos.configverify import verify_source_interface from vyos.configverify import verify_interface_exists from vyos.configverify import verify_vrf from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import PPPoEIf from vyos.template import render from vyos.util import call @@ -46,33 +49,17 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'pppoe'] - pppoe = get_interface_dict(conf, base) + ifname, pppoe = get_interface_dict(conf, base) # We should only terminate the PPPoE session if critical parameters change. # All parameters that can be changed on-the-fly (like interface description) # should not lead to a reconnect! - tmp = leaf_node_changed(conf, ['access-concentrator']) - if tmp: pppoe.update({'shutdown_required': {}}) - - tmp = leaf_node_changed(conf, ['connect-on-demand']) - if tmp: pppoe.update({'shutdown_required': {}}) - - tmp = leaf_node_changed(conf, ['service-name']) - if tmp: pppoe.update({'shutdown_required': {}}) - - tmp = leaf_node_changed(conf, ['source-interface']) - if tmp: pppoe.update({'shutdown_required': {}}) - - tmp = leaf_node_changed(conf, ['vrf']) - # leaf_node_changed() returns a list, as VRF is a non-multi node, there - # will be only one list element - if tmp: pppoe.update({'vrf_old': tmp[0]}) - - tmp = leaf_node_changed(conf, ['authentication', 'user']) - if tmp: pppoe.update({'shutdown_required': {}}) - - tmp = leaf_node_changed(conf, ['authentication', 'password']) - if tmp: pppoe.update({'shutdown_required': {}}) + for options in ['access-concentrator', 'connect-on-demand', 'service-name', + 'source-interface', 'vrf', 'no-default-route', 'authentication']: + if is_node_changed(conf, base + [ifname, options]): + pppoe.update({'shutdown_required': {}}) + # bail out early - no need to further process other nodes + break return pppoe @@ -85,6 +72,7 @@ def verify(pppoe): verify_authentication(pppoe) verify_vrf(pppoe) verify_mtu_ipv6(pppoe) + verify_mirror_redirect(pppoe) if {'connect_on_demand', 'vrf'} <= set(pppoe): raise ConfigError('On-demand dialing and VRF can not be used at the same time') @@ -104,7 +92,7 @@ def generate(pppoe): return None # Create PPP configuration files - render(config_pppoe, 'pppoe/peer.tmpl', pppoe, permission=0o640) + render(config_pppoe, 'pppoe/peer.j2', pppoe, permission=0o640) return None @@ -118,7 +106,7 @@ def apply(pppoe): return None # reconnect should only be necessary when certain config options change, - # like ACS name, authentication, no-peer-dns, source-interface + # like ACS name, authentication ... (see get_config() for details) if ((not is_systemd_service_running(f'ppp@{ifname}.service')) or 'shutdown_required' in pppoe): @@ -128,6 +116,9 @@ def apply(pppoe): p.remove() call(f'systemctl restart ppp@{ifname}.service') + # When interface comes "live" a hook is called: + # /etc/ppp/ip-up.d/99-vyos-pppoe-callback + # which triggers PPPoEIf.update() else: if os.path.isdir(f'/sys/class/net/{ifname}'): p = PPPoEIf(ifname) diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index 945a2ea9c..1cd3fe276 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -18,13 +18,14 @@ from sys import exit from vyos.config import Config from vyos.configdict import get_interface_dict -from vyos.configdict import leaf_node_changed +from vyos.configdict import is_node_changed from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_source_interface from vyos.configverify import verify_vlan_config from vyos.configverify import verify_mtu_parent +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import MACVLANIf from vyos import ConfigError @@ -41,14 +42,14 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'pseudo-ethernet'] - peth = get_interface_dict(conf, base) + ifname, peth = get_interface_dict(conf, base) - mode = leaf_node_changed(conf, ['mode']) - if mode: peth.update({'mode_old' : mode}) + mode = is_node_changed(conf, ['mode']) + if mode: peth.update({'shutdown_required' : {}}) if 'source_interface' in peth: - peth['parent'] = get_interface_dict(conf, ['interfaces', 'ethernet'], - peth['source_interface']) + _, peth['parent'] = get_interface_dict(conf, ['interfaces', 'ethernet'], + peth['source_interface']) return peth def verify(peth): @@ -60,6 +61,7 @@ def verify(peth): verify_vrf(peth) verify_address(peth) verify_mtu_parent(peth, peth['parent']) + verify_mirror_redirect(peth) # use common function to verify VLAN configuration verify_vlan_config(peth) diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py index 30f57ec0c..eff7f373c 100755 --- a/src/conf_mode/interfaces-tunnel.py +++ b/src/conf_mode/interfaces-tunnel.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2021 VyOS maintainers and contributors +# Copyright (C) 2018-2022 yOS 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 @@ -18,24 +18,20 @@ import os from sys import exit from netifaces import interfaces -from ipaddress import IPv4Address from vyos.config import Config -from vyos.configdict import dict_merge from vyos.configdict import get_interface_dict -from vyos.configdict import node_changed from vyos.configdict import leaf_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_interface_exists from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.configverify import verify_tunnel from vyos.ifconfig import Interface from vyos.ifconfig import Section from vyos.ifconfig import TunnelIf -from vyos.template import is_ipv4 -from vyos.template import is_ipv6 from vyos.util import get_interface_config from vyos.util import dict_search from vyos import ConfigError @@ -52,10 +48,26 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'tunnel'] - tunnel = get_interface_dict(conf, base) - - tmp = leaf_node_changed(conf, ['encapsulation']) - if tmp: tunnel.update({'encapsulation_changed': {}}) + ifname, tunnel = get_interface_dict(conf, base) + + if 'deleted' not in tunnel: + tmp = leaf_node_changed(conf, base + [ifname, 'encapsulation']) + if tmp: tunnel.update({'encapsulation_changed': {}}) + + # We also need to inspect other configured tunnels as there are Kernel + # restrictions where we need to comply. E.g. GRE tunnel key can't be used + # twice, or with multiple GRE tunnels to the same location we must specify + # a GRE key + conf.set_level(base) + tunnel['other_tunnels'] = conf.get_config_dict([], key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True) + # delete our own instance from this dict + ifname = tunnel['ifname'] + del tunnel['other_tunnels'][ifname] + # if only one tunnel is present on the system, no need to keep this key + if len(tunnel['other_tunnels']) == 0: + del tunnel['other_tunnels'] # We must check if our interface is configured to be a DMVPN member nhrp_base = ['protocols', 'nhrp', 'tunnel'] @@ -96,35 +108,47 @@ def verify(tunnel): if 'direction' not in tunnel['parameters']['erspan']: raise ConfigError('ERSPAN version 2 requires direction to be set!') - # If tunnel source address any and key not set + # If tunnel source is any and gre key is not set + interface = tunnel['ifname'] if tunnel['encapsulation'] in ['gre'] and \ dict_search('source_address', tunnel) == '0.0.0.0' and \ dict_search('parameters.ip.key', tunnel) == None: - raise ConfigError('Tunnel parameters ip key must be set!') - - if tunnel['encapsulation'] in ['gre', 'gretap']: - if dict_search('parameters.ip.key', tunnel) != None: - # Check pairs tunnel source-address/encapsulation/key with exists tunnels. - # Prevent the same key for 2 tunnels with same source-address/encap. T2920 - for tunnel_if in Section.interfaces('tunnel'): - # It makes no sense to run the test for re-used GRE keys on our - # own interface we are currently working on - if tunnel['ifname'] == tunnel_if: - continue - tunnel_cfg = get_interface_config(tunnel_if) - # no match on encapsulation - bail out - if dict_search('linkinfo.info_kind', tunnel_cfg) != tunnel['encapsulation']: - continue - new_source_address = dict_search('source_address', tunnel) - # Convert tunnel key to ip key, format "ip -j link show" - # 1 => 0.0.0.1, 999 => 0.0.3.231 - orig_new_key = dict_search('parameters.ip.key', tunnel) - new_key = IPv4Address(int(orig_new_key)) - new_key = str(new_key) - if dict_search('address', tunnel_cfg) == new_source_address and \ - dict_search('linkinfo.info_data.ikey', tunnel_cfg) == new_key: - raise ConfigError(f'Key "{orig_new_key}" for source-address "{new_source_address}" ' \ + raise ConfigError(f'"parameters ip key" must be set for {interface} when '\ + 'encapsulation is GRE!') + + gre_encapsulations = ['gre', 'gretap'] + if tunnel['encapsulation'] in gre_encapsulations and 'other_tunnels' in tunnel: + # Check pairs tunnel source-address/encapsulation/key with exists tunnels. + # Prevent the same key for 2 tunnels with same source-address/encap. T2920 + for o_tunnel, o_tunnel_conf in tunnel['other_tunnels'].items(): + # no match on encapsulation - bail out + our_encapsulation = tunnel['encapsulation'] + their_encapsulation = o_tunnel_conf['encapsulation'] + if our_encapsulation in gre_encapsulations and their_encapsulation \ + not in gre_encapsulations: + continue + + our_address = dict_search('source_address', tunnel) + our_key = dict_search('parameters.ip.key', tunnel) + their_address = dict_search('source_address', o_tunnel_conf) + their_key = dict_search('parameters.ip.key', o_tunnel_conf) + if our_key != None: + if their_address == our_address and their_key == our_key: + raise ConfigError(f'Key "{our_key}" for source-address "{our_address}" ' \ f'is already used for tunnel "{tunnel_if}"!') + else: + our_source_if = dict_search('source_interface', tunnel) + their_source_if = dict_search('source_interface', o_tunnel_conf) + our_remote = dict_search('remote', tunnel) + their_remote = dict_search('remote', o_tunnel_conf) + # If no IP GRE key is defined we can not have more then one GRE tunnel + # bound to any one interface/IP address and the same remote. This will + # result in a OS PermissionError: add tunnel "gre0" failed: File exists + if (their_address == our_address or our_source_if == their_source_if) and \ + our_remote == their_remote: + raise ConfigError(f'Missing required "ip key" parameter when '\ + 'running more then one GRE based tunnel on the '\ + 'same source-interface/source-address') # Keys are not allowed with ipip and sit tunnels if tunnel['encapsulation'] in ['ipip', 'sit']: @@ -134,6 +158,7 @@ def verify(tunnel): verify_mtu_ipv6(tunnel) verify_address(tunnel) verify_vrf(tunnel) + verify_mirror_redirect(tunnel) if 'source_interface' in tunnel: verify_interface_exists(tunnel['source_interface']) diff --git a/src/conf_mode/interfaces-vti.py b/src/conf_mode/interfaces-vti.py index 57950ffea..f4b0436af 100755 --- a/src/conf_mode/interfaces-vti.py +++ b/src/conf_mode/interfaces-vti.py @@ -19,6 +19,7 @@ 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 VTIIf from vyos.util import dict_search from vyos import ConfigError @@ -35,10 +36,11 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'vti'] - vti = get_interface_dict(conf, base) + _, vti = get_interface_dict(conf, base) return vti def verify(vti): + verify_mirror_redirect(vti) return None def generate(vti): diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py index 804f2d14f..f44d754ba 100755 --- a/src/conf_mode/interfaces-vxlan.py +++ b/src/conf_mode/interfaces-vxlan.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 @@ -19,11 +19,15 @@ import os from sys import exit from netifaces import interfaces +from vyos.base import Warning from vyos.config import Config from vyos.configdict import get_interface_dict +from vyos.configdict import leaf_node_changed +from vyos.configdict import is_node_changed from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_source_interface from vyos.ifconfig import Interface from vyos.ifconfig import VXLANIf @@ -34,15 +38,40 @@ 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 + 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', 'vxlan'] - vxlan = get_interface_dict(conf, base) + ifname, vxlan = get_interface_dict(conf, base) + + # VXLAN interfaces are picky and require recreation if certain parameters + # change. But a VXLAN interface should - of course - not be re-created if + # it's description or IP address is adjusted. Feels somehow logic doesn't it? + for cli_option in ['external', 'gpe', 'group', 'port', 'remote', + 'source-address', 'source-interface', 'vni']: + if leaf_node_changed(conf, base + [ifname, cli_option]): + vxlan.update({'rebuild_required': {}}) + + if is_node_changed(conf, base + [ifname, 'parameters']): + vxlan.update({'rebuild_required': {}}) + + # We need to verify that no other VXLAN tunnel is configured when external + # mode is in use - Linux Kernel limitation + conf.set_level(base) + vxlan['other_tunnels'] = conf.get_config_dict([], key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True) + + # This if-clause is just to be sure - it will always evaluate to true + ifname = vxlan['ifname'] + if ifname in vxlan['other_tunnels']: + del vxlan['other_tunnels'][ifname] + if len(vxlan['other_tunnels']) == 0: + del vxlan['other_tunnels'] return vxlan @@ -52,19 +81,31 @@ def verify(vxlan): return None if int(vxlan['mtu']) < 1500: - print('WARNING: RFC7348 recommends VXLAN tunnels preserve a 1500 byte MTU') + Warning('RFC7348 recommends VXLAN tunnels preserve a 1500 byte MTU') if 'group' in vxlan: if 'source_interface' not in vxlan: - raise ConfigError('Multicast VXLAN requires an underlaying interface ') - + raise ConfigError('Multicast VXLAN requires an underlaying interface') verify_source_interface(vxlan) if not any(tmp in ['group', 'remote', 'source_address'] for tmp in vxlan): raise ConfigError('Group, remote or source-address must be configured') - if 'vni' not in vxlan: - raise ConfigError('Must configure VNI for VXLAN') + if 'vni' not in vxlan and 'external' not in vxlan: + raise ConfigError( + 'Must either configure VXLAN "vni" or use "external" CLI option!') + + if {'external', 'vni'} <= set(vxlan): + raise ConfigError('Can not specify both "external" and "VNI"!') + + if {'external', 'other_tunnels'} <= set(vxlan): + other_tunnels = ', '.join(vxlan['other_tunnels']) + raise ConfigError(f'Only one VXLAN tunnel is supported when "external" '\ + f'CLI option is used. Additional tunnels: {other_tunnels}') + + if 'gpe' in vxlan and 'external' not in vxlan: + raise ConfigError(f'VXLAN-GPE is only supported when "external" '\ + f'CLI option is used.') if 'source_interface' in vxlan: # VXLAN adds at least an overhead of 50 byte - we need to check the @@ -81,22 +122,42 @@ def verify(vxlan): raise ConfigError(f'Underlaying device MTU is to small ({lower_mtu} '\ f'bytes) for VXLAN overhead ({vxlan_overhead} bytes!)') + # Check for mixed IPv4 and IPv6 addresses + protocol = None + if 'source_address' in vxlan: + if is_ipv6(vxlan['source_address']): + protocol = 'ipv6' + else: + protocol = 'ipv4' + + if 'remote' in vxlan: + error_msg = 'Can not mix both IPv4 and IPv6 for VXLAN underlay' + for remote in vxlan['remote']: + if is_ipv6(remote): + if protocol == 'ipv4': + raise ConfigError(error_msg) + protocol = 'ipv6' + else: + if protocol == 'ipv6': + raise ConfigError(error_msg) + protocol = 'ipv4' + verify_mtu_ipv6(vxlan) verify_address(vxlan) + verify_mirror_redirect(vxlan) return None - def generate(vxlan): return None - def apply(vxlan): # Check if the VXLAN interface already exists - if vxlan['ifname'] in interfaces(): - v = VXLANIf(vxlan['ifname']) - # VXLAN is super picky and the tunnel always needs to be recreated, - # thus we can simply always delete it first. - v.remove() + if 'rebuild_required' in vxlan or 'delete' in vxlan: + if vxlan['ifname'] in interfaces(): + v = VXLANIf(vxlan['ifname']) + # VXLAN is super picky and the tunnel always needs to be recreated, + # thus we can simply always delete it first. + v.remove() if 'deleted' not in vxlan: # Finally create the new interface @@ -105,7 +166,6 @@ def apply(vxlan): return None - if __name__ == '__main__': try: c = get_config() diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py index da64dd076..180ffa507 100755 --- a/src/conf_mode/interfaces-wireguard.py +++ b/src/conf_mode/interfaces-wireguard.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -28,6 +28,7 @@ from vyos.configverify import verify_vrf from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_mtu_ipv6 +from vyos.configverify import verify_mirror_redirect from vyos.ifconfig import WireGuardIf from vyos.util import check_kmod from vyos.util import check_port_availability @@ -45,17 +46,17 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'wireguard'] - wireguard = get_interface_dict(conf, base) + ifname, wireguard = get_interface_dict(conf, base) # Check if a port was changed - wireguard['port_changed'] = leaf_node_changed(conf, ['port']) + wireguard['port_changed'] = leaf_node_changed(conf, base + [ifname, 'port']) # Determine which Wireguard peer has been removed. # Peers can only be removed with their public key! dict = {} - tmp = node_changed(conf, ['peer'], key_mangling=('-', '_')) + tmp = node_changed(conf, base + [ifname, 'peer'], key_mangling=('-', '_')) for peer in (tmp or []): - public_key = leaf_node_changed(conf, ['peer', peer, 'public_key']) + public_key = leaf_node_changed(conf, base + [ifname, 'peer', peer, 'public_key']) if public_key: dict = dict_merge({'peer_remove' : {peer : {'public_key' : public_key[0]}}}, dict) wireguard.update(dict) @@ -70,6 +71,7 @@ def verify(wireguard): verify_mtu_ipv6(wireguard) verify_address(wireguard) verify_vrf(wireguard) + verify_mirror_redirect(wireguard) if 'private_key' not in wireguard: raise ConfigError('Wireguard private-key not defined') diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index af35b5f03..d34297063 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -27,6 +27,7 @@ from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_dhcpv6 from vyos.configverify import verify_source_interface +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.ifconfig import WiFiIf @@ -75,15 +76,19 @@ def get_config(config=None): conf = Config() base = ['interfaces', 'wireless'] - wifi = get_interface_dict(conf, base) + ifname, wifi = get_interface_dict(conf, base) # Cleanup "delete" default values when required user selectable values are # not defined at all - tmp = conf.get_config_dict([], key_mangling=('-', '_'), get_first_key=True) + tmp = conf.get_config_dict(base + [ifname], key_mangling=('-', '_'), + get_first_key=True) if not (dict_search('security.wpa.passphrase', tmp) or dict_search('security.wpa.radius', tmp)): if 'deleted' not in wifi: del wifi['security']['wpa'] + # if 'security' key is empty, drop it too + if len(wifi['security']) == 0: + del wifi['security'] # defaults include RADIUS server specifics per TAG node which need to be # added to individual RADIUS servers instead - so we can simply delete them @@ -189,6 +194,7 @@ def verify(wifi): verify_address(wifi) verify_vrf(wifi) + verify_mirror_redirect(wifi) # use common function to verify VLAN configuration verify_vlan_config(wifi) @@ -242,11 +248,11 @@ def generate(wifi): # render appropriate new config files depending on access-point or station mode if wifi['type'] == 'access-point': - render(hostapd_conf.format(**wifi), 'wifi/hostapd.conf.tmpl', + render(hostapd_conf.format(**wifi), 'wifi/hostapd.conf.j2', wifi) elif wifi['type'] == 'station': - render(wpa_suppl_conf.format(**wifi), 'wifi/wpa_supplicant.conf.tmpl', + render(wpa_suppl_conf.format(**wifi), 'wifi/wpa_supplicant.conf.j2', wifi) return None diff --git a/src/conf_mode/interfaces-wwan.py b/src/conf_mode/interfaces-wwan.py index f013e5411..e275ace84 100755 --- a/src/conf_mode/interfaces-wwan.py +++ b/src/conf_mode/interfaces-wwan.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -17,21 +17,29 @@ import os from sys import exit +from time import sleep from vyos.config import Config from vyos.configdict import get_interface_dict +from vyos.configdict import is_node_changed from vyos.configverify import verify_authentication from vyos.configverify import verify_interface_exists +from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_vrf from vyos.ifconfig import WWANIf from vyos.util import cmd from vyos.util import call from vyos.util import dict_search from vyos.util import DEVNULL +from vyos.util import is_systemd_service_active +from vyos.util import write_file from vyos import ConfigError from vyos import airbag airbag.enable() +service_name = 'ModemManager.service' +cron_script = '/etc/cron.d/vyos-wwan' + def get_config(config=None): """ Retrive CLI config as dictionary. Dictionary can never be empty, as at least the @@ -42,7 +50,41 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'wwan'] - wwan = get_interface_dict(conf, base) + ifname, wwan = get_interface_dict(conf, base) + + # We should only terminate the WWAN session if critical parameters change. + # All parameters that can be changed on-the-fly (like interface description) + # should not lead to a reconnect! + tmp = is_node_changed(conf, base + [ifname, 'address']) + if tmp: wwan.update({'shutdown_required': {}}) + + tmp = is_node_changed(conf, base + [ifname, 'apn']) + if tmp: wwan.update({'shutdown_required': {}}) + + tmp = is_node_changed(conf, base + [ifname, 'disable']) + if tmp: wwan.update({'shutdown_required': {}}) + + tmp = is_node_changed(conf, base + [ifname, 'vrf']) + if tmp: wwan.update({'shutdown_required': {}}) + + tmp = is_node_changed(conf, base + [ifname, 'authentication']) + if tmp: wwan.update({'shutdown_required': {}}) + + tmp = is_node_changed(conf, base + [ifname, 'ipv6', 'address', 'autoconf']) + if tmp: wwan.update({'shutdown_required': {}}) + + # We need to know the amount of other WWAN interfaces as ModemManager needs + # to be started or stopped. + conf.set_level(base) + _, wwan['other_interfaces'] = conf.get_config_dict([], key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True) + + # This if-clause is just to be sure - it will always evaluate to true + if ifname in wwan['other_interfaces']: + del wwan['other_interfaces'][ifname] + if len(wwan['other_interfaces']) == 0: + del wwan['other_interfaces'] return wwan @@ -57,42 +99,84 @@ def verify(wwan): verify_interface_exists(ifname) verify_authentication(wwan) verify_vrf(wwan) + verify_mirror_redirect(wwan) return None def generate(wwan): + if 'deleted' in wwan: + # We are the last WWAN interface - there are no other ones remaining + # thus the cronjob needs to go away, too + if 'other_interfaces' not in wwan: + if os.path.exists(cron_script): + os.unlink(cron_script) + return None + + # Install cron triggered helper script to re-dial WWAN interfaces on + # disconnect - e.g. happens during RF signal loss. The script watches every + # WWAN interface - so there is only one instance. + if not os.path.exists(cron_script): + write_file(cron_script, '*/5 * * * * root /usr/libexec/vyos/vyos-check-wwan.py') + return None def apply(wwan): - # we only need the modem number. wwan0 -> 0, wwan1 -> 1 - modem = wwan['ifname'].lstrip('wwan') - base_cmd = f'mmcli --modem {modem}' - # Number of bearers is limited - always disconnect first - cmd(f'{base_cmd} --simple-disconnect') + # ModemManager is required to dial WWAN connections - one instance is + # required to serve all modems. Activate ModemManager on first invocation + # of any WWAN interface. + if not is_systemd_service_active(service_name): + cmd(f'systemctl start {service_name}') + + counter = 100 + # Wait until a modem is detected and then we can continue + while counter > 0: + counter -= 1 + tmp = cmd('mmcli -L') + if tmp != 'No modems were found': + break + sleep(0.250) + + if 'shutdown_required' in wwan: + # we only need the modem number. wwan0 -> 0, wwan1 -> 1 + modem = wwan['ifname'].lstrip('wwan') + base_cmd = f'mmcli --modem {modem}' + # Number of bearers is limited - always disconnect first + cmd(f'{base_cmd} --simple-disconnect') w = WWANIf(wwan['ifname']) if 'deleted' in wwan or 'disable' in wwan: w.remove() + + # We are the last WWAN interface - there are no other WWAN interfaces + # remaining, thus we can stop ModemManager and free resources. + if 'other_interfaces' not in wwan: + cmd(f'systemctl stop {service_name}') + # Clean CRON helper script which is used for to re-connect when + # RF signal is lost + if os.path.exists(cron_script): + os.unlink(cron_script) + return None - ip_type = 'ipv4' - slaac = dict_search('ipv6.address.autoconf', wwan) != None - if 'address' in wwan: - if 'dhcp' in wwan['address'] and ('dhcpv6' in wwan['address'] or slaac): - ip_type = 'ipv4v6' - elif 'dhcpv6' in wwan['address'] or slaac: - ip_type = 'ipv6' - elif 'dhcp' in wwan['address']: - ip_type = 'ipv4' - - options = f'ip-type={ip_type},apn=' + wwan['apn'] - if 'authentication' in wwan: - options += ',user={user},password={password}'.format(**wwan['authentication']) - - command = f'{base_cmd} --simple-connect="{options}"' - call(command, stdout=DEVNULL) - w.update(wwan) + if 'shutdown_required' in wwan: + ip_type = 'ipv4' + slaac = dict_search('ipv6.address.autoconf', wwan) != None + if 'address' in wwan: + if 'dhcp' in wwan['address'] and ('dhcpv6' in wwan['address'] or slaac): + ip_type = 'ipv4v6' + elif 'dhcpv6' in wwan['address'] or slaac: + ip_type = 'ipv6' + elif 'dhcp' in wwan['address']: + ip_type = 'ipv4' + + options = f'ip-type={ip_type},apn=' + wwan['apn'] + if 'authentication' in wwan: + options += ',user={user},password={password}'.format(**wwan['authentication']) + command = f'{base_cmd} --simple-connect="{options}"' + call(command, stdout=DEVNULL) + + w.update(wwan) return None if __name__ == '__main__': diff --git a/src/conf_mode/lldp.py b/src/conf_mode/lldp.py index 082c3e128..c703c1fe0 100755 --- a/src/conf_mode/lldp.py +++ b/src/conf_mode/lldp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2017-2020 VyOS maintainers and contributors +# Copyright (C) 2017-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 @@ -15,19 +15,20 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -import re -from copy import deepcopy from sys import exit +from vyos.base import Warning from vyos.config import Config +from vyos.configdict import dict_merge from vyos.validate import is_addr_assigned from vyos.validate import is_loopback_addr from vyos.version import get_version_data -from vyos import ConfigError from vyos.util import call +from vyos.util import dict_search +from vyos.xml import defaults from vyos.template import render - +from vyos import ConfigError from vyos import airbag airbag.enable() @@ -35,178 +36,73 @@ config_file = "/etc/default/lldpd" vyos_config_file = "/etc/lldpd.d/01-vyos.conf" base = ['service', 'lldp'] -default_config_data = { - "options": '', - "interface_list": '', - "location": '' -} - -def get_options(config): - options = {} - config.set_level(base) - - options['listen_vlan'] = config.exists('listen-vlan') - options['mgmt_addr'] = [] - for addr in config.return_values('management-address'): - if is_addr_assigned(addr) and not is_loopback_addr(addr): - options['mgmt_addr'].append(addr) - else: - message = 'WARNING: LLDP management address {0} invalid - '.format(addr) - if is_loopback_addr(addr): - message += '(loopback address).' - else: - message += 'address not found.' - print(message) - - snmp = config.exists('snmp enable') - options["snmp"] = snmp - if snmp: - config.set_level('') - options["sys_snmp"] = config.exists('service snmp') - config.set_level(base) - - config.set_level(base + ['legacy-protocols']) - options['cdp'] = config.exists('cdp') - options['edp'] = config.exists('edp') - options['fdp'] = config.exists('fdp') - options['sonmp'] = config.exists('sonmp') - - # start with an unknown version information - version_data = get_version_data() - options['description'] = version_data['version'] - options['listen_on'] = [] - - return options - -def get_interface_list(config): - config.set_level(base) - intfs_names = config.list_nodes(['interface']) - if len(intfs_names) < 0: - return 0 - - interface_list = [] - for name in intfs_names: - config.set_level(base + ['interface', name]) - disable = config.exists(['disable']) - intf = { - 'name': name, - 'disable': disable - } - interface_list.append(intf) - return interface_list - - -def get_location_intf(config, name): - path = base + ['interface', name] - config.set_level(path) - - config.set_level(path + ['location']) - elin = '' - coordinate_based = {} - - if config.exists('elin'): - elin = config.return_value('elin') - - if config.exists('coordinate-based'): - config.set_level(path + ['location', 'coordinate-based']) - - coordinate_based['latitude'] = config.return_value(['latitude']) - coordinate_based['longitude'] = config.return_value(['longitude']) - - coordinate_based['altitude'] = '0' - if config.exists(['altitude']): - coordinate_based['altitude'] = config.return_value(['altitude']) - - coordinate_based['datum'] = 'WGS84' - if config.exists(['datum']): - coordinate_based['datum'] = config.return_value(['datum']) - - intf = { - 'name': name, - 'elin': elin, - 'coordinate_based': coordinate_based - - } - return intf - - -def get_location(config): - config.set_level(base) - intfs_names = config.list_nodes(['interface']) - if len(intfs_names) < 0: - return 0 - - if config.exists('disable'): - return 0 - - intfs_location = [] - for name in intfs_names: - intf = get_location_intf(config, name) - intfs_location.append(intf) - - return intfs_location - - def get_config(config=None): - lldp = deepcopy(default_config_data) if config: conf = config else: conf = Config() + if not conf.exists(base): - return None - else: - lldp['options'] = get_options(conf) - lldp['interface_list'] = get_interface_list(conf) - lldp['location'] = get_location(conf) + return {} - return lldp + lldp = conf.get_config_dict(base, key_mangling=('-', '_'), + get_first_key=True, no_tag_node_value_mangle=True) + if conf.exists(['service', 'snmp']): + lldp['system_snmp_enabled'] = '' + + version_data = get_version_data() + lldp['version'] = version_data['version'] + + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + # location coordinates have a default value + if 'interface' in lldp: + for interface, interface_config in lldp['interface'].items(): + default_values = defaults(base + ['interface']) + if dict_search('location.coordinate_based', interface_config) == None: + # no location specified - no need to add defaults + del default_values['location']['coordinate_based']['datum'] + del default_values['location']['coordinate_based']['altitude'] + + # cleanup default_values dictionary from inner to outer + # this might feel overkill here, but it does support easy extension + # in the future with additional default values + if len(default_values['location']['coordinate_based']) == 0: + del default_values['location']['coordinate_based'] + if len(default_values['location']) == 0: + del default_values['location'] + + lldp['interface'][interface] = dict_merge(default_values, + lldp['interface'][interface]) + + return lldp def verify(lldp): # bail out early - looks like removal from running config if lldp is None: return - # check location - for location in lldp['location']: - # check coordinate-based - if len(location['coordinate_based']) > 0: - # check longitude and latitude - if not location['coordinate_based']['longitude']: - raise ConfigError('Must define longitude for interface {0}'.format(location['name'])) - - if not location['coordinate_based']['latitude']: - raise ConfigError('Must define latitude for interface {0}'.format(location['name'])) - - if not re.match(r'^(\d+)(\.\d+)?[nNsS]$', location['coordinate_based']['latitude']): - raise ConfigError('Invalid location for interface {0}:\n' \ - 'latitude should be a number followed by S or N'.format(location['name'])) - - if not re.match(r'^(\d+)(\.\d+)?[eEwW]$', location['coordinate_based']['longitude']): - raise ConfigError('Invalid location for interface {0}:\n' \ - 'longitude should be a number followed by E or W'.format(location['name'])) - - # check altitude and datum if exist - if location['coordinate_based']['altitude']: - if not re.match(r'^[-+0-9\.]+$', location['coordinate_based']['altitude']): - raise ConfigError('Invalid location for interface {0}:\n' \ - 'altitude should be a positive or negative number'.format(location['name'])) - - if location['coordinate_based']['datum']: - if not re.match(r'^(WGS84|NAD83|MLLW)$', location['coordinate_based']['datum']): - raise ConfigError("Invalid location for interface {0}:\n' \ - 'datum should be WGS84, NAD83, or MLLW".format(location['name'])) - - # check elin - elif location['elin']: - if not re.match(r'^[0-9]{10,25}$', location['elin']): - raise ConfigError('Invalid location for interface {0}:\n' \ - 'ELIN number must be between 10-25 numbers'.format(location['name'])) + if 'management_address' in lldp: + for address in lldp['management_address']: + message = f'LLDP management address "{address}" is invalid' + if is_loopback_addr(address): + Warning(f'{message} - loopback address') + elif not is_addr_assigned(address): + Warning(f'{message} - not assigned to any interface') + + if 'interface' in lldp: + for interface, interface_config in lldp['interface'].items(): + # bail out early if no location info present in interface config + if 'location' not in interface_config: + continue + if 'coordinate_based' in interface_config['location']: + if not {'latitude', 'latitude'} <= set(interface_config['location']['coordinate_based']): + raise ConfigError(f'Must define both longitude and latitude for "{interface}" location!') # check options - if lldp['options']['snmp']: - if not lldp['options']['sys_snmp']: + if 'snmp' in lldp and 'enable' in lldp['snmp']: + if 'system_snmp_enabled' not in lldp: raise ConfigError('SNMP must be configured to enable LLDP SNMP') @@ -215,29 +111,17 @@ def generate(lldp): if lldp is None: return - # generate listen on interfaces - for intf in lldp['interface_list']: - tmp = '' - # add exclamation mark if interface is disabled - if intf['disable']: - tmp = '!' - - tmp += intf['name'] - lldp['options']['listen_on'].append(tmp) - - # generate /etc/default/lldpd - render(config_file, 'lldp/lldpd.tmpl', lldp) - # generate /etc/lldpd.d/01-vyos.conf - render(vyos_config_file, 'lldp/vyos.conf.tmpl', lldp) - + render(config_file, 'lldp/lldpd.j2', lldp) + render(vyos_config_file, 'lldp/vyos.conf.j2', lldp) def apply(lldp): + systemd_service = 'lldpd.service' if lldp: # start/restart lldp service - call('systemctl restart lldpd.service') + call(f'systemctl restart {systemd_service}') else: # LLDP service has been terminated - call('systemctl stop lldpd.service') + call(f'systemctl stop {systemd_service}') if os.path.isfile(config_file): os.unlink(config_file) if os.path.isfile(vyos_config_file): diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py index 59939d0fb..85819a77e 100755 --- a/src/conf_mode/nat.py +++ b/src/conf_mode/nat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -23,11 +23,13 @@ from platform import release as kernel_version from sys import exit from netifaces import interfaces +from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render from vyos.template import is_ip_network from vyos.util import cmd +from vyos.util import run from vyos.util import check_kmod from vyos.util import dict_search from vyos.validate import is_addr_assigned @@ -42,7 +44,7 @@ if LooseVersion(kernel_version()) > LooseVersion('5.1'): else: k_mod = ['nft_nat', 'nft_chain_nat_ipv4'] -iptables_nat_config = '/tmp/vyos-nat-rules.nft' +nftables_nat_config = '/tmp/vyos-nat-rules.nft' def get_handler(json, chain, target): """ Get nftable rule handler number of given chain/target combination. @@ -93,7 +95,6 @@ def get_config(config=None): nat[direction]['rule'][rule] = dict_merge(default_values, nat[direction]['rule'][rule]) - # read in current nftable (once) for further processing tmp = cmd('nft -j list table raw') nftable_json = json.loads(tmp) @@ -106,9 +107,9 @@ def get_config(config=None): nat['helper_functions'] = 'remove' # Retrieve current table handler positions - nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_HELPER') + nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_HELPER') nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'NAT_CONNTRACK') - nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_HELPER') + nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_HELPER') nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'NAT_CONNTRACK') nat['deleted'] = '' return nat @@ -119,10 +120,10 @@ def get_config(config=None): nat['helper_functions'] = 'add' # Retrieve current table handler positions - nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_IGNORE') - nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_PREROUTING_HOOK') - nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_IGNORE') - nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_OUTPUT_HOOK') + nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_IGNORE') + nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_PREROUTING_HOOK') + nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_IGNORE') + nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_OUTPUT_HOOK') return nat @@ -142,14 +143,14 @@ def verify(nat): raise ConfigError(f'{err_msg} outbound-interface not specified') if config['outbound_interface'] not in 'any' and config['outbound_interface'] not in interfaces(): - print(f'WARNING: rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system') + Warning(f'rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system') addr = dict_search('translation.address', config) if addr != None: if addr != 'masquerade' and not is_ip_network(addr): for ip in addr.split('-'): if not is_addr_assigned(ip): - print(f'WARNING: IP address {ip} does not exist on the system!') + Warning(f'IP address {ip} does not exist on the system!') elif 'exclude' not in config: raise ConfigError(f'{err_msg}\n' \ 'translation address not specified') @@ -167,7 +168,7 @@ def verify(nat): 'inbound-interface not specified') else: if config['inbound_interface'] not in 'any' and config['inbound_interface'] not in interfaces(): - print(f'WARNING: rule "{rule}" interface "{config["inbound_interface"]}" does not exist on this system') + Warning(f'rule "{rule}" interface "{config["inbound_interface"]}" does not exist on this system') if dict_search('translation.address', config) == None and 'exclude' not in config: @@ -180,14 +181,21 @@ def verify(nat): return None def generate(nat): - render(iptables_nat_config, 'firewall/nftables-nat.tmpl', nat, - permission=0o755) + render(nftables_nat_config, 'firewall/nftables-nat.j2', nat) + + # dry-run newly generated configuration + tmp = run(f'nft -c -f {nftables_nat_config}') + if tmp > 0: + if os.path.exists(nftables_nat_config): + os.unlink(nftables_nat_config) + raise ConfigError('Configuration file errors encountered!') + return None def apply(nat): - cmd(f'{iptables_nat_config}') - if os.path.isfile(iptables_nat_config): - os.unlink(iptables_nat_config) + cmd(f'nft -f {nftables_nat_config}') + if os.path.isfile(nftables_nat_config): + os.unlink(nftables_nat_config) return None diff --git a/src/conf_mode/nat66.py b/src/conf_mode/nat66.py index fb376a434..0972151a0 100755 --- a/src/conf_mode/nat66.py +++ b/src/conf_mode/nat66.py @@ -21,6 +21,7 @@ import os from sys import exit from netifaces import interfaces +from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge from vyos.template import render @@ -35,7 +36,7 @@ airbag.enable() k_mod = ['nft_nat', 'nft_chain_nat'] -iptables_nat_config = '/tmp/vyos-nat66-rules.nft' +nftables_nat66_config = '/tmp/vyos-nat66-rules.nft' ndppd_config = '/run/ndppd/ndppd.conf' def get_handler(json, chain, target): @@ -79,9 +80,9 @@ def get_config(config=None): if not conf.exists(base): nat['helper_functions'] = 'remove' - nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_HELPER') + nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_HELPER') nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'NAT_CONNTRACK') - nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_HELPER') + nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_HELPER') nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'NAT_CONNTRACK') nat['deleted'] = '' return nat @@ -92,10 +93,10 @@ def get_config(config=None): nat['helper_functions'] = 'add' # Retrieve current table handler positions - nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_IGNORE') - nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_PREROUTING_HOOK') - nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_IGNORE') - nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'VYATTA_CT_OUTPUT_HOOK') + nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_IGNORE') + nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'VYOS_CT_PREROUTING_HOOK') + nat['out_ct_ignore'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_IGNORE') + nat['out_ct_conntrack'] = get_handler(condensed_json, 'OUTPUT', 'VYOS_CT_OUTPUT_HOOK') else: nat['helper_functions'] = 'has' @@ -117,12 +118,12 @@ def verify(nat): raise ConfigError(f'{err_msg} outbound-interface not specified') if config['outbound_interface'] not in interfaces(): - raise ConfigError(f'WARNING: rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system') + raise ConfigError(f'rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system') addr = dict_search('translation.address', config) if addr != None: if addr != 'masquerade' and not is_ipv6(addr): - raise ConfigError(f'Warning: IPv6 address {addr} is not a valid address') + raise ConfigError(f'IPv6 address {addr} is not a valid address') else: raise ConfigError(f'{err_msg} translation address not specified') @@ -140,27 +141,27 @@ def verify(nat): 'inbound-interface not specified') else: if config['inbound_interface'] not in 'any' and config['inbound_interface'] not in interfaces(): - print(f'WARNING: rule "{rule}" interface "{config["inbound_interface"]}" does not exist on this system') + Warning(f'rule "{rule}" interface "{config["inbound_interface"]}" does not exist on this system') return None def generate(nat): - render(iptables_nat_config, 'firewall/nftables-nat66.tmpl', nat, permission=0o755) - render(ndppd_config, 'ndppd/ndppd.conf.tmpl', nat, permission=0o755) + render(nftables_nat66_config, 'firewall/nftables-nat66.j2', nat, permission=0o755) + render(ndppd_config, 'ndppd/ndppd.conf.j2', nat, permission=0o755) return None def apply(nat): if not nat: return None - cmd(f'{iptables_nat_config}') + cmd(f'{nftables_nat66_config}') if 'deleted' in nat or not dict_search('source.rule', nat): cmd('systemctl stop ndppd') if os.path.isfile(ndppd_config): os.unlink(ndppd_config) else: cmd('systemctl restart ndppd') - if os.path.isfile(iptables_nat_config): - os.unlink(iptables_nat_config) + if os.path.isfile(nftables_nat66_config): + os.unlink(nftables_nat66_config) return None diff --git a/src/conf_mode/netns.py b/src/conf_mode/netns.py new file mode 100755 index 000000000..0924eb616 --- /dev/null +++ b/src/conf_mode/netns.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from sys import exit +from tempfile import NamedTemporaryFile + +from vyos.config import Config +from vyos.configdict import node_changed +from vyos.ifconfig import Interface +from vyos.util import call +from vyos.util import dict_search +from vyos.util import get_interface_config +from vyos import ConfigError +from vyos import airbag +airbag.enable() + + +def netns_interfaces(c, match): + """ + get NETNS bound interfaces + """ + matched = [] + old_level = c.get_level() + c.set_level(['interfaces']) + section = c.get_config_dict([], get_first_key=True) + for type in section: + interfaces = section[type] + for name in interfaces: + interface = interfaces[name] + if 'netns' in interface: + v = interface.get('netns', '') + if v == match: + matched.append(name) + + c.set_level(old_level) + return matched + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + + base = ['netns'] + netns = conf.get_config_dict(base, get_first_key=True, + no_tag_node_value_mangle=True) + + # determine which NETNS has been removed + for name in node_changed(conf, base + ['name']): + if 'netns_remove' not in netns: + netns.update({'netns_remove' : {}}) + + netns['netns_remove'][name] = {} + # get NETNS bound interfaces + interfaces = netns_interfaces(conf, name) + if interfaces: netns['netns_remove'][name]['interface'] = interfaces + + return netns + +def verify(netns): + # ensure NETNS is not assigned to any interface + if 'netns_remove' in netns: + for name, config in netns['netns_remove'].items(): + if 'interface' in config: + raise ConfigError(f'Can not remove NETNS "{name}", it still has '\ + f'member interfaces!') + + if 'name' in netns: + for name, config in netns['name'].items(): + print(name) + + return None + + +def generate(netns): + if not netns: + return None + + return None + + +def apply(netns): + + for tmp in (dict_search('netns_remove', netns) or []): + if os.path.isfile(f'/run/netns/{tmp}'): + call(f'ip netns del {tmp}') + + if 'name' in netns: + for name, config in netns['name'].items(): + if not os.path.isfile(f'/run/netns/{name}'): + call(f'ip netns add {name}') + + 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 52070aabc..0d6ec9ace 100755 --- a/src/conf_mode/ntp.py +++ b/src/conf_mode/ntp.py @@ -56,8 +56,8 @@ def generate(ntp): if not ntp: return None - render(config_file, 'ntp/ntpd.conf.tmpl', ntp) - render(systemd_override, 'ntp/override.conf.tmpl', ntp) + render(config_file, 'ntp/ntpd.conf.j2', ntp) + render(systemd_override, 'ntp/override.conf.j2', ntp) return None diff --git a/src/conf_mode/policy-local-route.py b/src/conf_mode/policy-local-route.py index 539189442..3f834f55c 100755 --- a/src/conf_mode/policy-local-route.py +++ b/src/conf_mode/policy-local-route.py @@ -18,6 +18,7 @@ import os from sys import exit +from netifaces import interfaces from vyos.config import Config from vyos.configdict import dict_merge from vyos.configdict import node_changed @@ -35,35 +36,92 @@ def get_config(config=None): conf = config else: conf = Config() - base = ['policy', 'local-route'] + base = ['policy'] + pbr = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) - # delete policy local-route - dict = {} - tmp = node_changed(conf, ['policy', 'local-route', 'rule'], key_mangling=('-', '_')) - if tmp: - for rule in (tmp or []): - src = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'source']) - fwmk = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'fwmark']) - if src: - dict = dict_merge({'rule_remove' : {rule : {'source' : src}}}, dict) - pbr.update(dict) - if fwmk: - dict = dict_merge({'rule_remove' : {rule : {'fwmark' : fwmk}}}, dict) + for route in ['local_route', 'local_route6']: + dict_id = 'rule_remove' if route == 'local_route' else 'rule6_remove' + route_key = 'local-route' if route == 'local_route' else 'local-route6' + base_rule = base + [route_key, 'rule'] + + # delete policy local-route + dict = {} + tmp = node_changed(conf, base_rule, key_mangling=('-', '_')) + if tmp: + for rule in (tmp or []): + src = leaf_node_changed(conf, base_rule + [rule, 'source']) + fwmk = leaf_node_changed(conf, base_rule + [rule, 'fwmark']) + iif = leaf_node_changed(conf, base_rule + [rule, 'inbound-interface']) + dst = leaf_node_changed(conf, base_rule + [rule, 'destination']) + rule_def = {} + if src: + rule_def = dict_merge({'source' : src}, rule_def) + if fwmk: + rule_def = dict_merge({'fwmark' : fwmk}, rule_def) + if iif: + rule_def = dict_merge({'inbound_interface' : iif}, rule_def) + if dst: + rule_def = dict_merge({'destination' : dst}, rule_def) + dict = dict_merge({dict_id : {rule : rule_def}}, dict) pbr.update(dict) - # delete policy local-route rule x source x.x.x.x - # delete policy local-route rule x fwmark x - if 'rule' in pbr: - for rule in pbr['rule']: - src = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'source']) - fwmk = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'fwmark']) - if src: - dict = dict_merge({'rule_remove' : {rule : {'source' : src}}}, dict) - pbr.update(dict) - if fwmk: - dict = dict_merge({'rule_remove' : {rule : {'fwmark' : fwmk}}}, dict) - pbr.update(dict) + if not route in pbr: + continue + + # delete policy local-route rule x source x.x.x.x + # delete policy local-route rule x fwmark x + # delete policy local-route rule x destination x.x.x.x + if 'rule' in pbr[route]: + for rule, rule_config in pbr[route]['rule'].items(): + src = leaf_node_changed(conf, base_rule + [rule, 'source']) + fwmk = leaf_node_changed(conf, base_rule + [rule, 'fwmark']) + iif = leaf_node_changed(conf, base_rule + [rule, 'inbound-interface']) + dst = leaf_node_changed(conf, base_rule + [rule, 'destination']) + # keep track of changes in configuration + # otherwise we might remove an existing node although nothing else has changed + changed = False + + rule_def = {} + # src is None if there are no changes to src + if src is None: + # if src hasn't changed, include it in the removal selector + # if a new selector is added, we have to remove all previous rules without this selector + # to make sure we remove all previous rules with this source(s), it will be included + if 'source' in rule_config: + rule_def = dict_merge({'source': rule_config['source']}, rule_def) + else: + # if src is not None, it's previous content will be returned + # this can be an empty array if it's just being set, or the previous value + # either way, something has to be changed and we only want to remove previous values + changed = True + # set the old value for removal if it's not empty + if len(src) > 0: + rule_def = dict_merge({'source' : src}, rule_def) + if fwmk is None: + if 'fwmark' in rule_config: + rule_def = dict_merge({'fwmark': rule_config['fwmark']}, rule_def) + else: + changed = True + if len(fwmk) > 0: + rule_def = dict_merge({'fwmark' : fwmk}, rule_def) + if iif is None: + if 'inbound_interface' in rule_config: + rule_def = dict_merge({'inbound_interface': rule_config['inbound_interface']}, rule_def) + else: + changed = True + if len(iif) > 0: + rule_def = dict_merge({'inbound_interface' : iif}, rule_def) + if dst is None: + if 'destination' in rule_config: + rule_def = dict_merge({'destination': rule_config['destination']}, rule_def) + else: + changed = True + if len(dst) > 0: + rule_def = dict_merge({'destination' : dst}, rule_def) + if changed: + dict = dict_merge({dict_id : {rule : rule_def}}, dict) + pbr.update(dict) return pbr @@ -72,13 +130,25 @@ def verify(pbr): if not pbr: return None - if 'rule' in pbr: - for rule in pbr['rule']: - if 'source' not in pbr['rule'][rule] and 'fwmark' not in pbr['rule'][rule]: - raise ConfigError('Source address or fwmark is required!') - else: - if 'set' not in pbr['rule'][rule] or 'table' not in pbr['rule'][rule]['set']: - raise ConfigError('Table set is required!') + for route in ['local_route', 'local_route6']: + if not route in pbr: + continue + + pbr_route = pbr[route] + if 'rule' in pbr_route: + for rule in pbr_route['rule']: + if 'source' not in pbr_route['rule'][rule] \ + and 'destination' not in pbr_route['rule'][rule] \ + and 'fwmark' not in pbr_route['rule'][rule] \ + and 'inbound_interface' not in pbr_route['rule'][rule]: + raise ConfigError('Source or destination address or fwmark or inbound-interface is required!') + else: + if 'set' not in pbr_route['rule'][rule] or 'table' not in pbr_route['rule'][rule]['set']: + raise ConfigError('Table set is required!') + if 'inbound_interface' in pbr_route['rule'][rule]: + interface = pbr_route['rule'][rule]['inbound_interface'] + if interface not in interfaces(): + raise ConfigError(f'Interface "{interface}" does not exist') return None @@ -93,36 +163,51 @@ def apply(pbr): return None # Delete old rule if needed - if 'rule_remove' in pbr: - for rule in pbr['rule_remove']: - if 'source' in pbr['rule_remove'][rule]: - for src in pbr['rule_remove'][rule]['source']: - call(f'ip rule del prio {rule} from {src}') - if 'fwmark' in pbr['rule_remove'][rule]: - for fwmk in pbr['rule_remove'][rule]['fwmark']: - call(f'ip rule del prio {rule} from all fwmark {fwmk}') + for rule_rm in ['rule_remove', 'rule6_remove']: + if rule_rm in pbr: + v6 = " -6" if rule_rm == 'rule6_remove' else "" + for rule, rule_config in pbr[rule_rm].items(): + rule_config['source'] = rule_config['source'] if 'source' in rule_config else [''] + for src in rule_config['source']: + f_src = '' if src == '' else f' from {src} ' + rule_config['destination'] = rule_config['destination'] if 'destination' in rule_config else [''] + for dst in rule_config['destination']: + f_dst = '' if dst == '' else f' to {dst} ' + rule_config['fwmark'] = rule_config['fwmark'] if 'fwmark' in rule_config else [''] + for fwmk in rule_config['fwmark']: + f_fwmk = '' if fwmk == '' else f' fwmark {fwmk} ' + rule_config['inbound_interface'] = rule_config['inbound_interface'] if 'inbound_interface' in rule_config else [''] + for iif in rule_config['inbound_interface']: + f_iif = '' if iif == '' else f' iif {iif} ' + call(f'ip{v6} rule del prio {rule} {f_src}{f_dst}{f_fwmk}{f_iif}') # Generate new config - if 'rule' in pbr: - for rule in pbr['rule']: - table = pbr['rule'][rule]['set']['table'] - # Only source in the rule - # set policy local-route rule 100 source '203.0.113.1' - if 'source' in pbr['rule'][rule] and not 'fwmark' in pbr['rule'][rule]: - for src in pbr['rule'][rule]['source']: - call(f'ip rule add prio {rule} from {src} lookup {table}') - # Only fwmark in the rule - # set policy local-route rule 101 fwmark '23' - if 'fwmark' in pbr['rule'][rule] and not 'source' in pbr['rule'][rule]: - fwmk = pbr['rule'][rule]['fwmark'] - call(f'ip rule add prio {rule} from all fwmark {fwmk} lookup {table}') - # Source and fwmark in the rule - # set policy local-route rule 100 source '203.0.113.1' - # set policy local-route rule 100 fwmark '23' - if 'source' in pbr['rule'][rule] and 'fwmark' in pbr['rule'][rule]: - fwmk = pbr['rule'][rule]['fwmark'] - for src in pbr['rule'][rule]['source']: - call(f'ip rule add prio {rule} from {src} fwmark {fwmk} lookup {table}') + for route in ['local_route', 'local_route6']: + if not route in pbr: + continue + + v6 = " -6" if route == 'local_route6' else "" + + pbr_route = pbr[route] + if 'rule' in pbr_route: + for rule, rule_config in pbr_route['rule'].items(): + table = rule_config['set']['table'] + + rule_config['source'] = rule_config['source'] if 'source' in rule_config else ['all'] + for src in rule_config['source'] or ['all']: + f_src = '' if src == '' else f' from {src} ' + rule_config['destination'] = rule_config['destination'] if 'destination' in rule_config else ['all'] + for dst in rule_config['destination']: + f_dst = '' if dst == '' else f' to {dst} ' + f_fwmk = '' + if 'fwmark' in rule_config: + fwmk = rule_config['fwmark'] + f_fwmk = f' fwmark {fwmk} ' + f_iif = '' + if 'inbound_interface' in rule_config: + iif = rule_config['inbound_interface'] + f_iif = f' iif {iif} ' + call(f'ip{v6} rule add prio {rule} {f_src}{f_dst}{f_fwmk}{f_iif} lookup {table}') return None diff --git a/src/conf_mode/policy-route-interface.py b/src/conf_mode/policy-route-interface.py new file mode 100755 index 000000000..1108aebe6 --- /dev/null +++ b/src/conf_mode/policy-route-interface.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import re + +from sys import argv +from sys import exit + +from vyos.config import Config +from vyos.ifconfig import Section +from vyos.template import render +from vyos.util import cmd +from vyos import ConfigError +from vyos import airbag +airbag.enable() + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + + ifname = argv[1] + ifpath = Section.get_config_path(ifname) + if_policy_path = f'interfaces {ifpath} policy' + + if_policy = conf.get_config_dict(if_policy_path, key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + + if_policy['ifname'] = ifname + if_policy['policy'] = conf.get_config_dict(['policy'], key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + + return if_policy + +def verify(if_policy): + # bail out early - looks like removal from running config + if not if_policy: + return None + + for route in ['route', 'route6']: + if route in if_policy: + if route not in if_policy['policy']: + raise ConfigError('Policy route not configured') + + route_name = if_policy[route] + + if route_name not in if_policy['policy'][route]: + raise ConfigError(f'Invalid policy route name "{name}"') + + return None + +def generate(if_policy): + return None + +def cleanup_rule(table, chain, ifname, new_name=None): + results = cmd(f'nft -a list chain {table} {chain}').split("\n") + retval = None + for line in results: + if f'ifname "{ifname}"' in line: + if new_name and f'jump {new_name}' in line: + # new_name is used to clear rules for any previously referenced chains + # returns true when rule exists and doesn't need to be created + retval = True + continue + + handle_search = re.search('handle (\d+)', line) + if handle_search: + cmd(f'nft delete rule {table} {chain} handle {handle_search[1]}') + return retval + +def apply(if_policy): + ifname = if_policy['ifname'] + + route_chain = 'VYOS_PBR_PREROUTING' + ipv6_route_chain = 'VYOS_PBR6_PREROUTING' + + if 'route' in if_policy: + name = 'VYOS_PBR_' + if_policy['route'] + rule_exists = cleanup_rule('ip mangle', route_chain, ifname, name) + + if not rule_exists: + cmd(f'nft insert rule ip mangle {route_chain} iifname {ifname} counter jump {name}') + else: + cleanup_rule('ip mangle', route_chain, ifname) + + if 'route6' in if_policy: + name = 'VYOS_PBR6_' + if_policy['route6'] + rule_exists = cleanup_rule('ip6 mangle', ipv6_route_chain, ifname, name) + + if not rule_exists: + cmd(f'nft insert rule ip6 mangle {ipv6_route_chain} iifname {ifname} counter jump {name}') + else: + cleanup_rule('ip6 mangle', ipv6_route_chain, ifname) + + 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/policy-route.py b/src/conf_mode/policy-route.py new file mode 100755 index 000000000..5de341beb --- /dev/null +++ b/src/conf_mode/policy-route.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import re + +from json import loads +from sys import exit + +from vyos.base import Warning +from vyos.config import Config +from vyos.template import render +from vyos.util import cmd +from vyos.util import dict_search_args +from vyos.util import run +from vyos import ConfigError +from vyos import airbag +airbag.enable() + +mark_offset = 0x7FFFFFFF +nftables_conf = '/run/nftables_policy.conf' + +preserve_chains = [ + 'VYOS_PBR_PREROUTING', + 'VYOS_PBR_POSTROUTING', + 'VYOS_PBR6_PREROUTING', + 'VYOS_PBR6_POSTROUTING' +] + +valid_groups = [ + 'address_group', + 'network_group', + 'port_group' +] + +def get_policy_interfaces(conf): + out = {} + interfaces = conf.get_config_dict(['interfaces'], key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + def find_interfaces(iftype_conf, output={}, prefix=''): + for ifname, if_conf in iftype_conf.items(): + if 'policy' in if_conf: + output[prefix + ifname] = if_conf['policy'] + for vif in ['vif', 'vif_s', 'vif_c']: + if vif in if_conf: + output.update(find_interfaces(if_conf[vif], output, f'{prefix}{ifname}.')) + return output + for iftype, iftype_conf in interfaces.items(): + out.update(find_interfaces(iftype_conf)) + return out + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + base = ['policy'] + + policy = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + + policy['firewall_group'] = conf.get_config_dict(['firewall', 'group'], key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + policy['interfaces'] = get_policy_interfaces(conf) + + return policy + +def verify_rule(policy, name, rule_conf, ipv6): + icmp = 'icmp' if not ipv6 else 'icmpv6' + if icmp in rule_conf: + icmp_defined = False + if 'type_name' in rule_conf[icmp]: + icmp_defined = True + if 'code' in rule_conf[icmp] or 'type' in rule_conf[icmp]: + raise ConfigError(f'{name} rule {rule_id}: Cannot use ICMP type/code with ICMP type-name') + if 'code' in rule_conf[icmp]: + icmp_defined = True + if 'type' not in rule_conf[icmp]: + raise ConfigError(f'{name} rule {rule_id}: ICMP code can only be defined if ICMP type is defined') + if 'type' in rule_conf[icmp]: + icmp_defined = True + + if icmp_defined and 'protocol' not in rule_conf or rule_conf['protocol'] != icmp: + raise ConfigError(f'{name} rule {rule_id}: ICMP type/code or type-name can only be defined if protocol is ICMP') + + if 'set' in rule_conf: + if 'tcp_mss' in rule_conf['set']: + tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags') + if not tcp_flags or 'syn' not in tcp_flags: + raise ConfigError(f'{name} rule {rule_id}: TCP SYN flag must be set to modify TCP-MSS') + + tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags') + if tcp_flags: + if dict_search_args(rule_conf, 'protocol') != 'tcp': + raise ConfigError('Protocol must be tcp when specifying tcp flags') + + not_flags = dict_search_args(rule_conf, 'tcp', 'flags', 'not') + if not_flags: + duplicates = [flag for flag in tcp_flags if flag in not_flags] + if duplicates: + raise ConfigError(f'Cannot match a tcp flag as set and not set') + + for side in ['destination', 'source']: + if side in rule_conf: + side_conf = rule_conf[side] + + if 'group' in side_conf: + if {'address_group', 'network_group'} <= set(side_conf['group']): + raise ConfigError('Only one address-group or network-group can be specified') + + for group in valid_groups: + if group in side_conf['group']: + group_name = side_conf['group'][group] + + if group_name.startswith('!'): + group_name = group_name[1:] + + fw_group = f'ipv6_{group}' if ipv6 and group in ['address_group', 'network_group'] else group + error_group = fw_group.replace("_", "-") + group_obj = dict_search_args(policy['firewall_group'], fw_group, group_name) + + if group_obj is None: + raise ConfigError(f'Invalid {error_group} "{group_name}" on policy route rule') + + if not group_obj: + Warning(f'{error_group} "{group_name}" has no members') + + if 'port' in side_conf or dict_search_args(side_conf, 'group', 'port_group'): + if 'protocol' not in rule_conf: + raise ConfigError('Protocol must be defined if specifying a port or port-group') + + if rule_conf['protocol'] not in ['tcp', 'udp', 'tcp_udp']: + raise ConfigError('Protocol must be tcp, udp, or tcp_udp when specifying a port or port-group') + +def verify(policy): + for route in ['route', 'route6']: + ipv6 = route == 'route6' + if route in policy: + for name, pol_conf in policy[route].items(): + if 'rule' in pol_conf: + for rule_id, rule_conf in pol_conf['rule'].items(): + verify_rule(policy, name, rule_conf, ipv6) + + for ifname, if_policy in policy['interfaces'].items(): + name = dict_search_args(if_policy, 'route') + ipv6_name = dict_search_args(if_policy, 'route6') + + if name and not dict_search_args(policy, 'route', name): + raise ConfigError(f'Policy route "{name}" is still referenced on interface {ifname}') + + if ipv6_name and not dict_search_args(policy, 'route6', ipv6_name): + raise ConfigError(f'Policy route6 "{ipv6_name}" is still referenced on interface {ifname}') + + return None + +def cleanup_rule(table, jump_chain): + commands = [] + results = cmd(f'nft -a list table {table}').split("\n") + for line in results: + if f'jump {jump_chain}' in line: + handle_search = re.search('handle (\d+)', line) + if handle_search: + commands.append(f'delete rule {table} {chain} handle {handle_search[1]}') + return commands + +def cleanup_commands(policy): + commands = [] + for table in ['ip mangle', 'ip6 mangle']: + json_str = cmd(f'nft -j list table {table}') + obj = loads(json_str) + if 'nftables' not in obj: + continue + for item in obj['nftables']: + if 'chain' in item: + chain = item['chain']['name'] + if not chain.startswith("VYOS_PBR"): + continue + if chain not in preserve_chains: + if table == 'ip mangle' and dict_search_args(policy, 'route', chain.replace("VYOS_PBR_", "", 1)): + commands.append(f'flush chain {table} {chain}') + elif table == 'ip6 mangle' and dict_search_args(policy, 'route6', chain.replace("VYOS_PBR6_", "", 1)): + commands.append(f'flush chain {table} {chain}') + else: + commands += cleanup_rule(table, chain) + commands.append(f'delete chain {table} {chain}') + return commands + +def generate(policy): + if not os.path.exists(nftables_conf): + policy['first_install'] = True + else: + policy['cleanup_commands'] = cleanup_commands(policy) + + render(nftables_conf, 'firewall/nftables-policy.j2', policy) + return None + +def apply_table_marks(policy): + for route in ['route', 'route6']: + if route in policy: + cmd_str = 'ip' if route == 'route' else 'ip -6' + tables = [] + for name, pol_conf in policy[route].items(): + if 'rule' in pol_conf: + for rule_id, rule_conf in pol_conf['rule'].items(): + set_table = dict_search_args(rule_conf, 'set', 'table') + if set_table: + if set_table == 'main': + set_table = '254' + if set_table in tables: + continue + tables.append(set_table) + table_mark = mark_offset - int(set_table) + cmd(f'{cmd_str} rule add pref {set_table} fwmark {table_mark} table {set_table}') + +def cleanup_table_marks(): + for cmd_str in ['ip', 'ip -6']: + json_rules = cmd(f'{cmd_str} -j -N rule list') + rules = loads(json_rules) + for rule in rules: + if 'fwmark' not in rule or 'table' not in rule: + continue + fwmark = rule['fwmark'] + table = int(rule['table']) + if fwmark[:2] == '0x': + fwmark = int(fwmark, 16) + if (int(fwmark) == (mark_offset - table)): + cmd(f'{cmd_str} rule del fwmark {fwmark} table {table}') + +def apply(policy): + install_result = run(f'nft -f {nftables_conf}') + if install_result == 1: + raise ConfigError('Failed to apply policy based routing') + + if 'first_install' not in policy: + cleanup_table_marks() + + apply_table_marks(policy) + + 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/policy.py b/src/conf_mode/policy.py index 1a03d520b..ef6008140 100755 --- a/src/conf_mode/policy.py +++ b/src/conf_mode/policy.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -87,6 +87,7 @@ def verify(policy): # human readable instance name (hypen instead of underscore) policy_hr = policy_type.replace('_', '-') + entries = [] for rule, rule_config in instance_config['rule'].items(): mandatory_error = f'must be specified for "{policy_hr} {instance} rule {rule}"!' if 'action' not in rule_config: @@ -113,6 +114,10 @@ def verify(policy): if 'prefix' not in rule_config: raise ConfigError(f'A prefix {mandatory_error}') + if rule_config in entries: + raise ConfigError(f'Rule "{rule}" contains a duplicate prefix definition!') + entries.append(rule_config) + # route-maps tend to be a bit more complex so they get their own verify() section if 'route_map' in policy: @@ -171,10 +176,8 @@ def verify(policy): def generate(policy): if not policy: - policy['new_frr_config'] = '' return None - - policy['new_frr_config'] = render_to_string('frr/policy.frr.tmpl', policy) + policy['new_frr_config'] = render_to_string('frr/policy.frr.j2', policy) return None def apply(policy): @@ -190,8 +193,9 @@ def apply(policy): frr_cfg.modify_section(r'^bgp community-list .*') frr_cfg.modify_section(r'^bgp extcommunity-list .*') frr_cfg.modify_section(r'^bgp large-community-list .*') - frr_cfg.modify_section(r'^route-map .*') - frr_cfg.add_before('^line vty', policy['new_frr_config']) + frr_cfg.modify_section(r'^route-map .*', stop_pattern='^exit', remove_stop_mark=True) + if 'new_frr_config' in policy: + frr_cfg.add_before(frr.default_add_before, policy['new_frr_config']) frr_cfg.commit_configuration(bgp_daemon) # The route-map used for the FIB (zebra) is part of the zebra daemon @@ -200,19 +204,11 @@ def apply(policy): frr_cfg.modify_section(r'^ipv6 access-list .*') frr_cfg.modify_section(r'^ip prefix-list .*') frr_cfg.modify_section(r'^ipv6 prefix-list .*') - frr_cfg.modify_section(r'^route-map .*') - frr_cfg.add_before('^line vty', policy['new_frr_config']) + frr_cfg.modify_section(r'^route-map .*', stop_pattern='^exit', remove_stop_mark=True) + if 'new_frr_config' in policy: + frr_cfg.add_before(frr.default_add_before, policy['new_frr_config']) frr_cfg.commit_configuration(zebra_daemon) - # If FRR config is blank, rerun the blank commit x times due to frr-reload - # behavior/bug not properly clearing out on one commit. - if policy['new_frr_config'] == '': - for a in range(5): - frr_cfg.commit_configuration(zebra_daemon) - - # Save configuration to /run/frr/config/frr.conf - frr.save_configuration() - return None if __name__ == '__main__': diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 539fd7b8e..0436abaf9 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -16,10 +16,9 @@ import os -from sys import exit - from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configverify import verify_vrf from vyos.template import is_ipv6 from vyos.template import render_to_string from vyos.validate import is_ipv6_link_local @@ -35,8 +34,9 @@ def get_config(config=None): else: conf = Config() base = ['protocols', 'bfd'] - bfd = conf.get_config_dict(base, get_first_key=True) - + bfd = conf.get_config_dict(base, key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True) # Bail out early if configuration tree does not exist if not conf.exists(base): return bfd @@ -79,28 +79,37 @@ def verify(bfd): # multihop and echo-mode cannot be used together if 'echo_mode' in peer_config: - raise ConfigError('Multihop and echo-mode cannot be used together') + raise ConfigError('BFD multihop and echo-mode cannot be used together') # multihop doesn't accept interface names if 'source' in peer_config and 'interface' in peer_config['source']: - raise ConfigError('Multihop and source interface cannot be used together') + raise ConfigError('BFD multihop and source interface cannot be used together') + + if 'profile' in peer_config: + profile_name = peer_config['profile'] + if 'profile' not in bfd or profile_name not in bfd['profile']: + raise ConfigError(f'BFD profile "{profile_name}" does not exist!') + + if 'vrf' in peer_config: + verify_vrf(peer_config) return None def generate(bfd): if not bfd: - bfd['new_frr_config'] = '' return None - - bfd['new_frr_config'] = render_to_string('frr/bfdd.frr.tmpl', bfd) + bfd['new_frr_config'] = render_to_string('frr/bfdd.frr.j2', bfd) def apply(bfd): + bfd_daemon = 'bfdd' + # Save original configuration prior to starting any commit actions frr_cfg = frr.FRRConfig() - frr_cfg.load_configuration() - frr_cfg.modify_section('^bfd', '') - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', bfd['new_frr_config']) - frr_cfg.commit_configuration() + frr_cfg.load_configuration(bfd_daemon) + frr_cfg.modify_section('^bfd', stop_pattern='^exit', remove_stop_mark=True) + if 'new_frr_config' in bfd: + frr_cfg.add_before(frr.default_add_before, bfd['new_frr_config']) + frr_cfg.commit_configuration(bfd_daemon) return None diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index 68284e0f9..cd46cbcb4 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -138,13 +138,20 @@ def verify(bgp): if asn == bgp['local_as']: raise ConfigError('Cannot have local-as same as BGP AS number') + # Neighbor AS specified for local-as and remote-as can not be the same + if dict_search('remote_as', peer_config) == asn: + raise ConfigError(f'Neighbor "{peer}" has local-as specified which is '\ + 'the same as remote-as, this is not allowed!') + # ttl-security and ebgp-multihop can't be used in the same configration if 'ebgp_multihop' in peer_config and 'ttl_security' in peer_config: raise ConfigError('You can not set both ebgp-multihop and ttl-security hops') - # Check if neighbor has both override capability and strict capability match configured at the same time. + # Check if neighbor has both override capability and strict capability match + # configured at the same time. if 'override_capability' in peer_config and 'strict_capability_match' in peer_config: - raise ConfigError(f'Neighbor "{peer}" cannot have both override-capability and strict-capability-match configured at the same time!') + raise ConfigError(f'Neighbor "{peer}" cannot have both override-capability and '\ + 'strict-capability-match configured at the same time!') # Check spaces in the password if 'password' in peer_config and ' ' in peer_config['password']: @@ -157,15 +164,39 @@ def verify(bgp): if not verify_remote_as(peer_config, bgp): raise ConfigError(f'Neighbor "{peer}" remote-as must be set!') + # Peer-group member cannot override remote-as of peer-group + if 'peer_group' in peer_config: + peer_group = peer_config['peer_group'] + if 'remote_as' in peer_config and 'remote_as' in bgp['peer_group'][peer_group]: + raise ConfigError(f'Peer-group member "{peer}" cannot override remote-as of peer-group "{peer_group}"!') + if 'interface' in peer_config: + if 'peer_group' in peer_config['interface']: + peer_group = peer_config['interface']['peer_group'] + if 'remote_as' in peer_config['interface'] and 'remote_as' in bgp['peer_group'][peer_group]: + raise ConfigError(f'Peer-group member "{peer}" cannot override remote-as of peer-group "{peer_group}"!') + if 'v6only' in peer_config['interface']: + if 'peer_group' in peer_config['interface']['v6only']: + peer_group = peer_config['interface']['v6only']['peer_group'] + if 'remote_as' in peer_config['interface']['v6only'] and 'remote_as' in bgp['peer_group'][peer_group]: + raise ConfigError(f'Peer-group member "{peer}" cannot override remote-as of peer-group "{peer_group}"!') + # Only checks for ipv4 and ipv6 neighbors # Check if neighbor address is assigned as system interface address - if is_ip(peer) and is_addr_assigned(peer): - raise ConfigError(f'Can not configure a local address as neighbor "{peer}"') + vrf = None + vrf_error_msg = f' in default VRF!' + if 'vrf' in bgp: + vrf = bgp['vrf'] + vrf_error_msg = f' in VRF "{vrf}"!' + + if is_ip(peer) and is_addr_assigned(peer, vrf): + raise ConfigError(f'Can not configure local address as neighbor "{peer}"{vrf_error_msg}') elif is_interface(peer): if 'peer_group' in peer_config: raise ConfigError(f'peer-group must be set under the interface node of "{peer}"') if 'remote_as' in peer_config: raise ConfigError(f'remote-as must be set under the interface node of "{peer}"') + if 'source_interface' in peer_config['interface']: + raise ConfigError(f'"source-interface" option not allowed for neighbor "{peer}"') for afi in ['ipv4_unicast', 'ipv4_multicast', 'ipv4_labeled_unicast', 'ipv4_flowspec', 'ipv6_unicast', 'ipv6_multicast', 'ipv6_labeled_unicast', 'ipv6_flowspec', @@ -183,6 +214,33 @@ def verify(bgp): raise ConfigError(f'Neighbor "{peer}" cannot have both ipv6-unicast and ipv6-labeled-unicast configured at the same time!') afi_config = peer_config['address_family'][afi] + + if 'conditionally_advertise' in afi_config: + if 'advertise_map' not in afi_config['conditionally_advertise']: + raise ConfigError('Must speficy advertise-map when conditionally-advertise is in use!') + # Verify advertise-map (which is a route-map) exists + verify_route_map(afi_config['conditionally_advertise']['advertise_map'], bgp) + + if ('exist_map' not in afi_config['conditionally_advertise'] and + 'non_exist_map' not in afi_config['conditionally_advertise']): + raise ConfigError('Must either speficy exist-map or non-exist-map when ' \ + 'conditionally-advertise is in use!') + + if {'exist_map', 'non_exist_map'} <= set(afi_config['conditionally_advertise']): + raise ConfigError('Can not specify both exist-map and non-exist-map for ' \ + 'conditionally-advertise!') + + if 'exist_map' in afi_config['conditionally_advertise']: + verify_route_map(afi_config['conditionally_advertise']['exist_map'], bgp) + + if 'non_exist_map' in afi_config['conditionally_advertise']: + verify_route_map(afi_config['conditionally_advertise']['non_exist_map'], bgp) + + # T4332: bgp deterministic-med cannot be disabled while addpath-tx-bestpath-per-AS is in use + if 'addpath_tx_per_as' in afi_config: + if dict_search('parameters.deterministic_med', bgp) == None: + raise ConfigError('addpath-tx-per-as requires BGP deterministic-med paramtere to be set!') + # Validate if configured Prefix list exists if 'prefix_list' in afi_config: for tmp in ['import', 'export']: @@ -255,26 +313,16 @@ def verify(bgp): tmp = dict_search(f'route_map.vpn.{export_import}', afi_config) if tmp: verify_route_map(tmp, bgp) - if afi in ['l2vpn_evpn'] and 'vrf' not in bgp: - # Some L2VPN EVPN AFI options are only supported under VRF - if 'vni' in afi_config: - for vni, vni_config in afi_config['vni'].items(): - if 'rd' in vni_config: - raise ConfigError('VNI route-distinguisher is only supported under EVPN VRF') - if 'route_target' in vni_config: - raise ConfigError('VNI route-target is only supported under EVPN VRF') return None def generate(bgp): if not bgp or 'deleted' in bgp: - bgp['frr_bgpd_config'] = '' - bgp['frr_zebra_config'] = '' return None - bgp['protocol'] = 'bgp' # required for frr/vrf.route-map.frr.tmpl - bgp['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.tmpl', bgp) - bgp['frr_bgpd_config'] = render_to_string('frr/bgpd.frr.tmpl', bgp) + bgp['protocol'] = 'bgp' # required for frr/vrf.route-map.frr.j2 + bgp['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.j2', bgp) + bgp['frr_bgpd_config'] = render_to_string('frr/bgpd.frr.j2', bgp) return None @@ -287,8 +335,9 @@ def apply(bgp): # The route-map used for the FIB (zebra) is part of the zebra daemon frr_cfg.load_configuration(zebra_daemon) - frr_cfg.modify_section(r'(\s+)?ip protocol bgp route-map [-a-zA-Z0-9.]+$', '', '(\s|!)') - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', bgp['frr_zebra_config']) + frr_cfg.modify_section(r'(\s+)?ip protocol bgp route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)') + if 'frr_zebra_config' in bgp: + frr_cfg.add_before(frr.default_add_before, bgp['frr_zebra_config']) frr_cfg.commit_configuration(zebra_daemon) # Generate empty helper string which can be ammended to FRR commands, it @@ -298,13 +347,11 @@ def apply(bgp): vrf = ' vrf ' + bgp['vrf'] frr_cfg.load_configuration(bgp_daemon) - frr_cfg.modify_section(f'^router bgp \d+{vrf}$', '') - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', bgp['frr_bgpd_config']) + frr_cfg.modify_section(f'^router bgp \d+{vrf}', stop_pattern='^exit', remove_stop_mark=True) + if 'frr_bgpd_config' in bgp: + frr_cfg.add_before(frr.default_add_before, bgp['frr_bgpd_config']) frr_cfg.commit_configuration(bgp_daemon) - # Save configuration to /run/frr/config/frr.conf - frr.save_configuration() - return None if __name__ == '__main__': diff --git a/src/conf_mode/protocols_igmp.py b/src/conf_mode/protocols_igmp.py index 28d560d03..65cc2beba 100755 --- a/src/conf_mode/protocols_igmp.py +++ b/src/conf_mode/protocols_igmp.py @@ -108,7 +108,7 @@ def generate(igmp): if igmp is None: return None - render(config_file, 'frr/igmp.frr.tmpl', igmp) + render(config_file, 'frr/igmp.frr.j2', igmp) return None def apply(igmp): diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py index 4505e2496..5dafd26d0 100755 --- a/src/conf_mode/protocols_isis.py +++ b/src/conf_mode/protocols_isis.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -56,10 +56,10 @@ def get_config(config=None): # instead of the VRF instance. if vrf: isis['vrf'] = vrf - # As we no re-use this Python handler for both VRF and non VRF instances for - # IS-IS we need to find out if any interfaces changed so properly adjust - # the FRR configuration and not by acctident change interfaces from a - # different VRF. + # FRR has VRF support for different routing daemons. As interfaces belong + # to VRFs - or the global VRF, we need to check for changed interfaces so + # that they will be properly rendered for the FRR config. Also this eases + # removal of interfaces from the running configuration. interfaces_removed = node_changed(conf, base + ['interface']) if interfaces_removed: isis['interface_removed'] = list(interfaces_removed) @@ -169,40 +169,50 @@ def verify(isis): # Segment routing checks if dict_search('segment_routing.global_block', isis): - high_label_value = dict_search('segment_routing.global_block.high_label_value', isis) - low_label_value = dict_search('segment_routing.global_block.low_label_value', isis) + g_high_label_value = dict_search('segment_routing.global_block.high_label_value', isis) + g_low_label_value = dict_search('segment_routing.global_block.low_label_value', isis) - # If segment routing global block high value is blank, throw error - if (low_label_value and not high_label_value) or (high_label_value and not low_label_value): - raise ConfigError('Segment routing global block requires both low and high value!') + # If segment routing global block high or low value is blank, throw error + if not (g_low_label_value or g_high_label_value): + raise ConfigError('Segment routing global-block requires both low and high value!') # If segment routing global block low value is higher than the high value, throw error - if int(low_label_value) > int(high_label_value): - raise ConfigError('Segment routing global block low value must be lower than high value') + if int(g_low_label_value) > int(g_high_label_value): + raise ConfigError('Segment routing global-block low value must be lower than high value') if dict_search('segment_routing.local_block', isis): - high_label_value = dict_search('segment_routing.local_block.high_label_value', isis) - low_label_value = dict_search('segment_routing.local_block.low_label_value', isis) + if dict_search('segment_routing.global_block', isis) == None: + raise ConfigError('Segment routing local-block requires global-block to be configured!') - # If segment routing local block high value is blank, throw error - if (low_label_value and not high_label_value) or (high_label_value and not low_label_value): - raise ConfigError('Segment routing local block requires both high and low value!') + l_high_label_value = dict_search('segment_routing.local_block.high_label_value', isis) + l_low_label_value = dict_search('segment_routing.local_block.low_label_value', isis) - # If segment routing local block low value is higher than the high value, throw error - if int(low_label_value) > int(high_label_value): - raise ConfigError('Segment routing local block low value must be lower than high value') + # If segment routing local-block high or low value is blank, throw error + if not (l_low_label_value or l_high_label_value): + raise ConfigError('Segment routing local-block requires both high and low value!') + + # If segment routing local-block low value is higher than the high value, throw error + if int(l_low_label_value) > int(l_high_label_value): + raise ConfigError('Segment routing local-block low value must be lower than high value') + + # local-block most live outside global block + global_range = range(int(g_low_label_value), int(g_high_label_value) +1) + local_range = range(int(l_low_label_value), int(l_high_label_value) +1) + + # Check for overlapping ranges + if list(set(global_range) & set(local_range)): + raise ConfigError(f'Segment-Routing Global Block ({g_low_label_value}/{g_high_label_value}) '\ + f'conflicts with Local Block ({l_low_label_value}/{l_high_label_value})!') return None def generate(isis): if not isis or 'deleted' in isis: - isis['frr_isisd_config'] = '' - isis['frr_zebra_config'] = '' return None - isis['protocol'] = 'isis' # required for frr/vrf.route-map.frr.tmpl - isis['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.tmpl', isis) - isis['frr_isisd_config'] = render_to_string('frr/isisd.frr.tmpl', isis) + isis['protocol'] = 'isis' # required for frr/vrf.route-map.frr.j2 + isis['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.j2', isis) + isis['frr_isisd_config'] = render_to_string('frr/isisd.frr.j2', isis) return None def apply(isis): @@ -214,8 +224,9 @@ def apply(isis): # The route-map used for the FIB (zebra) is part of the zebra daemon frr_cfg.load_configuration(zebra_daemon) - frr_cfg.modify_section(r'(\s+)?ip protocol isis route-map [-a-zA-Z0-9.]+$', '', '(\s|!)') - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', isis['frr_zebra_config']) + frr_cfg.modify_section('(\s+)?ip protocol isis route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)') + if 'frr_zebra_config' in isis: + frr_cfg.add_before(frr.default_add_before, isis['frr_zebra_config']) frr_cfg.commit_configuration(zebra_daemon) # Generate empty helper string which can be ammended to FRR commands, it @@ -225,19 +236,18 @@ def apply(isis): vrf = ' vrf ' + isis['vrf'] frr_cfg.load_configuration(isis_daemon) - frr_cfg.modify_section(f'^router isis VyOS{vrf}$', '') + frr_cfg.modify_section(f'^router isis VyOS{vrf}', stop_pattern='^exit', remove_stop_mark=True) for key in ['interface', 'interface_removed']: if key not in isis: continue for interface in isis[key]: - frr_cfg.modify_section(f'^interface {interface}{vrf}$', '') + frr_cfg.modify_section(f'^interface {interface}{vrf}', stop_pattern='^exit', remove_stop_mark=True) - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', isis['frr_isisd_config']) - frr_cfg.commit_configuration(isis_daemon) + if 'frr_isisd_config' in isis: + frr_cfg.add_before(frr.default_add_before, isis['frr_isisd_config']) - # Save configuration to /run/frr/config/frr.conf - frr.save_configuration() + frr_cfg.commit_configuration(isis_daemon) return None diff --git a/src/conf_mode/protocols_mpls.py b/src/conf_mode/protocols_mpls.py index 3b27608da..5da8e7b06 100755 --- a/src/conf_mode/protocols_mpls.py +++ b/src/conf_mode/protocols_mpls.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -20,11 +20,10 @@ from sys import exit from glob import glob from vyos.config import Config -from vyos.configdict import node_changed from vyos.template import render_to_string -from vyos.util import call from vyos.util import dict_search from vyos.util import read_file +from vyos.util import sysctl_write from vyos import ConfigError from vyos import frr from vyos import airbag @@ -66,82 +65,70 @@ def verify(mpls): def generate(mpls): # If there's no MPLS config generated, create dictionary key with no value. - if not mpls: - mpls['new_frr_config'] = '' + if not mpls or 'deleted' in mpls: return None - mpls['new_frr_config'] = render_to_string('frr/ldpd.frr.tmpl', mpls) + mpls['frr_ldpd_config'] = render_to_string('frr/ldpd.frr.j2', mpls) return None def apply(mpls): - # Define dictionary that will load FRR config - frr_cfg = {} + ldpd_damon = 'ldpd' + # Save original configuration prior to starting any commit actions - frr_cfg['original_config'] = frr.get_configuration(daemon='ldpd') - frr_cfg['modified_config'] = frr.replace_section(frr_cfg['original_config'], mpls['new_frr_config'], from_re='mpls.*') - - # If FRR config is blank, rerun the blank commit three times due to frr-reload - # behavior/bug not properly clearing out on one commit. - if mpls['new_frr_config'] == '': - for x in range(3): - frr.reload_configuration(frr_cfg['modified_config'], daemon='ldpd') - elif not 'ldp' in mpls: - for x in range(3): - frr.reload_configuration(frr_cfg['modified_config'], daemon='ldpd') - else: - # FRR mark configuration will test for syntax errors and throws an - # exception if any syntax errors is detected - frr.mark_configuration(frr_cfg['modified_config']) + frr_cfg = frr.FRRConfig() + + frr_cfg.load_configuration(ldpd_damon) + frr_cfg.modify_section(f'^mpls ldp', stop_pattern='^exit', remove_stop_mark=True) - # Commit resulting configuration to FRR, this will throw CommitError - # on failure - frr.reload_configuration(frr_cfg['modified_config'], daemon='ldpd') + if 'frr_ldpd_config' in mpls: + frr_cfg.add_before(frr.default_add_before, mpls['frr_ldpd_config']) + frr_cfg.commit_configuration(ldpd_damon) # Set number of entries in the platform label tables labels = '0' if 'interface' in mpls: labels = '1048575' - call(f'sysctl -wq net.mpls.platform_labels={labels}') + sysctl_write('net.mpls.platform_labels', labels) # Check for changes in global MPLS options if 'parameters' in mpls: # Choose whether to copy IP TTL to MPLS header TTL if 'no_propagate_ttl' in mpls['parameters']: - call('sysctl -wq net.mpls.ip_ttl_propagate=0') + sysctl_write('net.mpls.ip_ttl_propagate', 0) # Choose whether to limit maximum MPLS header TTL if 'maximum_ttl' in mpls['parameters']: ttl = mpls['parameters']['maximum_ttl'] - call(f'sysctl -wq net.mpls.default_ttl={ttl}') + sysctl_write('net.mpls.default_ttl', ttl) else: # Set default global MPLS options if not defined. - call('sysctl -wq net.mpls.ip_ttl_propagate=1') - call('sysctl -wq net.mpls.default_ttl=255') + sysctl_write('net.mpls.ip_ttl_propagate', 1) + sysctl_write('net.mpls.default_ttl', 255) # Enable and disable MPLS processing on interfaces per configuration if 'interface' in mpls: system_interfaces = [] # Populate system interfaces list with local MPLS capable interfaces for interface in glob('/proc/sys/net/mpls/conf/*'): - system_interfaces.append(os.path.basename(interface)) + system_interfaces.append(os.path.basename(interface)) # This is where the comparison is done on if an interface needs to be enabled/disabled. for system_interface in system_interfaces: interface_state = read_file(f'/proc/sys/net/mpls/conf/{system_interface}/input') if '1' in interface_state: if system_interface not in mpls['interface']: system_interface = system_interface.replace('.', '/') - call(f'sysctl -wq net.mpls.conf.{system_interface}.input=0') + sysctl_write(f'net.mpls.conf.{system_interface}.input', 0) elif '0' in interface_state: if system_interface in mpls['interface']: system_interface = system_interface.replace('.', '/') - call(f'sysctl -wq net.mpls.conf.{system_interface}.input=1') + sysctl_write(f'net.mpls.conf.{system_interface}.input', 1) else: system_interfaces = [] # If MPLS interfaces are not configured, set MPLS processing disabled for interface in glob('/proc/sys/net/mpls/conf/*'): - system_interfaces.append(os.path.basename(interface)) + system_interfaces.append(os.path.basename(interface)) for system_interface in system_interfaces: system_interface = system_interface.replace('.', '/') - call(f'sysctl -wq net.mpls.conf.{system_interface}.input=0') + sysctl_write(f'net.mpls.conf.{system_interface}.input', 0) return None diff --git a/src/conf_mode/protocols_nhrp.py b/src/conf_mode/protocols_nhrp.py index 12dacdba0..56939955d 100755 --- a/src/conf_mode/protocols_nhrp.py +++ b/src/conf_mode/protocols_nhrp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -16,6 +16,8 @@ from vyos.config import Config from vyos.configdict import node_changed +from vyos.firewall import find_nftables_rule +from vyos.firewall import remove_nftables_rule from vyos.template import render from vyos.util import process_named_running from vyos.util import run @@ -79,36 +81,36 @@ def verify(nhrp): for map_name, map_conf in nhrp_conf['dynamic_map'].items(): if 'nbma_domain_name' not in map_conf: raise ConfigError(f'nbma-domain-name missing on dynamic-map {map_name} on tunnel {name}') + + if 'cisco_authentication' in nhrp_conf: + if len(nhrp_conf['cisco_authentication']) > 8: + raise ConfigError('Maximum length of the secret is 8 characters!') + return None def generate(nhrp): - render(opennhrp_conf, 'nhrp/opennhrp.conf.tmpl', nhrp) + render(opennhrp_conf, 'nhrp/opennhrp.conf.j2', nhrp) return None def apply(nhrp): if 'tunnel' in nhrp: for tunnel, tunnel_conf in nhrp['tunnel'].items(): - if 'source_address' in tunnel_conf: - chain = f'VYOS_NHRP_{tunnel}_OUT_HOOK' - source_address = tunnel_conf['source_address'] + if 'source_address' in nhrp['if_tunnel'][tunnel]: + comment = f'VYOS_NHRP_{tunnel}' + source_address = nhrp['if_tunnel'][tunnel]['source_address'] - chain_exists = run(f'sudo iptables --check {chain} -j RETURN') == 0 - if not chain_exists: - run(f'sudo iptables --new {chain}') - run(f'sudo iptables --append {chain} -p gre -s {source_address} -d 224.0.0.0/4 -j DROP') - run(f'sudo iptables --append {chain} -j RETURN') - run(f'sudo iptables --insert OUTPUT 2 -j {chain}') + rule_handle = find_nftables_rule('ip filter', 'VYOS_FW_OUTPUT', ['ip protocol gre', f'ip saddr {source_address}', 'ip daddr 224.0.0.0/4']) + if not rule_handle: + run(f'sudo nft insert rule ip filter VYOS_FW_OUTPUT ip protocol gre ip saddr {source_address} ip daddr 224.0.0.0/4 counter drop comment "{comment}"') for tunnel in nhrp['del_tunnels']: - chain = f'VYOS_NHRP_{tunnel}_OUT_HOOK' - chain_exists = run(f'sudo iptables --check {chain} -j RETURN') == 0 - if chain_exists: - run(f'sudo iptables --delete OUTPUT -j {chain}') - run(f'sudo iptables --flush {chain}') - run(f'sudo iptables --delete-chain {chain}') + comment = f'VYOS_NHRP_{tunnel}' + rule_handle = find_nftables_rule('ip filter', 'VYOS_FW_OUTPUT', [f'comment "{comment}"']) + if rule_handle: + remove_nftables_rule('ip filter', 'VYOS_FW_OUTPUT', rule_handle) action = 'restart' if nhrp and 'tunnel' in nhrp else 'stop' - run(f'systemctl {action} opennhrp') + run(f'systemctl {action} opennhrp.service') return None if __name__ == '__main__': diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py index 6ccda2e5a..5b4874ba2 100755 --- a/src/conf_mode/protocols_ospf.py +++ b/src/conf_mode/protocols_ospf.py @@ -25,6 +25,7 @@ from vyos.configdict import node_changed from vyos.configverify import verify_common_route_maps from vyos.configverify import verify_route_map from vyos.configverify import verify_interface_exists +from vyos.configverify import verify_access_list from vyos.template import render_to_string from vyos.util import dict_search from vyos.util import get_interface_config @@ -56,10 +57,10 @@ def get_config(config=None): # instead of the VRF instance. if vrf: ospf['vrf'] = vrf - # As we no re-use this Python handler for both VRF and non VRF instances for - # OSPF we need to find out if any interfaces changed so properly adjust - # the FRR configuration and not by acctident change interfaces from a - # different VRF. + # FRR has VRF support for different routing daemons. As interfaces belong + # to VRFs - or the global VRF, we need to check for changed interfaces so + # that they will be properly rendered for the FRR config. Also this eases + # removal of interfaces from the running configuration. interfaces_removed = node_changed(conf, base + ['interface']) if interfaces_removed: ospf['interface_removed'] = list(interfaces_removed) @@ -159,6 +160,16 @@ def verify(ospf): route_map_name = dict_search('default_information.originate.route_map', ospf) if route_map_name: verify_route_map(route_map_name, ospf) + # Validate if configured Access-list exists + if 'area' in ospf: + for area, area_config in ospf['area'].items(): + if 'import_list' in area_config: + acl_import = area_config['import_list'] + if acl_import: verify_access_list(acl_import, ospf) + if 'export_list' in area_config: + acl_export = area_config['export_list'] + if acl_export: verify_access_list(acl_export, ospf) + if 'interface' in ospf: for interface, interface_config in ospf['interface'].items(): verify_interface_exists(interface) @@ -177,11 +188,11 @@ def verify(ospf): raise ConfigError('Can not use OSPF interface area and area ' \ 'network configuration at the same time!') - if 'vrf' in ospf: # If interface specific options are set, we must ensure that the # interface is bound to our requesting VRF. Due to the VyOS # priorities the interface is bound to the VRF after creation of # the VRF itself, and before any routing protocol is configured. + if 'vrf' in ospf: vrf = ospf['vrf'] tmp = get_interface_config(interface) if 'master' not in tmp or tmp['master'] != vrf: @@ -191,13 +202,11 @@ def verify(ospf): def generate(ospf): if not ospf or 'deleted' in ospf: - ospf['frr_ospfd_config'] = '' - ospf['frr_zebra_config'] = '' return None - ospf['protocol'] = 'ospf' # required for frr/vrf.route-map.frr.tmpl - ospf['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.tmpl', ospf) - ospf['frr_ospfd_config'] = render_to_string('frr/ospfd.frr.tmpl', ospf) + ospf['protocol'] = 'ospf' # required for frr/vrf.route-map.frr.j2 + ospf['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.j2', ospf) + ospf['frr_ospfd_config'] = render_to_string('frr/ospfd.frr.j2', ospf) return None def apply(ospf): @@ -209,8 +218,9 @@ def apply(ospf): # The route-map used for the FIB (zebra) is part of the zebra daemon frr_cfg.load_configuration(zebra_daemon) - frr_cfg.modify_section(r'(\s+)?ip protocol ospf route-map [-a-zA-Z0-9.]+$', '', '(\s|!)') - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ospf['frr_zebra_config']) + frr_cfg.modify_section('(\s+)?ip protocol ospf route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)') + if 'frr_zebra_config' in ospf: + frr_cfg.add_before(frr.default_add_before, ospf['frr_zebra_config']) frr_cfg.commit_configuration(zebra_daemon) # Generate empty helper string which can be ammended to FRR commands, it @@ -220,20 +230,18 @@ def apply(ospf): vrf = ' vrf ' + ospf['vrf'] frr_cfg.load_configuration(ospf_daemon) - frr_cfg.modify_section(f'^router ospf{vrf}$', '') + frr_cfg.modify_section(f'^router ospf{vrf}', stop_pattern='^exit', remove_stop_mark=True) for key in ['interface', 'interface_removed']: if key not in ospf: continue for interface in ospf[key]: - frr_cfg.modify_section(f'^interface {interface}{vrf}$', '') + frr_cfg.modify_section(f'^interface {interface}{vrf}', stop_pattern='^exit', remove_stop_mark=True) - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ospf['frr_ospfd_config']) + if 'frr_ospfd_config' in ospf: + frr_cfg.add_before(frr.default_add_before, ospf['frr_ospfd_config']) frr_cfg.commit_configuration(ospf_daemon) - # Save configuration to /run/frr/config/frr.conf - frr.save_configuration() - return None if __name__ == '__main__': diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py index 536ffa690..ee4eaf59d 100755 --- a/src/conf_mode/protocols_ospfv3.py +++ b/src/conf_mode/protocols_ospfv3.py @@ -17,32 +17,80 @@ import os from sys import exit +from sys import argv from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configdict import node_changed from vyos.configverify import verify_common_route_maps +from vyos.configverify import verify_route_map +from vyos.configverify import verify_interface_exists from vyos.template import render_to_string from vyos.ifconfig import Interface +from vyos.util import dict_search +from vyos.util import get_interface_config from vyos.xml import defaults from vyos import ConfigError from vyos import frr from vyos import airbag airbag.enable() -frr_daemon = 'ospf6d' - def get_config(config=None): if config: conf = config else: conf = Config() - base = ['protocols', 'ospfv3'] + + vrf = None + if len(argv) > 1: + vrf = argv[1] + + base_path = ['protocols', 'ospfv3'] + + # eqivalent of the C foo ? 'a' : 'b' statement + base = vrf and ['vrf', 'name', vrf, 'protocols', 'ospfv3'] or base_path ospfv3 = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + # Assign the name of our VRF context. This MUST be done before the return + # statement below, else on deletion we will delete the default instance + # instead of the VRF instance. + if vrf: ospfv3['vrf'] = vrf + + # FRR has VRF support for different routing daemons. As interfaces belong + # to VRFs - or the global VRF, we need to check for changed interfaces so + # that they will be properly rendered for the FRR config. Also this eases + # removal of interfaces from the running configuration. + interfaces_removed = node_changed(conf, base + ['interface']) + if interfaces_removed: + ospfv3['interface_removed'] = list(interfaces_removed) + # Bail out early if configuration tree does not exist if not conf.exists(base): + ospfv3.update({'deleted' : ''}) return ospfv3 + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + # XXX: Note that we can not call defaults(base), as defaults does not work + # on an instance of a tag node. As we use the exact same CLI definition for + # both the non-vrf and vrf version this is absolutely safe! + default_values = defaults(base_path) + + # We have to cleanup the default dict, as default values could enable features + # which are not explicitly enabled on the CLI. Example: default-information + # originate comes with a default metric-type of 2, which will enable the + # entire default-information originate tree, even when not set via CLI so we + # need to check this first and probably drop that key. + if dict_search('default_information.originate', ospfv3) is None: + del default_values['default_information'] + + # XXX: T2665: we currently have no nice way for defaults under tag nodes, + # clean them out and add them manually :( + del default_values['interface'] + + # merge in remaining default values + ospfv3 = dict_merge(default_values, ospfv3) + # We also need some additional information from the config, prefix-lists # and route-maps for instance. They will be used in verify(). # @@ -60,34 +108,68 @@ def verify(ospfv3): verify_common_route_maps(ospfv3) + # As we can have a default-information route-map, we need to validate it! + route_map_name = dict_search('default_information.originate.route_map', ospfv3) + if route_map_name: verify_route_map(route_map_name, ospfv3) + + if 'area' in ospfv3: + for area, area_config in ospfv3['area'].items(): + 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 'interface' in ospfv3: - for ifname, if_config in ospfv3['interface'].items(): - if 'ifmtu' in if_config: - mtu = Interface(ifname).get_mtu() - if int(if_config['ifmtu']) > int(mtu): + for interface, interface_config in ospfv3['interface'].items(): + verify_interface_exists(interface) + if 'ifmtu' in interface_config: + mtu = Interface(interface).get_mtu() + if int(interface_config['ifmtu']) > int(mtu): raise ConfigError(f'OSPFv3 ifmtu can not exceed physical MTU of "{mtu}"') + # If interface specific options are set, we must ensure that the + # interface is bound to our requesting VRF. Due to the VyOS + # priorities the interface is bound to the VRF after creation of + # the VRF itself, and before any routing protocol is configured. + if 'vrf' in ospfv3: + vrf = ospfv3['vrf'] + tmp = get_interface_config(interface) + if 'master' not in tmp or tmp['master'] != vrf: + raise ConfigError(f'Interface {interface} is not a member of VRF {vrf}!') + return None def generate(ospfv3): - if not ospfv3: - ospfv3['new_frr_config'] = '' + if not ospfv3 or 'deleted' in ospfv3: return None - ospfv3['new_frr_config'] = render_to_string('frr/ospf6d.frr.tmpl', ospfv3) + ospfv3['new_frr_config'] = render_to_string('frr/ospf6d.frr.j2', ospfv3) return None def apply(ospfv3): + ospf6_daemon = 'ospf6d' + # Save original configuration prior to starting any commit actions frr_cfg = frr.FRRConfig() - frr_cfg.load_configuration(frr_daemon) - frr_cfg.modify_section(r'^interface \S+', '') - frr_cfg.modify_section('^router ospf6$', '') - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ospfv3['new_frr_config']) - frr_cfg.commit_configuration(frr_daemon) - - # Save configuration to /run/frr/config/frr.conf - frr.save_configuration() + + # Generate empty helper string which can be ammended to FRR commands, it + # will be either empty (default VRF) or contain the "vrf <name" statement + vrf = '' + if 'vrf' in ospfv3: + vrf = ' vrf ' + ospfv3['vrf'] + + frr_cfg.load_configuration(ospf6_daemon) + frr_cfg.modify_section(f'^router ospf6{vrf}', stop_pattern='^exit', remove_stop_mark=True) + + for key in ['interface', 'interface_removed']: + if key not in ospfv3: + continue + for interface in ospfv3[key]: + frr_cfg.modify_section(f'^interface {interface}{vrf}', stop_pattern='^exit', remove_stop_mark=True) + + if 'new_frr_config' in ospfv3: + frr_cfg.add_before(frr.default_add_before, ospfv3['new_frr_config']) + + frr_cfg.commit_configuration(ospf6_daemon) return None diff --git a/src/conf_mode/protocols_pim.py b/src/conf_mode/protocols_pim.py index df2e6f941..78df9b6f8 100755 --- a/src/conf_mode/protocols_pim.py +++ b/src/conf_mode/protocols_pim.py @@ -135,7 +135,7 @@ def generate(pim): if pim is None: return None - render(config_file, 'frr/pimd.frr.tmpl', pim) + render(config_file, 'frr/pimd.frr.j2', pim) return None def apply(pim): diff --git a/src/conf_mode/protocols_rip.py b/src/conf_mode/protocols_rip.py index 6b78f6f2d..a76c1ce76 100755 --- a/src/conf_mode/protocols_rip.py +++ b/src/conf_mode/protocols_rip.py @@ -20,6 +20,7 @@ from sys import exit from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configdict import node_changed from vyos.configverify import verify_common_route_maps from vyos.configverify import verify_access_list from vyos.configverify import verify_prefix_list @@ -39,8 +40,17 @@ def get_config(config=None): base = ['protocols', 'rip'] rip = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + # FRR has VRF support for different routing daemons. As interfaces belong + # to VRFs - or the global VRF, we need to check for changed interfaces so + # that they will be properly rendered for the FRR config. Also this eases + # removal of interfaces from the running configuration. + interfaces_removed = node_changed(conf, base + ['interface']) + if interfaces_removed: + rip['interface_removed'] = list(interfaces_removed) + # Bail out early if configuration tree does not exist if not conf.exists(base): + rip.update({'deleted' : ''}) return rip # We have gathered the dict representation of the CLI, but there are default @@ -89,12 +99,10 @@ def verify(rip): f'with "split-horizon disable" for "{interface}"!') def generate(rip): - if not rip: - rip['new_frr_config'] = '' + if not rip or 'deleted' in rip: return None - rip['new_frr_config'] = render_to_string('frr/ripd.frr.tmpl', rip) - + rip['new_frr_config'] = render_to_string('frr/ripd.frr.j2', rip) return None def apply(rip): @@ -106,19 +114,22 @@ def apply(rip): # The route-map used for the FIB (zebra) is part of the zebra daemon frr_cfg.load_configuration(zebra_daemon) - frr_cfg.modify_section(r'^ip protocol rip route-map [-a-zA-Z0-9.]+$', '') + frr_cfg.modify_section('^ip protocol rip route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)') frr_cfg.commit_configuration(zebra_daemon) frr_cfg.load_configuration(rip_daemon) - frr_cfg.modify_section(r'key chain \S+', '') - frr_cfg.modify_section(r'interface \S+', '') - frr_cfg.modify_section('^router rip$', '') + frr_cfg.modify_section('^key chain \S+', stop_pattern='^exit', remove_stop_mark=True) + frr_cfg.modify_section('^router rip', stop_pattern='^exit', remove_stop_mark=True) - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', rip['new_frr_config']) - frr_cfg.commit_configuration(rip_daemon) + for key in ['interface', 'interface_removed']: + if key not in rip: + continue + for interface in rip[key]: + frr_cfg.modify_section(f'^interface {interface}', stop_pattern='^exit', remove_stop_mark=True) - # Save configuration to /run/frr/config/frr.conf - frr.save_configuration() + if 'new_frr_config' in rip: + frr_cfg.add_before(frr.default_add_before, rip['new_frr_config']) + frr_cfg.commit_configuration(rip_daemon) return None diff --git a/src/conf_mode/protocols_ripng.py b/src/conf_mode/protocols_ripng.py index bc4954f63..21ff710b3 100755 --- a/src/conf_mode/protocols_ripng.py +++ b/src/conf_mode/protocols_ripng.py @@ -31,8 +31,6 @@ from vyos import frr from vyos import airbag airbag.enable() -frr_daemon = 'ripngd' - def get_config(config=None): if config: conf = config @@ -95,21 +93,28 @@ def generate(ripng): ripng['new_frr_config'] = '' return None - ripng['new_frr_config'] = render_to_string('frr/ripngd.frr.tmpl', ripng) + ripng['new_frr_config'] = render_to_string('frr/ripngd.frr.j2', ripng) return None def apply(ripng): + ripng_daemon = 'ripngd' + zebra_daemon = 'zebra' + # Save original configuration prior to starting any commit actions frr_cfg = frr.FRRConfig() - frr_cfg.load_configuration(frr_daemon) - frr_cfg.modify_section(r'key chain \S+', '') - frr_cfg.modify_section(r'interface \S+', '') - frr_cfg.modify_section('router ripng', '') - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ripng['new_frr_config']) - frr_cfg.commit_configuration(frr_daemon) - - # Save configuration to /run/frr/config/frr.conf - frr.save_configuration() + + # The route-map used for the FIB (zebra) is part of the zebra daemon + frr_cfg.load_configuration(zebra_daemon) + frr_cfg.modify_section('^ipv6 protocol ripng route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)') + frr_cfg.commit_configuration(zebra_daemon) + + frr_cfg.load_configuration(ripng_daemon) + frr_cfg.modify_section('key chain \S+', stop_pattern='^exit', remove_stop_mark=True) + frr_cfg.modify_section('interface \S+', stop_pattern='^exit', remove_stop_mark=True) + frr_cfg.modify_section('^router ripng', stop_pattern='^exit', remove_stop_mark=True) + if 'new_frr_config' in ripng: + frr_cfg.add_before(frr.default_add_before, ripng['new_frr_config']) + frr_cfg.commit_configuration(ripng_daemon) return None diff --git a/src/conf_mode/protocols_rpki.py b/src/conf_mode/protocols_rpki.py index 947c8ab7a..62ea9c878 100755 --- a/src/conf_mode/protocols_rpki.py +++ b/src/conf_mode/protocols_rpki.py @@ -28,8 +28,6 @@ from vyos import frr from vyos import airbag airbag.enable() -frr_daemon = 'bgpd' - def get_config(config=None): if config: conf = config @@ -38,7 +36,9 @@ def get_config(config=None): base = ['protocols', 'rpki'] rpki = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + # Bail out early if configuration tree does not exist if not conf.exists(base): + rpki.update({'deleted' : ''}) return rpki # We have gathered the dict representation of the CLI, but there are default @@ -79,17 +79,22 @@ def verify(rpki): return None def generate(rpki): - rpki['new_frr_config'] = render_to_string('frr/rpki.frr.tmpl', rpki) + if not rpki: + return + rpki['new_frr_config'] = render_to_string('frr/rpki.frr.j2', rpki) return None def apply(rpki): + bgp_daemon = 'bgpd' + # Save original configuration prior to starting any commit actions frr_cfg = frr.FRRConfig() - frr_cfg.load_configuration(frr_daemon) - frr_cfg.modify_section('rpki', '') - frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', rpki['new_frr_config']) - frr_cfg.commit_configuration(frr_daemon) + frr_cfg.load_configuration(bgp_daemon) + frr_cfg.modify_section('^rpki', stop_pattern='^exit', remove_stop_mark=True) + if 'new_frr_config' in rpki: + frr_cfg.add_before(frr.default_add_before, rpki['new_frr_config']) + frr_cfg.commit_configuration(bgp_daemon) return None if __name__ == '__main__': diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py index f010141e9..58e202928 100755 --- a/src/conf_mode/protocols_static.py +++ b/src/conf_mode/protocols_static.py @@ -22,6 +22,7 @@ from sys import argv from vyos.config import Config from vyos.configdict import dict_merge 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_to_string @@ -59,7 +60,9 @@ def get_config(config=None): # T3680 - get a list of all interfaces currently configured to use DHCP tmp = get_dhcp_interfaces(conf, vrf) - if tmp: static['dhcp'] = tmp + if tmp: static.update({'dhcp' : tmp}) + tmp = get_pppoe_interfaces(conf, vrf) + if tmp: static.update({'pppoe' : tmp}) return static @@ -82,10 +85,16 @@ def verify(static): for interface, interface_config in prefix_options[type].items(): verify_vrf(interface_config) + if {'blackhole', 'reject'} <= set(prefix_options): + raise ConfigError(f'Can not use both blackhole and reject for '\ + 'prefix "{prefix}"!') + return None def generate(static): - static['new_frr_config'] = render_to_string('frr/staticd.frr.tmpl', static) + if not static: + return None + static['new_frr_config'] = render_to_string('frr/staticd.frr.j2', static) return None def apply(static): @@ -97,24 +106,21 @@ def apply(static): # The route-map used for the FIB (zebra) is part of the zebra daemon frr_cfg.load_configuration(zebra_daemon) - frr_cfg.modify_section(r'^ip protocol static route-map [-a-zA-Z0-9.]+$', '') + frr_cfg.modify_section(r'^ip protocol static route-map [-a-zA-Z0-9.]+', '') frr_cfg.commit_configuration(zebra_daemon) - frr_cfg.load_configuration(static_daemon) if 'vrf' in static: vrf = static['vrf'] - frr_cfg.modify_section(f'^vrf {vrf}$', '') + frr_cfg.modify_section(f'^vrf {vrf}', stop_pattern='^exit', remove_stop_mark=True) else: - frr_cfg.modify_section(r'^ip route .*', '') - frr_cfg.modify_section(r'^ipv6 route .*', '') + frr_cfg.modify_section(r'^ip route .*') + frr_cfg.modify_section(r'^ipv6 route .*') - frr_cfg.add_before(r'(interface .*|line vty)', static['new_frr_config']) + if 'new_frr_config' in static: + frr_cfg.add_before(frr.default_add_before, static['new_frr_config']) frr_cfg.commit_configuration(static_daemon) - # Save configuration to /run/frr/config/frr.conf - frr.save_configuration() - return None if __name__ == '__main__': diff --git a/src/conf_mode/protocols_static_multicast.py b/src/conf_mode/protocols_static_multicast.py index 99157835a..6afdf31f3 100755 --- a/src/conf_mode/protocols_static_multicast.py +++ b/src/conf_mode/protocols_static_multicast.py @@ -96,7 +96,7 @@ def generate(mroute): if mroute is None: return None - render(config_file, 'frr/static_mcast.frr.tmpl', mroute) + render(config_file, 'frr/static_mcast.frr.j2', mroute) return None def apply(mroute): diff --git a/src/conf_mode/qos.py b/src/conf_mode/qos.py new file mode 100755 index 000000000..dbe3be225 --- /dev/null +++ b/src/conf_mode/qos.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 dict_merge +from vyos.xml import defaults +from vyos import ConfigError +from vyos import airbag +airbag.enable() + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + base = ['qos'] + if not conf.exists(base): + return None + + qos = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + + if 'policy' in qos: + for policy in qos['policy']: + # CLI mangles - to _ for better Jinja2 compatibility - do we need + # Jinja2 here? + policy = policy.replace('-','_') + + default_values = defaults(base + ['policy', policy]) + + # class is another tag node which requires individual handling + class_default_values = defaults(base + ['policy', policy, 'class']) + if 'class' in default_values: + del default_values['class'] + + for p_name, p_config in qos['policy'][policy].items(): + qos['policy'][policy][p_name] = dict_merge( + default_values, qos['policy'][policy][p_name]) + + if 'class' in p_config: + for p_class in p_config['class']: + qos['policy'][policy][p_name]['class'][p_class] = dict_merge( + class_default_values, qos['policy'][policy][p_name]['class'][p_class]) + + import pprint + pprint.pprint(qos) + return qos + +def verify(qos): + if not qos: + return None + + # network policy emulator + # reorder rerquires delay to be set + + raise ConfigError('123') + return None + +def generate(qos): + return None + +def apply(qos): + 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/salt-minion.py b/src/conf_mode/salt-minion.py index 841bf6a39..00b889a11 100755 --- a/src/conf_mode/salt-minion.py +++ b/src/conf_mode/salt-minion.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -16,14 +16,18 @@ import os -from copy import deepcopy from socket import gethostname from sys import exit from urllib3 import PoolManager +from vyos.base import Warning from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.configverify import verify_interface_exists from vyos.template import render -from vyos.util import call, chown +from vyos.util import call +from vyos.util import chown +from vyos.xml import defaults from vyos import ConfigError from vyos import airbag @@ -32,20 +36,10 @@ airbag.enable() config_file = r'/etc/salt/minion' master_keyfile = r'/opt/vyatta/etc/config/salt/pki/minion/master_sign.pub' -default_config_data = { - 'hash': 'sha256', - 'log_level': 'warning', - 'master' : 'salt', - 'user': 'minion', - 'group': 'vyattacfg', - 'salt_id': gethostname(), - 'mine_interval': '60', - 'verify_master_pubkey_sign': 'false', - 'master_key': '' -} +user='minion' +group='vyattacfg' def get_config(config=None): - salt = deepcopy(default_config_data) if config: conf = config else: @@ -54,44 +48,44 @@ def get_config(config=None): if not conf.exists(base): return None - else: - conf.set_level(base) - if conf.exists(['hash']): - salt['hash'] = conf.return_value(['hash']) + salt = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + # ID default is dynamic thus we can not use defaults() + if 'id' not in salt: + salt['id'] = gethostname() + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + default_values = defaults(base) + salt = dict_merge(default_values, salt) - if conf.exists(['master']): - salt['master'] = conf.return_values(['master']) - - if conf.exists(['id']): - salt['salt_id'] = conf.return_value(['id']) + if not conf.exists(base): + return None + else: + conf.set_level(base) - if conf.exists(['user']): - salt['user'] = conf.return_value(['user']) + return salt - if conf.exists(['interval']): - salt['interval'] = conf.return_value(['interval']) +def verify(salt): + if not salt: + return None - if conf.exists(['master-key']): - salt['master_key'] = conf.return_value(['master-key']) - salt['verify_master_pubkey_sign'] = 'true' + if 'hash' in salt and salt['hash'] == 'sha1': + Warning('Do not use sha1 hashing algorithm, upgrade to sha256 or later!') - return salt + if 'source_interface' in salt: + verify_interface_exists(salt['source_interface']) -def verify(salt): return None def generate(salt): if not salt: return None - render(config_file, 'salt-minion/minion.tmpl', salt, - user=salt['user'], group=salt['group']) + render(config_file, 'salt-minion/minion.j2', salt, user=user, group=group) if not os.path.exists(master_keyfile): - if salt['master_key']: + if 'master_key' in salt: req = PoolManager().request('GET', salt['master_key'], preload_content=False) - with open(master_keyfile, 'wb') as f: while True: data = req.read(1024) @@ -100,18 +94,19 @@ def generate(salt): f.write(data) req.release_conn() - chown(master_keyfile, salt['user'], salt['group']) + chown(master_keyfile, user, group) return None def apply(salt): + service_name = 'salt-minion.service' if not salt: # Salt removed from running config - call('systemctl stop salt-minion.service') + call(f'systemctl stop {service_name}') if os.path.exists(config_file): os.unlink(config_file) else: - call('systemctl restart salt-minion.service') + call(f'systemctl restart {service_name}') return None diff --git a/src/conf_mode/service_console-server.py b/src/conf_mode/service_console-server.py index 51050e702..a2e411e49 100755 --- a/src/conf_mode/service_console-server.py +++ b/src/conf_mode/service_console-server.py @@ -81,7 +81,7 @@ def generate(proxy): if not proxy: return None - render(config_file, 'conserver/conserver.conf.tmpl', proxy) + render(config_file, 'conserver/conserver.conf.j2', proxy) if 'device' in proxy: for device, device_config in proxy['device'].items(): if 'ssh' not in device_config: @@ -92,7 +92,7 @@ def generate(proxy): 'port' : device_config['ssh']['port'], } render(dropbear_systemd_file.format(**tmp), - 'conserver/dropbear@.service.tmpl', tmp) + 'conserver/dropbear@.service.j2', tmp) return None diff --git a/src/conf_mode/service_ids_fastnetmon.py b/src/conf_mode/service_ids_fastnetmon.py index 67edeb630..ae7e582ec 100755 --- a/src/conf_mode/service_ids_fastnetmon.py +++ b/src/conf_mode/service_ids_fastnetmon.py @@ -67,8 +67,8 @@ def generate(fastnetmon): return - render(config_file, 'ids/fastnetmon.tmpl', fastnetmon) - render(networks_list, 'ids/fastnetmon_networks_list.tmpl', fastnetmon) + render(config_file, 'ids/fastnetmon.j2', fastnetmon) + render(networks_list, 'ids/fastnetmon_networks_list.j2', fastnetmon) return None diff --git a/src/conf_mode/service_ipoe-server.py b/src/conf_mode/service_ipoe-server.py index f676fdbbe..559d1bcd5 100755 --- a/src/conf_mode/service_ipoe-server.py +++ b/src/conf_mode/service_ipoe-server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -41,6 +41,7 @@ default_config_data = { 'interfaces': [], 'dnsv4': [], 'dnsv6': [], + 'client_named_ip_pool': [], 'client_ipv6_pool': [], 'client_ipv6_delegate_prefix': [], 'radius_server': [], @@ -219,6 +220,22 @@ def get_config(config=None): conf.set_level(base_path) + # Named client-ip-pool + if conf.exists(['client-ip-pool', 'name']): + for name in conf.list_nodes(['client-ip-pool', 'name']): + tmp = { + 'name': name, + 'gateway_address': '', + 'subnet': '' + } + + if conf.exists(['client-ip-pool', 'name', name, 'gateway-address']): + tmp['gateway_address'] += conf.return_value(['client-ip-pool', 'name', name, 'gateway-address']) + if conf.exists(['client-ip-pool', 'name', name, 'subnet']): + tmp['subnet'] += conf.return_value(['client-ip-pool', 'name', name, 'subnet']) + + ipoe['client_named_ip_pool'].append(tmp) + if conf.exists(['client-ipv6-pool', 'prefix']): for prefix in conf.list_nodes(['client-ipv6-pool', 'prefix']): tmp = { @@ -254,10 +271,6 @@ def verify(ipoe): if not ipoe['interfaces']: raise ConfigError('No IPoE interface configured') - for interface in ipoe['interfaces']: - if not interface['range']: - raise ConfigError(f'No IPoE client subnet defined on interface "{ interface }"') - if len(ipoe['dnsv4']) > 2: raise ConfigError('Not more then two IPv4 DNS name-servers can be configured') @@ -283,10 +296,10 @@ def generate(ipoe): if not ipoe: return None - render(ipoe_conf, 'accel-ppp/ipoe.config.tmpl', ipoe) + render(ipoe_conf, 'accel-ppp/ipoe.config.j2', ipoe) if ipoe['auth_mode'] == 'local': - render(ipoe_chap_secrets, 'accel-ppp/chap-secrets.ipoe.tmpl', ipoe) + render(ipoe_chap_secrets, 'accel-ppp/chap-secrets.ipoe.j2', ipoe) os.chmod(ipoe_chap_secrets, S_IRUSR | S_IWUSR | S_IRGRP) else: diff --git a/src/conf_mode/service_mdns-repeater.py b/src/conf_mode/service_mdns-repeater.py index d31a0c49e..2383a53fb 100755 --- a/src/conf_mode/service_mdns-repeater.py +++ b/src/conf_mode/service_mdns-repeater.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2017-2020 VyOS maintainers and contributors +# Copyright (C) 2017-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 @@ -92,7 +92,7 @@ def generate(mdns): if len(mdns['interface']) < 2: return None - render(config_file, 'mdns-repeater/avahi-daemon.tmpl', mdns) + render(config_file, 'mdns-repeater/avahi-daemon.j2', mdns) return None def apply(mdns): diff --git a/src/conf_mode/service_monitoring_telegraf.py b/src/conf_mode/service_monitoring_telegraf.py new file mode 100755 index 000000000..daf75d740 --- /dev/null +++ b/src/conf_mode/service_monitoring_telegraf.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021-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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import json + +from sys import exit +from shutil import rmtree + +from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.ifconfig import Section +from vyos.template import render +from vyos.util import call +from vyos.util import chown +from vyos.util import cmd +from vyos.xml import defaults +from vyos import ConfigError +from vyos import airbag +airbag.enable() + + +base_dir = '/run/telegraf' +cache_dir = f'/etc/telegraf/.cache' +config_telegraf = f'{base_dir}/vyos-telegraf.conf' +custom_scripts_dir = '/etc/telegraf/custom_scripts' +syslog_telegraf = '/etc/rsyslog.d/50-telegraf.conf' +systemd_telegraf_service = '/etc/systemd/system/vyos-telegraf.service' +systemd_telegraf_override_dir = '/etc/systemd/system/vyos-telegraf.service.d' +systemd_override = f'{systemd_telegraf_override_dir}/10-override.conf' + + +def get_interfaces(type='', vlan=True): + """ + Get interfaces + get_interfaces() + ['dum0', 'eth0', 'eth1', 'eth1.5', 'lo', 'tun0'] + + get_interfaces("dummy") + ['dum0'] + """ + interfaces = [] + ifaces = Section.interfaces(type) + for iface in ifaces: + if vlan == False and '.' in iface: + continue + interfaces.append(iface) + + return interfaces + +def get_nft_filter_chains(): + """ + Get nft chains for table filter + """ + nft = cmd('nft --json list table ip filter') + nft = json.loads(nft) + chain_list = [] + + for output in nft['nftables']: + if 'chain' in output: + chain = output['chain']['name'] + chain_list.append(chain) + + return chain_list + + +def get_config(config=None): + + if config: + conf = config + else: + conf = Config() + base = ['service', 'monitoring', 'telegraf'] + if not conf.exists(base): + return None + + monitoring = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + default_values = defaults(base) + monitoring = dict_merge(default_values, monitoring) + + monitoring['custom_scripts_dir'] = custom_scripts_dir + monitoring['interfaces_ethernet'] = get_interfaces('ethernet', vlan=False) + monitoring['nft_chains'] = get_nft_filter_chains() + + if 'authentication' in monitoring or \ + 'url' in monitoring: + monitoring['influxdb_configured'] = True + + # Redefine azure group-metrics 'single-table' and 'table-per-metric' + if 'azure_data_explorer' in monitoring: + if 'single-table' in monitoring['azure_data_explorer']['group_metrics']: + monitoring['azure_data_explorer']['group_metrics'] = 'SingleTable' + else: + monitoring['azure_data_explorer']['group_metrics'] = 'TablePerMetric' + # Set azure env + if 'authentication' in monitoring['azure_data_explorer']: + auth_config = monitoring['azure_data_explorer']['authentication'] + if {'client_id', 'client_secret', 'tenant_id'} <= set(auth_config): + os.environ['AZURE_CLIENT_ID'] = auth_config['client_id'] + os.environ['AZURE_CLIENT_SECRET'] = auth_config['client_secret'] + os.environ['AZURE_TENANT_ID'] = auth_config['tenant_id'] + + # Ignore default XML values if config doesn't exists + # Delete key from dict + if not conf.exists(base + ['prometheus-client']): + del monitoring['prometheus_client'] + + if not conf.exists(base + ['azure-data-explorer']): + del monitoring['azure_data_explorer'] + + return monitoring + +def verify(monitoring): + # bail out early - looks like removal from running config + if not monitoring: + return None + + if 'influxdb_configured' in monitoring: + if 'authentication' not in monitoring or \ + 'organization' not in monitoring['authentication'] or \ + 'token' not in monitoring['authentication']: + raise ConfigError(f'Authentication "organization and token" are mandatory!') + + if 'url' not in monitoring: + raise ConfigError(f'Monitoring "url" is mandatory!') + + # Verify azure-data-explorer + if 'azure_data_explorer' in monitoring: + if 'authentication' not in monitoring['azure_data_explorer'] or \ + 'client_id' not in monitoring['azure_data_explorer']['authentication'] or \ + 'client_secret' not in monitoring['azure_data_explorer']['authentication'] or \ + 'tenant_id' not in monitoring['azure_data_explorer']['authentication']: + raise ConfigError(f'Authentication "client-id, client-secret and tenant-id" are mandatory!') + + if 'database' not in monitoring['azure_data_explorer']: + raise ConfigError(f'Monitoring "database" is mandatory!') + + if 'url' not in monitoring['azure_data_explorer']: + raise ConfigError(f'Monitoring "url" is mandatory!') + + if monitoring['azure_data_explorer']['group_metrics'] == 'SingleTable' and \ + 'table' not in monitoring['azure_data_explorer']: + raise ConfigError(f'Monitoring "table" name for single-table mode is mandatory!') + + # Verify Splunk + if 'splunk' in monitoring: + if 'authentication' not in monitoring['splunk'] or \ + 'token' not in monitoring['splunk']['authentication']: + raise ConfigError(f'Authentication "organization and token" are mandatory!') + + if 'url' not in monitoring['splunk']: + raise ConfigError(f'Monitoring splunk "url" is mandatory!') + + return None + +def generate(monitoring): + if not monitoring: + # Delete config and systemd files + config_files = [config_telegraf, systemd_telegraf_service, systemd_override, syslog_telegraf] + for file in config_files: + if os.path.isfile(file): + os.unlink(file) + + # Delete old directories + if os.path.isdir(cache_dir): + rmtree(cache_dir, ignore_errors=True) + + return None + + # Create telegraf cache dir + if not os.path.exists(cache_dir): + os.makedirs(cache_dir) + + chown(cache_dir, 'telegraf', 'telegraf') + + # Create systemd override dir + if not os.path.exists(systemd_telegraf_override_dir): + os.mkdir(systemd_telegraf_override_dir) + + # Create custome scripts dir + if not os.path.exists(custom_scripts_dir): + os.mkdir(custom_scripts_dir) + + # Render telegraf configuration and systemd override + render(config_telegraf, 'monitoring/telegraf.j2', monitoring) + render(systemd_telegraf_service, 'monitoring/systemd_vyos_telegraf_service.j2', monitoring) + render(systemd_override, 'monitoring/override.conf.j2', monitoring, permission=0o640) + render(syslog_telegraf, 'monitoring/syslog_telegraf.j2', monitoring) + + chown(base_dir, 'telegraf', 'telegraf') + + return None + +def apply(monitoring): + # Reload systemd manager configuration + call('systemctl daemon-reload') + if monitoring: + call('systemctl restart vyos-telegraf.service') + else: + call('systemctl stop vyos-telegraf.service') + # Telegraf include custom rsyslog config changes + call('systemctl restart rsyslog') + +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/service_pppoe-server.py b/src/conf_mode/service_pppoe-server.py index 9fbd531da..6086ef859 100755 --- a/src/conf_mode/service_pppoe-server.py +++ b/src/conf_mode/service_pppoe-server.py @@ -24,8 +24,11 @@ from vyos.configverify import verify_accel_ppp_base_service from vyos.template import render from vyos.util import call from vyos.util import dict_search +from vyos.util import get_interface_config from vyos import ConfigError from vyos import airbag +from vyos.range_regex import range_to_regex + airbag.enable() pppoe_conf = r'/run/accel-pppd/pppoe.conf' @@ -56,6 +59,11 @@ def verify(pppoe): if 'interface' not in pppoe: raise ConfigError('At least one listen interface must be defined!') + # Check is interface exists in the system + for iface in pppoe['interface']: + if not get_interface_config(iface): + raise ConfigError(f'Interface {iface} does not exist!') + # local ippool and gateway settings config checks if not (dict_search('client_ip_pool.subnet', pppoe) or (dict_search('client_ip_pool.start', pppoe) and @@ -73,10 +81,17 @@ def generate(pppoe): if not pppoe: return None - render(pppoe_conf, 'accel-ppp/pppoe.config.tmpl', pppoe) + # Generate special regex for dynamic interfaces + for iface in pppoe['interface']: + if 'vlan_range' in pppoe['interface'][iface]: + pppoe['interface'][iface]['regex'] = [] + for vlan_range in pppoe['interface'][iface]['vlan_range']: + pppoe['interface'][iface]['regex'].append(range_to_regex(vlan_range)) + + render(pppoe_conf, 'accel-ppp/pppoe.config.j2', pppoe) if dict_search('authentication.mode', pppoe) == 'local': - render(pppoe_chap_secrets, 'accel-ppp/chap-secrets.config_dict.tmpl', + render(pppoe_chap_secrets, 'accel-ppp/chap-secrets.config_dict.j2', pppoe, permission=0o640) else: if os.path.exists(pppoe_chap_secrets): diff --git a/src/conf_mode/service_router-advert.py b/src/conf_mode/service_router-advert.py index 9afcdd63e..71b758399 100755 --- a/src/conf_mode/service_router-advert.py +++ b/src/conf_mode/service_router-advert.py @@ -101,7 +101,7 @@ def generate(rtradv): if not rtradv: return None - render(config_file, 'router-advert/radvd.conf.tmpl', rtradv, permission=0o644) + render(config_file, 'router-advert/radvd.conf.j2', rtradv, permission=0o644) return None def apply(rtradv): diff --git a/src/conf_mode/service_upnp.py b/src/conf_mode/service_upnp.py new file mode 100755 index 000000000..36f3e18a7 --- /dev/null +++ b/src/conf_mode/service_upnp.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021-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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from sys import exit +import uuid +import netifaces +from ipaddress import IPv4Network +from ipaddress import IPv6Network + +from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.configdict import get_interface_dict +from vyos.configverify import verify_vrf +from vyos.util import call +from vyos.template import render +from vyos.template import is_ipv4 +from vyos.template import is_ipv6 +from vyos.xml import defaults +from vyos import ConfigError +from vyos import airbag +airbag.enable() + +config_file = r'/run/upnp/miniupnp.conf' + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + + base = ['service', 'upnp'] + upnpd = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + + if not upnpd: + return None + + if 'rule' in upnpd: + default_member_values = defaults(base + ['rule']) + for rule,rule_config in upnpd['rule'].items(): + upnpd['rule'][rule] = dict_merge(default_member_values, upnpd['rule'][rule]) + + uuidgen = uuid.uuid1() + upnpd.update({'uuid': uuidgen}) + + return upnpd + +def get_all_interface_addr(prefix, filter_dev, filter_family): + list_addr = [] + interfaces = netifaces.interfaces() + + for interface in interfaces: + if filter_dev and interface in filter_dev: + continue + addrs = netifaces.ifaddresses(interface) + if netifaces.AF_INET in addrs.keys(): + if netifaces.AF_INET in filter_family: + for addr in addrs[netifaces.AF_INET]: + if prefix: + # we need to manually assemble a list of IPv4 address/prefix + prefix = '/' + \ + str(IPv4Network('0.0.0.0/' + addr['netmask']).prefixlen) + list_addr.append(addr['addr'] + prefix) + else: + list_addr.append(addr['addr']) + if netifaces.AF_INET6 in addrs.keys(): + if netifaces.AF_INET6 in filter_family: + for addr in addrs[netifaces.AF_INET6]: + if prefix: + # we need to manually assemble a list of IPv4 address/prefix + bits = bin(int(addr['netmask'].replace(':', '').split('/')[0], 16)).count('1') + prefix = '/' + str(bits) + list_addr.append(addr['addr'] + prefix) + else: + list_addr.append(addr['addr']) + + return list_addr + +def verify(upnpd): + if not upnpd: + return None + + if 'wan_interface' not in upnpd: + raise ConfigError('To enable UPNP, you must have the "wan-interface" option!') + + if 'rule' in upnpd: + for rule, rule_config in upnpd['rule'].items(): + for option in ['external_port_range', 'internal_port_range', 'ip', 'action']: + if option not in rule_config: + tmp = option.replace('_', '-') + raise ConfigError(f'Every UPNP rule requires "{tmp}" to be set!') + + if 'stun' in upnpd: + for option in ['host', 'port']: + if option not in upnpd['stun']: + raise ConfigError(f'A UPNP stun support must have an "{option}" option!') + + # Check the validity of the IP address + listen_dev = [] + system_addrs_cidr = get_all_interface_addr(True, [], [netifaces.AF_INET, netifaces.AF_INET6]) + system_addrs = get_all_interface_addr(False, [], [netifaces.AF_INET, netifaces.AF_INET6]) + for listen_if_or_addr in upnpd['listen']: + if listen_if_or_addr not in netifaces.interfaces(): + listen_dev.append(listen_if_or_addr) + if (listen_if_or_addr not in system_addrs) and (listen_if_or_addr not in system_addrs_cidr) and (listen_if_or_addr not in netifaces.interfaces()): + if is_ipv4(listen_if_or_addr) and IPv4Network(listen_if_or_addr).is_multicast: + raise ConfigError(f'The address "{listen_if_or_addr}" is an address that is not allowed to listen on. It is not an interface address nor a multicast address!') + if is_ipv6(listen_if_or_addr) and IPv6Network(listen_if_or_addr).is_multicast: + raise ConfigError(f'The address "{listen_if_or_addr}" is an address that is not allowed to listen on. It is not an interface address nor a multicast address!') + + system_listening_dev_addrs_cidr = get_all_interface_addr(True, listen_dev, [netifaces.AF_INET6]) + system_listening_dev_addrs = get_all_interface_addr(False, listen_dev, [netifaces.AF_INET6]) + for listen_if_or_addr in upnpd['listen']: + if listen_if_or_addr not in netifaces.interfaces() and (listen_if_or_addr not in system_listening_dev_addrs_cidr) and (listen_if_or_addr not in system_listening_dev_addrs) and is_ipv6(listen_if_or_addr) and (not IPv6Network(listen_if_or_addr).is_multicast): + raise ConfigError(f'{listen_if_or_addr} must listen on the interface of the network card') + +def generate(upnpd): + if not upnpd: + return None + + if os.path.isfile(config_file): + os.unlink(config_file) + + render(config_file, 'firewall/upnpd.conf.j2', upnpd) + +def apply(upnpd): + systemd_service_name = 'miniupnpd.service' + if not upnpd: + # Stop the UPNP service + call(f'systemctl stop {systemd_service_name}') + else: + # Start the UPNP service + call(f'systemctl restart {systemd_service_name}') + +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/service_webproxy.py b/src/conf_mode/service_webproxy.py index a16cc4aeb..32af31bde 100755 --- a/src/conf_mode/service_webproxy.py +++ b/src/conf_mode/service_webproxy.py @@ -61,7 +61,7 @@ def generate_sg_localdb(category, list_type, role, proxy): user=user_group, group=user_group) # temporary config file, deleted after generation - render(sg_tmp_file, 'squid/sg_acl.conf.tmpl', tmp, + render(sg_tmp_file, 'squid/sg_acl.conf.j2', tmp, user=user_group, group=user_group) call(f'su - {user_group} -c "squidGuard -d -c {sg_tmp_file} -C {db_file}"') @@ -166,8 +166,8 @@ def generate(proxy): if not proxy: return None - render(squid_config_file, 'squid/squid.conf.tmpl', proxy) - render(squidguard_config_file, 'squid/squidGuard.conf.tmpl', proxy) + render(squid_config_file, 'squid/squid.conf.j2', proxy) + render(squidguard_config_file, 'squid/squidGuard.conf.j2', proxy) cat_dict = { 'local-block' : 'domains', diff --git a/src/conf_mode/snmp.py b/src/conf_mode/snmp.py index 6c6367045..5cd24db32 100755 --- a/src/conf_mode/snmp.py +++ b/src/conf_mode/snmp.py @@ -18,17 +18,20 @@ import os from sys import exit +from vyos.base import Warning from vyos.config import Config +from vyos.configdict import dict_merge from vyos.configverify import verify_vrf from vyos.snmpv3_hashgen import plaintext_to_md5 from vyos.snmpv3_hashgen import plaintext_to_sha1 from vyos.snmpv3_hashgen import random from vyos.template import render -from vyos.template import is_ipv4 from vyos.util import call from vyos.util import chmod_755 +from vyos.util import dict_search from vyos.validate import is_addr_assigned from vyos.version import get_version_data +from vyos.xml import defaults from vyos import ConfigError from vyos import airbag airbag.enable() @@ -37,57 +40,26 @@ 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' -default_script_dir = r'/config/user-data/' systemd_override = r'/etc/systemd/system/snmpd.service.d/override.conf' +systemd_service = 'snmpd.service' -# SNMP OIDs used to mark auth/priv type -OIDs = { - 'md5' : '.1.3.6.1.6.3.10.1.1.2', - 'sha' : '.1.3.6.1.6.3.10.1.1.3', - 'aes' : '.1.3.6.1.6.3.10.1.2.4', - 'des' : '.1.3.6.1.6.3.10.1.2.2', - 'none': '.1.3.6.1.6.3.10.1.2.1' -} - -default_config_data = { - 'listen_on': [], - 'listen_address': [], - 'ipv6_enabled': 'True', - 'communities': [], - 'smux_peers': [], - 'location' : '', - 'protocol' : 'udp', - 'description' : '', - 'contact' : '', - 'route_table': 'False', - 'trap_source': '', - 'trap_targets': [], - 'vyos_user': '', - 'vyos_user_pass': '', - 'version': '', - 'v3_enabled': 'False', - 'v3_engineid': '', - 'v3_groups': [], - 'v3_traps': [], - 'v3_users': [], - 'v3_views': [], - 'script_ext': [] -} - -def rmfile(file): - if os.path.isfile(file): - os.unlink(file) - -def get_config(): - snmp = default_config_data - conf = Config() - if not conf.exists('service snmp'): - return None +def get_config(config=None): + if config: + conf = config else: - if conf.exists('system ipv6 disable'): - snmp['ipv6_enabled'] = False + conf = Config() + base = ['service', 'snmp'] - conf.set_level('service snmp') + snmp = conf.get_config_dict(base, key_mangling=('-', '_'), + get_first_key=True, no_tag_node_value_mangle=True) + if not conf.exists(base): + snmp.update({'deleted' : ''}) + + if conf.exists(['service', 'lldp', 'snmp', 'enable']): + snmp.update({'lldp_snmp' : ''}) + + if 'deleted' in snmp: + return snmp version_data = get_version_data() snmp['version'] = version_data['version'] @@ -96,477 +68,217 @@ def get_config(): snmp['vyos_user'] = 'vyos' + random(8) snmp['vyos_user_pass'] = random(16) - if conf.exists('community'): - for name in conf.list_nodes('community'): - community = { - 'name': name, - 'authorization': 'ro', - 'network_v4': [], - 'network_v6': [], - 'has_source' : False - } - - if conf.exists('community {0} authorization'.format(name)): - community['authorization'] = conf.return_value('community {0} authorization'.format(name)) - - # Subnet of SNMP client(s) allowed to contact system - if conf.exists('community {0} network'.format(name)): - for addr in conf.return_values('community {0} network'.format(name)): - if is_ipv4(addr): - community['network_v4'].append(addr) - else: - community['network_v6'].append(addr) - - # IP address of SNMP client allowed to contact system - if conf.exists('community {0} client'.format(name)): - for addr in conf.return_values('community {0} client'.format(name)): - if is_ipv4(addr): - community['network_v4'].append(addr) - else: - community['network_v6'].append(addr) - - if (len(community['network_v4']) > 0) or (len(community['network_v6']) > 0): - community['has_source'] = True - - snmp['communities'].append(community) - - if conf.exists('contact'): - snmp['contact'] = conf.return_value('contact') - - if conf.exists('description'): - snmp['description'] = conf.return_value('description') - - if conf.exists('listen-address'): - for addr in conf.list_nodes('listen-address'): - port = '161' - if conf.exists('listen-address {0} port'.format(addr)): - port = conf.return_value('listen-address {0} port'.format(addr)) - - snmp['listen_address'].append((addr, port)) + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + default_values = defaults(base) + + # We can not merge defaults for tagNodes - those need to be blended in + # per tagNode instance + if 'listen_address' in default_values: + del default_values['listen_address'] + if 'community' in default_values: + del default_values['community'] + if 'trap_target' in default_values: + del default_values['trap_target'] + if 'v3' in default_values: + del default_values['v3'] + snmp = dict_merge(default_values, snmp) + + if 'listen_address' in snmp: + default_values = defaults(base + ['listen-address']) + for address in snmp['listen_address']: + snmp['listen_address'][address] = dict_merge( + default_values, snmp['listen_address'][address]) # Always listen on localhost if an explicit address has been configured # This is a safety measure to not end up with invalid listen addresses # that are not configured on this system. See https://phabricator.vyos.net/T850 - if not '127.0.0.1' in conf.list_nodes('listen-address'): - snmp['listen_address'].append(('127.0.0.1', '161')) - - if not '::1' in conf.list_nodes('listen-address'): - snmp['listen_address'].append(('::1', '161')) - - if conf.exists('location'): - snmp['location'] = conf.return_value('location') - - if conf.exists('protocol'): - snmp['protocol'] = conf.return_value('protocol') - - if conf.exists('smux-peer'): - snmp['smux_peers'] = conf.return_values('smux-peer') - - if conf.exists('trap-source'): - snmp['trap_source'] = conf.return_value('trap-source') - - if conf.exists('trap-target'): - for target in conf.list_nodes('trap-target'): - trap_tgt = { - 'target': target, - 'community': '', - 'port': '' - } - - if conf.exists('trap-target {0} community'.format(target)): - trap_tgt['community'] = conf.return_value('trap-target {0} community'.format(target)) - - if conf.exists('trap-target {0} port'.format(target)): - trap_tgt['port'] = conf.return_value('trap-target {0} port'.format(target)) - - snmp['trap_targets'].append(trap_tgt) - - if conf.exists('script-extensions'): - for extname in conf.list_nodes('script-extensions extension-name'): - conf_script = conf.return_value('script-extensions extension-name {} script'.format(extname)) - # if script has not absolute path, use pre configured path - if "/" not in conf_script: - conf_script = default_script_dir + conf_script - - extension = { - 'name': extname, - 'script' : conf_script - } - - snmp['script_ext'].append(extension) - - if conf.exists('oid-enable route-table'): - snmp['route_table'] = True - - if conf.exists('vrf'): - # Append key to dict but don't place it in the default dictionary. - # This is required to make the override.conf.tmpl work until we - # migrate to get_config_dict(). - snmp['vrf'] = conf.return_value('vrf') - - - ######################################################################### - # ____ _ _ __ __ ____ _____ # - # / ___|| \ | | \/ | _ \ __ _|___ / # - # \___ \| \| | |\/| | |_) | \ \ / / |_ \ # - # ___) | |\ | | | | __/ \ V / ___) | # - # |____/|_| \_|_| |_|_| \_/ |____/ # - # # - # now take care about the fancy SNMP v3 stuff, or bail out eraly # - ######################################################################### - if not conf.exists('v3'): - return snmp - else: - snmp['v3_enabled'] = True - - # 'set service snmp v3 engineid' - if conf.exists('v3 engineid'): - snmp['v3_engineid'] = conf.return_value('v3 engineid') - - # 'set service snmp v3 group' - if conf.exists('v3 group'): - for group in conf.list_nodes('v3 group'): - v3_group = { - 'name': group, - 'mode': 'ro', - 'seclevel': 'auth', - 'view': '' - } - - if conf.exists('v3 group {0} mode'.format(group)): - v3_group['mode'] = conf.return_value('v3 group {0} mode'.format(group)) - - if conf.exists('v3 group {0} seclevel'.format(group)): - v3_group['seclevel'] = conf.return_value('v3 group {0} seclevel'.format(group)) - - if conf.exists('v3 group {0} view'.format(group)): - v3_group['view'] = conf.return_value('v3 group {0} view'.format(group)) - - snmp['v3_groups'].append(v3_group) - - # 'set service snmp v3 trap-target' - if conf.exists('v3 trap-target'): - for trap in conf.list_nodes('v3 trap-target'): - trap_cfg = { - 'ipAddr': trap, - 'secName': '', - 'authProtocol': 'md5', - 'authPassword': '', - 'authMasterKey': '', - 'privProtocol': 'des', - 'privPassword': '', - 'privMasterKey': '', - 'ipProto': 'udp', - 'ipPort': '162', - 'type': '', - 'secLevel': 'noAuthNoPriv' - } - - if conf.exists('v3 trap-target {0} user'.format(trap)): - # Set the securityName used for authenticated SNMPv3 messages. - trap_cfg['secName'] = conf.return_value('v3 trap-target {0} user'.format(trap)) - - if conf.exists('v3 trap-target {0} auth type'.format(trap)): - # Set the authentication protocol (MD5 or SHA) used for authenticated SNMPv3 messages - # cmdline option '-a' - trap_cfg['authProtocol'] = conf.return_value('v3 trap-target {0} auth type'.format(trap)) - - if conf.exists('v3 trap-target {0} auth plaintext-password'.format(trap)): - # Set the authentication pass phrase used for authenticated SNMPv3 messages. - # cmdline option '-A' - trap_cfg['authPassword'] = conf.return_value('v3 trap-target {0} auth plaintext-password'.format(trap)) - - if conf.exists('v3 trap-target {0} auth encrypted-password'.format(trap)): - # Sets the keys to be used for SNMPv3 transactions. These options allow you to set the master authentication keys. - # cmdline option '-3m' - trap_cfg['authMasterKey'] = conf.return_value('v3 trap-target {0} auth encrypted-password'.format(trap)) - - if conf.exists('v3 trap-target {0} privacy type'.format(trap)): - # Set the privacy protocol (DES or AES) used for encrypted SNMPv3 messages. - # cmdline option '-x' - trap_cfg['privProtocol'] = conf.return_value('v3 trap-target {0} privacy type'.format(trap)) - - if conf.exists('v3 trap-target {0} privacy plaintext-password'.format(trap)): - # Set the privacy pass phrase used for encrypted SNMPv3 messages. - # cmdline option '-X' - trap_cfg['privPassword'] = conf.return_value('v3 trap-target {0} privacy plaintext-password'.format(trap)) - - if conf.exists('v3 trap-target {0} privacy encrypted-password'.format(trap)): - # Sets the keys to be used for SNMPv3 transactions. These options allow you to set the master encryption keys. - # cmdline option '-3M' - trap_cfg['privMasterKey'] = conf.return_value('v3 trap-target {0} privacy encrypted-password'.format(trap)) - - if conf.exists('v3 trap-target {0} protocol'.format(trap)): - trap_cfg['ipProto'] = conf.return_value('v3 trap-target {0} protocol'.format(trap)) - - if conf.exists('v3 trap-target {0} port'.format(trap)): - trap_cfg['ipPort'] = conf.return_value('v3 trap-target {0} port'.format(trap)) - - if conf.exists('v3 trap-target {0} type'.format(trap)): - trap_cfg['type'] = conf.return_value('v3 trap-target {0} type'.format(trap)) - - # Determine securityLevel used for SNMPv3 messages (noAuthNoPriv|authNoPriv|authPriv). - # Appropriate pass phrase(s) must provided when using any level higher than noAuthNoPriv. - if trap_cfg['authPassword'] or trap_cfg['authMasterKey']: - if trap_cfg['privProtocol'] or trap_cfg['privPassword']: - trap_cfg['secLevel'] = 'authPriv' - else: - trap_cfg['secLevel'] = 'authNoPriv' - - snmp['v3_traps'].append(trap_cfg) - - # 'set service snmp v3 user' - if conf.exists('v3 user'): - for user in conf.list_nodes('v3 user'): - user_cfg = { - 'name': user, - 'authMasterKey': '', - 'authPassword': '', - 'authProtocol': 'md5', - 'authOID': 'none', - 'group': '', - 'mode': 'ro', - 'privMasterKey': '', - 'privPassword': '', - 'privOID': '', - 'privProtocol': 'des' - } - - # v3 user {0} auth - if conf.exists('v3 user {0} auth encrypted-password'.format(user)): - user_cfg['authMasterKey'] = conf.return_value('v3 user {0} auth encrypted-password'.format(user)) - - if conf.exists('v3 user {0} auth plaintext-password'.format(user)): - user_cfg['authPassword'] = conf.return_value('v3 user {0} auth plaintext-password'.format(user)) - - # load default value - type = user_cfg['authProtocol'] - if conf.exists('v3 user {0} auth type'.format(user)): - type = conf.return_value('v3 user {0} auth type'.format(user)) - - # (re-)update with either default value or value from CLI - user_cfg['authProtocol'] = type - user_cfg['authOID'] = OIDs[type] - - # v3 user {0} group - if conf.exists('v3 user {0} group'.format(user)): - user_cfg['group'] = conf.return_value('v3 user {0} group'.format(user)) - - # v3 user {0} mode - if conf.exists('v3 user {0} mode'.format(user)): - user_cfg['mode'] = conf.return_value('v3 user {0} mode'.format(user)) - - # v3 user {0} privacy - if conf.exists('v3 user {0} privacy encrypted-password'.format(user)): - user_cfg['privMasterKey'] = conf.return_value('v3 user {0} privacy encrypted-password'.format(user)) - - if conf.exists('v3 user {0} privacy plaintext-password'.format(user)): - user_cfg['privPassword'] = conf.return_value('v3 user {0} privacy plaintext-password'.format(user)) - - # load default value - type = user_cfg['privProtocol'] - if conf.exists('v3 user {0} privacy type'.format(user)): - type = conf.return_value('v3 user {0} privacy type'.format(user)) - - # (re-)update with either default value or value from CLI - user_cfg['privProtocol'] = type - user_cfg['privOID'] = OIDs[type] - - snmp['v3_users'].append(user_cfg) - - # 'set service snmp v3 view' - if conf.exists('v3 view'): - for view in conf.list_nodes('v3 view'): - view_cfg = { - 'name': view, - 'oids': [] - } - - if conf.exists('v3 view {0} oid'.format(view)): - for oid in conf.list_nodes('v3 view {0} oid'.format(view)): - oid_cfg = { - 'oid': oid - } - view_cfg['oids'].append(oid_cfg) - snmp['v3_views'].append(view_cfg) + if '127.0.0.1' not in snmp['listen_address']: + tmp = {'127.0.0.1': {'port': '161'}} + snmp['listen_address'] = dict_merge(tmp, snmp['listen_address']) + + if '::1' not in snmp['listen_address']: + tmp = {'::1': {'port': '161'}} + snmp['listen_address'] = dict_merge(tmp, snmp['listen_address']) + + if 'community' in snmp: + default_values = defaults(base + ['community']) + for community in snmp['community']: + snmp['community'][community] = dict_merge( + default_values, snmp['community'][community]) + + if 'trap_target' in snmp: + default_values = defaults(base + ['trap-target']) + for trap in snmp['trap_target']: + snmp['trap_target'][trap] = dict_merge( + default_values, snmp['trap_target'][trap]) + + if 'v3' in snmp: + default_values = defaults(base + ['v3']) + # tagNodes need to be merged in individually later on + for tmp in ['user', 'group', 'trap_target']: + del default_values[tmp] + snmp['v3'] = dict_merge(default_values, snmp['v3']) + + for user_group in ['user', 'group']: + if user_group in snmp['v3']: + default_values = defaults(base + ['v3', user_group]) + for tmp in snmp['v3'][user_group]: + snmp['v3'][user_group][tmp] = dict_merge( + default_values, snmp['v3'][user_group][tmp]) + + if 'trap_target' in snmp['v3']: + default_values = defaults(base + ['v3', 'trap-target']) + for trap in snmp['v3']['trap_target']: + snmp['v3']['trap_target'][trap] = dict_merge( + default_values, snmp['v3']['trap_target'][trap]) return snmp def verify(snmp): - if snmp is None: - # we can not delete SNMP when LLDP is configured with SNMP - conf = Config() - if conf.exists('service lldp snmp enable'): - raise ConfigError('Can not delete SNMP service, as LLDP still uses SNMP!') - + if not snmp: return None + if {'deleted', 'lldp_snmp'} <= set(snmp): + raise ConfigError('Can not delete SNMP service, as LLDP still uses SNMP!') + ### check if the configured script actually exist - if snmp['script_ext']: - for ext in snmp['script_ext']: - if not os.path.isfile(ext['script']): - print ("WARNING: script: {} doesn't exist".format(ext['script'])) + if 'script_extensions' in snmp and 'extension_name' in snmp['script_extensions']: + for extension, extension_opt in snmp['script_extensions']['extension_name'].items(): + if 'script' not in extension_opt: + raise ConfigError(f'Script extension "{extension}" requires an actual script to be configured!') + + tmp = extension_opt['script'] + if not os.path.isfile(tmp): + Warning(f'script "{tmp}" does not exist!') else: - chmod_755(ext['script']) - - for listen in snmp['listen_address']: - addr = listen[0] - port = listen[1] - protocol = snmp['protocol'] - - tmp = None - if is_ipv4(addr): - # example: udp:127.0.0.1:161 - tmp = f'{protocol}:{addr}:{port}' - elif snmp['ipv6_enabled']: - # example: udp6:[::1]:161 - tmp = f'{protocol}6:[{addr}]:{port}' - - # We only wan't to configure addresses that exist on the system. - # Hint the user if they don't exist - if is_addr_assigned(addr): - if tmp: snmp['listen_on'].append(tmp) - else: - print(f'WARNING: SNMP listen address {addr} not configured!') + chmod_755(extension_opt['script']) + + if 'listen_address' in snmp: + for address in snmp['listen_address']: + # We only wan't to configure addresses that exist on the system. + # Hint the user if they don't exist + if not is_addr_assigned(address): + Warning(f'SNMP listen address "{address}" not configured!') + + if 'trap_target' in snmp: + for trap, trap_config in snmp['trap_target'].items(): + if 'community' not in trap_config: + raise ConfigError(f'Trap target "{trap}" requires a community to be set!') verify_vrf(snmp) # bail out early if SNMP v3 is not configured - if not snmp['v3_enabled']: + if 'v3' not in snmp: return None - if 'v3_groups' in snmp.keys(): - for group in snmp['v3_groups']: - # - # A view must exist prior to mapping it into a group - # - if 'view' in group.keys(): - error = True - if 'v3_views' in snmp.keys(): - for view in snmp['v3_views']: - if view['name'] == group['view']: - error = False - if error: - raise ConfigError('You must create view "{0}" first'.format(group['view'])) - else: - raise ConfigError('"view" must be specified') - - if not 'mode' in group.keys(): - raise ConfigError('"mode" must be specified') - - if not 'seclevel' in group.keys(): - raise ConfigError('"seclevel" must be specified') - - if 'v3_traps' in snmp.keys(): - for trap in snmp['v3_traps']: - if trap['authPassword'] and trap['authMasterKey']: - raise ConfigError('Must specify only one of encrypted-password/plaintext-key for trap auth') - - if trap['authPassword'] == '' and trap['authMasterKey'] == '': - raise ConfigError('Must specify encrypted-password or plaintext-key for trap auth') - - if trap['privPassword'] and trap['privMasterKey']: - raise ConfigError('Must specify only one of encrypted-password/plaintext-key for trap privacy') + if 'user' in snmp['v3']: + for user, user_config in snmp['v3']['user'].items(): + if 'group' not in user_config: + raise ConfigError(f'Group membership required for user "{user}"!') - if trap['privPassword'] == '' and trap['privMasterKey'] == '': - raise ConfigError('Must specify encrypted-password or plaintext-key for trap privacy') + if 'plaintext_password' not in user_config['auth'] and 'encrypted_password' not in user_config['auth']: + raise ConfigError(f'Must specify authentication encrypted-password or plaintext-password for user "{user}"!') - if not 'type' in trap.keys(): - raise ConfigError('v3 trap: "type" must be specified') + if 'plaintext_password' not in user_config['privacy'] and 'encrypted_password' not in user_config['privacy']: + raise ConfigError(f'Must specify privacy encrypted-password or plaintext-password for user "{user}"!') - if not 'authPassword' and 'authMasterKey' in trap.keys(): - raise ConfigError('v3 trap: "auth" must be specified') + if 'group' in snmp['v3']: + for group, group_config in snmp['v3']['group'].items(): + if 'seclevel' not in group_config: + raise ConfigError(f'Must configure "seclevel" for group "{group}"!') + if 'view' not in group_config: + raise ConfigError(f'Must configure "view" for group "{group}"!') - if not 'authProtocol' in trap.keys(): - raise ConfigError('v3 trap: "protocol" must be specified') + # Check if 'view' exists + view = group_config['view'] + if 'view' not in snmp['v3'] or view not in snmp['v3']['view']: + raise ConfigError(f'You must create view "{view}" first!') - if not 'privPassword' and 'privMasterKey' in trap.keys(): - raise ConfigError('v3 trap: "user" must be specified') + if 'view' in snmp['v3']: + for view, view_config in snmp['v3']['view'].items(): + if 'oid' not in view_config: + raise ConfigError(f'Must configure an "oid" for view "{view}"!') - if 'v3_users' in snmp.keys(): - for user in snmp['v3_users']: - # - # Group must exist prior to mapping it into a group - # seclevel will be extracted from group - # - if user['group']: - error = True - if 'v3_groups' in snmp.keys(): - for group in snmp['v3_groups']: - if group['name'] == user['group']: - seclevel = group['seclevel'] - error = False + if 'trap_target' in snmp['v3']: + for trap, trap_config in snmp['v3']['trap_target'].items(): + if 'plaintext_password' not in trap_config['auth'] and 'encrypted_password' not in trap_config['auth']: + raise ConfigError(f'Must specify one of authentication encrypted-password or plaintext-password for trap "{trap}"!') - if error: - raise ConfigError('You must create group "{0}" first'.format(user['group'])) + if {'plaintext_password', 'encrypted_password'} <= set(trap_config['auth']): + raise ConfigError(f'Can not specify both authentication encrypted-password and plaintext-password for trap "{trap}"!') - # Depending on the configured security level the user has to provide additional info - if (not user['authPassword'] and not user['authMasterKey']): - raise ConfigError('Must specify encrypted-password or plaintext-key for user auth') + if 'plaintext_password' not in trap_config['privacy'] and 'encrypted_password' not in trap_config['privacy']: + raise ConfigError(f'Must specify one of privacy encrypted-password or plaintext-password for trap "{trap}"!') - if user['privPassword'] == '' and user['privMasterKey'] == '': - raise ConfigError('Must specify encrypted-password or plaintext-key for user privacy') + if {'plaintext_password', 'encrypted_password'} <= set(trap_config['privacy']): + raise ConfigError(f'Can not specify both privacy encrypted-password and plaintext-password for trap "{trap}"!') - if user['mode'] == '': - raise ConfigError('Must specify user mode ro/rw') - - if 'v3_views' in snmp.keys(): - for view in snmp['v3_views']: - if not view['oids']: - raise ConfigError('Must configure an oid') + if 'type' not in trap_config: + raise ConfigError('SNMP v3 trap "type" must be specified!') return None def generate(snmp): + # # As we are manipulating the snmpd user database we have to stop it first! # This is even save if service is going to be removed - call('systemctl stop snmpd.service') - config_files = [config_file_client, config_file_daemon, config_file_access, - config_file_user, systemd_override] + call(f'systemctl stop {systemd_service}') + # Clean config files + config_files = [config_file_client, config_file_daemon, + config_file_access, config_file_user, systemd_override] for file in config_files: - rmfile(file) + if os.path.isfile(file): + os.unlink(file) if not snmp: return None - if 'v3_users' in snmp.keys(): + if 'v3' in snmp: # net-snmp is now regenerating the configuration file in the background # thus we need to re-open and re-read the file as the content changed. # After that we can no read the encrypted password from the config and # replace the CLI plaintext password with its encrypted version. - os.environ["vyos_libexec_dir"] = "/usr/libexec/vyos" + os.environ['vyos_libexec_dir'] = '/usr/libexec/vyos' - for user in snmp['v3_users']: - if user['authProtocol'] == 'sha': - hash = plaintext_to_sha1 - else: - hash = plaintext_to_md5 + if 'user' in snmp['v3']: + for user, user_config in snmp['v3']['user'].items(): + if dict_search('auth.type', user_config) == 'sha': + hash = plaintext_to_sha1 + else: + hash = plaintext_to_md5 + + if dict_search('auth.plaintext_password', user_config) is not None: + tmp = hash(dict_search('auth.plaintext_password', user_config), + dict_search('v3.engineid', snmp)) + + snmp['v3']['user'][user]['auth']['encrypted_password'] = tmp + del snmp['v3']['user'][user]['auth']['plaintext_password'] - if user['authPassword']: - user['authMasterKey'] = hash(user['authPassword'], snmp['v3_engineid']) - user['authPassword'] = '' + call(f'/opt/vyatta/sbin/my_set service snmp v3 user "{user}" auth encrypted-password "{tmp}" > /dev/null') + call(f'/opt/vyatta/sbin/my_delete service snmp v3 user "{user}" auth plaintext-password > /dev/null') - call('/opt/vyatta/sbin/my_set service snmp v3 user "{name}" auth encrypted-password "{authMasterKey}" > /dev/null'.format(**user)) - call('/opt/vyatta/sbin/my_delete service snmp v3 user "{name}" auth plaintext-password > /dev/null'.format(**user)) + if dict_search('privacy.plaintext_password', user_config) is not None: + tmp = hash(dict_search('privacy.plaintext_password', user_config), + dict_search('v3.engineid', snmp)) - if user['privPassword']: - user['privMasterKey'] = hash(user['privPassword'], snmp['v3_engineid']) - user['privPassword'] = '' + snmp['v3']['user'][user]['privacy']['encrypted_password'] = tmp + del snmp['v3']['user'][user]['privacy']['plaintext_password'] - call('/opt/vyatta/sbin/my_set service snmp v3 user "{name}" privacy encrypted-password "{privMasterKey}" > /dev/null'.format(**user)) - call('/opt/vyatta/sbin/my_delete service snmp v3 user "{name}" privacy plaintext-password > /dev/null'.format(**user)) + call(f'/opt/vyatta/sbin/my_set service snmp v3 user "{user}" privacy encrypted-password "{tmp}" > /dev/null') + call(f'/opt/vyatta/sbin/my_delete service snmp v3 user "{user}" privacy plaintext-password > /dev/null') # Write client config file - render(config_file_client, 'snmp/etc.snmp.conf.tmpl', snmp) + render(config_file_client, 'snmp/etc.snmp.conf.j2', snmp) # Write server config file - render(config_file_daemon, 'snmp/etc.snmpd.conf.tmpl', snmp) + render(config_file_daemon, 'snmp/etc.snmpd.conf.j2', snmp) # Write access rights config file - render(config_file_access, 'snmp/usr.snmpd.conf.tmpl', snmp) + render(config_file_access, 'snmp/usr.snmpd.conf.j2', snmp) # Write access rights config file - render(config_file_user, 'snmp/var.snmpd.conf.tmpl', snmp) + render(config_file_user, 'snmp/var.snmpd.conf.j2', snmp) # Write daemon configuration file - render(systemd_override, 'snmp/override.conf.tmpl', snmp) + render(systemd_override, 'snmp/override.conf.j2', snmp) return None @@ -578,7 +290,7 @@ def apply(snmp): return None # start SNMP daemon - call('systemctl restart snmpd.service') + call(f'systemctl restart {systemd_service}') # Enable AgentX in FRR # This should be done for each daemon individually because common command diff --git a/src/conf_mode/ssh.py b/src/conf_mode/ssh.py index 67724b043..28669694b 100755 --- a/src/conf_mode/ssh.py +++ b/src/conf_mode/ssh.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2021 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -33,6 +33,9 @@ airbag.enable() config_file = r'/run/sshd/sshd_config' systemd_override = r'/etc/systemd/system/ssh.service.d/override.conf' +sshguard_config_file = '/etc/sshguard/sshguard.conf' +sshguard_whitelist = '/etc/sshguard/whitelist' + key_rsa = '/etc/ssh/ssh_host_rsa_key' key_dsa = '/etc/ssh/ssh_host_dsa_key' key_ed25519 = '/etc/ssh/ssh_host_ed25519_key' @@ -54,6 +57,11 @@ def get_config(config=None): # pass config file path - used in override template ssh['config_file'] = config_file + # Ignore default XML values if config doesn't exists + # Delete key from dict + if not conf.exists(base + ['dynamic-protection']): + del ssh['dynamic_protection'] + return ssh def verify(ssh): @@ -84,8 +92,12 @@ def generate(ssh): syslog(LOG_INFO, 'SSH ed25519 host key not found, generating new key!') call(f'ssh-keygen -q -N "" -t ed25519 -f {key_ed25519}') - render(config_file, 'ssh/sshd_config.tmpl', ssh) - render(systemd_override, 'ssh/override.conf.tmpl', ssh) + render(config_file, 'ssh/sshd_config.j2', ssh) + render(systemd_override, 'ssh/override.conf.j2', ssh) + + if 'dynamic_protection' in ssh: + render(sshguard_config_file, 'ssh/sshguard_config.j2', ssh) + render(sshguard_whitelist, 'ssh/sshguard_whitelist.j2', ssh) # Reload systemd manager configuration call('systemctl daemon-reload') @@ -95,7 +107,12 @@ def apply(ssh): if not ssh: # SSH access is removed in the commit call('systemctl stop ssh.service') + call('systemctl stop sshguard.service') return None + if 'dynamic_protection' not in ssh: + call('systemctl stop sshguard.service') + else: + call('systemctl restart sshguard.service') call('systemctl restart ssh.service') return None diff --git a/src/conf_mode/system-ip.py b/src/conf_mode/system-ip.py index 32cb2f036..05fc3a97a 100755 --- a/src/conf_mode/system-ip.py +++ b/src/conf_mode/system-ip.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 @@ -20,14 +20,13 @@ from vyos.config import Config from vyos.configdict import dict_merge from vyos.util import call from vyos.util import dict_search +from vyos.util import sysctl_write +from vyos.util import write_file from vyos.xml import defaults from vyos import ConfigError from vyos import airbag airbag.enable() -def sysctl(name, value): - call(f'sysctl -wq {name}={value}') - def get_config(config=None): if config: conf = config @@ -50,29 +49,29 @@ def generate(opt): pass def apply(opt): + # Apply ARP threshold values + # table_size has a default value - thus the key always exists size = int(dict_search('arp.table_size', opt)) - if size: - # apply ARP threshold values - sysctl('net.ipv4.neigh.default.gc_thresh3', str(size)) - sysctl('net.ipv4.neigh.default.gc_thresh2', str(size // 2)) - sysctl('net.ipv4.neigh.default.gc_thresh1', str(size // 8)) + # Amount upon reaching which the records begin to be cleared immediately + sysctl_write('net.ipv4.neigh.default.gc_thresh3', size) + # Amount after which the records begin to be cleaned after 5 seconds + sysctl_write('net.ipv4.neigh.default.gc_thresh2', size // 2) + # Minimum number of stored records is indicated which is not cleared + sysctl_write('net.ipv4.neigh.default.gc_thresh1', size // 8) # enable/disable IPv4 forwarding - tmp = '1' - if 'disable_forwarding' in opt: - tmp = '0' - sysctl('net.ipv4.conf.all.forwarding', tmp) + tmp = dict_search('disable_forwarding', opt) + value = '0' if (tmp != None) else '1' + write_file('/proc/sys/net/ipv4/conf/all/forwarding', value) - tmp = '0' - # configure multipath - dict_search() returns an empty dict if key was found - if isinstance(dict_search('multipath.ignore_unreachable_nexthops', opt), dict): - tmp = '1' - sysctl('net.ipv4.fib_multipath_use_neigh', tmp) + # configure multipath + tmp = dict_search('multipath.ignore_unreachable_nexthops', opt) + value = '1' if (tmp != None) else '0' + sysctl_write('net.ipv4.fib_multipath_use_neigh', value) - tmp = '0' - if isinstance(dict_search('multipath.layer4_hashing', opt), dict): - tmp = '1' - sysctl('net.ipv4.fib_multipath_hash_policy', tmp) + tmp = dict_search('multipath.layer4_hashing', opt) + value = '1' if (tmp != None) else '0' + sysctl_write('net.ipv4.fib_multipath_hash_policy', value) if __name__ == '__main__': try: diff --git a/src/conf_mode/system-ipv6.py b/src/conf_mode/system-ipv6.py index f70ec2631..26aacf46b 100755 --- a/src/conf_mode/system-ipv6.py +++ b/src/conf_mode/system-ipv6.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019 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 @@ -15,95 +15,68 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -import sys from sys import exit -from copy import deepcopy from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.util import dict_search +from vyos.util import sysctl_write +from vyos.util import write_file +from vyos.xml import defaults from vyos import ConfigError -from vyos.util import call - from vyos import airbag airbag.enable() -ipv6_disable_file = '/etc/modprobe.d/vyos_disable_ipv6.conf' - -default_config_data = { - 'reboot_message': False, - 'ipv6_forward': '1', - 'disable_addr_assignment': False, - 'mp_layer4_hashing': '0', - 'neighbor_cache': 8192, - 'strict_dad': '1' - -} - -def sysctl(name, value): - call('sysctl -wq {}={}'.format(name, value)) - def get_config(config=None): - ip_opt = deepcopy(default_config_data) if config: conf = config else: conf = Config() - conf.set_level('system ipv6') - if conf.exists(''): - ip_opt['disable_addr_assignment'] = conf.exists('disable') - if conf.exists_effective('disable') != conf.exists('disable'): - ip_opt['reboot_message'] = True - - if conf.exists('disable-forwarding'): - ip_opt['ipv6_forward'] = '0' + base = ['system', 'ipv6'] - if conf.exists('multipath layer4-hashing'): - ip_opt['mp_layer4_hashing'] = '1' + opt = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) - if conf.exists('neighbor table-size'): - ip_opt['neighbor_cache'] = int(conf.return_value('neighbor table-size')) + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + default_values = defaults(base) + opt = dict_merge(default_values, opt) - if conf.exists('strict-dad'): - ip_opt['strict_dad'] = 2 + return opt - return ip_opt - -def verify(ip_opt): +def verify(opt): pass -def generate(ip_opt): +def generate(opt): pass -def apply(ip_opt): - # disable IPv6 address assignment - if ip_opt['disable_addr_assignment']: - with open(ipv6_disable_file, 'w') as f: - f.write('options ipv6 disable_ipv6=1') - else: - if os.path.exists(ipv6_disable_file): - os.unlink(ipv6_disable_file) - - if ip_opt['reboot_message']: - print('Changing IPv6 disable parameter will only take affect\n' \ - 'when the system is rebooted.') - +def apply(opt): # configure multipath - sysctl('net.ipv6.fib_multipath_hash_policy', ip_opt['mp_layer4_hashing']) - - # apply neighbor table threshold values - sysctl('net.ipv6.neigh.default.gc_thresh3', ip_opt['neighbor_cache']) - sysctl('net.ipv6.neigh.default.gc_thresh2', ip_opt['neighbor_cache'] // 2) - sysctl('net.ipv6.neigh.default.gc_thresh1', ip_opt['neighbor_cache'] // 8) + tmp = dict_search('multipath.layer4_hashing', opt) + value = '1' if (tmp != None) else '0' + sysctl_write('net.ipv6.fib_multipath_hash_policy', value) + + # Apply ND threshold values + # table_size has a default value - thus the key always exists + size = int(dict_search('neighbor.table_size', opt)) + # Amount upon reaching which the records begin to be cleared immediately + sysctl_write('net.ipv6.neigh.default.gc_thresh3', size) + # Amount after which the records begin to be cleaned after 5 seconds + sysctl_write('net.ipv6.neigh.default.gc_thresh2', size // 2) + # Minimum number of stored records is indicated which is not cleared + sysctl_write('net.ipv6.neigh.default.gc_thresh1', size // 8) # enable/disable IPv6 forwarding - with open('/proc/sys/net/ipv6/conf/all/forwarding', 'w') as f: - f.write(ip_opt['ipv6_forward']) + tmp = dict_search('disable_forwarding', opt) + value = '0' if (tmp != None) else '1' + write_file('/proc/sys/net/ipv6/conf/all/forwarding', value) # configure IPv6 strict-dad + tmp = dict_search('strict_dad', opt) + value = '2' if (tmp != None) else '1' for root, dirs, files in os.walk('/proc/sys/net/ipv6/conf'): for name in files: - if name == "accept_dad": - with open(os.path.join(root, name), 'w') as f: - f.write(str(ip_opt['strict_dad'])) + if name == 'accept_dad': + write_file(os.path.join(root, name), value) if __name__ == '__main__': try: diff --git a/src/conf_mode/system-login-banner.py b/src/conf_mode/system-login-banner.py index 2220d7b66..a521c9834 100755 --- a/src/conf_mode/system-login-banner.py +++ b/src/conf_mode/system-login-banner.py @@ -15,22 +15,20 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from sys import exit +from copy import deepcopy + from vyos.config import Config +from vyos.util import write_file from vyos import ConfigError - from vyos import airbag airbag.enable() -motd=""" -Check out project news at https://blog.vyos.io -and feel free to report bugs at https://phabricator.vyos.net - -You can change this banner using "set system login banner post-login" command. - -VyOS is a free software distribution that includes multiple components, -you can check individual component licenses under /usr/share/doc/*/copyright - -""" +try: + with open('/usr/share/vyos/default_motd') as f: + motd = f.read() +except: + # Use an empty banner if the default banner file cannot be read + motd = "\n" PRELOGIN_FILE = r'/etc/issue' PRELOGIN_NET_FILE = r'/etc/issue.net' @@ -38,12 +36,12 @@ POSTLOGIN_FILE = r'/etc/motd' default_config_data = { 'issue': 'Welcome to VyOS - \\n \\l\n\n', - 'issue_net': 'Welcome to VyOS\n', + 'issue_net': '', 'motd': motd } def get_config(config=None): - banner = default_config_data + banner = deepcopy(default_config_data) if config: conf = config else: @@ -92,14 +90,9 @@ def generate(banner): pass def apply(banner): - with open(PRELOGIN_FILE, 'w') as f: - f.write(banner['issue']) - - with open(PRELOGIN_NET_FILE, 'w') as f: - f.write(banner['issue_net']) - - with open(POSTLOGIN_FILE, 'w') as f: - f.write(banner['motd']) + write_file(PRELOGIN_FILE, banner['issue']) + write_file(PRELOGIN_NET_FILE, banner['issue_net']) + write_file(POSTLOGIN_FILE, banner['motd']) return None diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login.py index 4dd7f936d..c717286ae 100755 --- a/src/conf_mode/system-login.py +++ b/src/conf_mode/system-login.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -23,6 +23,7 @@ from pwd import getpwall from pwd import getpwnam from spwd import getspnam from sys import exit +from time import sleep from vyos.config import Config from vyos.configdict import dict_merge @@ -31,6 +32,7 @@ from vyos.template import render from vyos.template import is_ipv4 from vyos.util import cmd from vyos.util import call +from vyos.util import run from vyos.util import DEVNULL from vyos.util import dict_search from vyos.xml import defaults @@ -195,7 +197,7 @@ def generate(login): pass if 'radius' in login: - render(radius_config_file, 'login/pam_radius_auth.conf.tmpl', login, + render(radius_config_file, 'login/pam_radius_auth.conf.j2', login, permission=0o600, user='root', group='root') else: if os.path.isfile(radius_config_file): @@ -239,7 +241,7 @@ def apply(login): # # XXX: Should we deny using root at all? home_dir = getpwnam(user).pw_dir - render(f'{home_dir}/.ssh/authorized_keys', 'login/authorized_keys.tmpl', + render(f'{home_dir}/.ssh/authorized_keys', 'login/authorized_keys.j2', user_config, permission=0o600, formater=lambda _: _.replace(""", '"'), user=user, group='users') @@ -250,13 +252,22 @@ def apply(login): if 'rm_users' in login: for user in login['rm_users']: try: + # Disable user to prevent re-login + call(f'usermod -s /sbin/nologin {user}') + # Logout user if he is still logged in if user in list(set([tmp[0] for tmp in users()])): print(f'{user} is logged in, forcing logout!') - call(f'pkill -HUP -u {user}') - - # Remove user account but leave home directory to be safe - call(f'userdel --remove {user}', stderr=DEVNULL) + # re-run command until user is logged out + while run(f'pkill -HUP -u {user}'): + sleep(0.250) + + # Remove user account but leave home directory in place. Re-run + # command until user is removed - userdel might return 8 as + # SSH sessions are not all yet properly cleaned away, thus we + # simply re-run the command until the account wen't away + while run(f'userdel --remove {user}', stderr=DEVNULL): + sleep(0.250) except Exception as e: raise ConfigError(f'Deleting user "{user}" raised exception: {e}') diff --git a/src/conf_mode/system-logs.py b/src/conf_mode/system-logs.py new file mode 100755 index 000000000..c71938a79 --- /dev/null +++ b/src/conf_mode/system-logs.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 import ConfigError +from vyos import airbag +from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.logger import syslog +from vyos.template import render +from vyos.util import dict_search +from vyos.xml import defaults +airbag.enable() + +# path to logrotate configs +logrotate_atop_file = '/etc/logrotate.d/vyos-atop' +logrotate_rsyslog_file = '/etc/logrotate.d/vyos-rsyslog' + + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + + base = ['system', 'logs'] + default_values = defaults(base) + logs_config = conf.get_config_dict(base, + key_mangling=('-', '_'), + get_first_key=True) + logs_config = dict_merge(default_values, logs_config) + + return logs_config + + +def verify(logs_config): + # Nothing to verify here + pass + + +def generate(logs_config): + # get configuration for logrotate atop + logrotate_atop = dict_search('logrotate.atop', logs_config) + # generate new config file for atop + syslog.debug('Adding logrotate config for atop') + render(logrotate_atop_file, 'logs/logrotate/vyos-atop.j2', logrotate_atop) + + # get configuration for logrotate rsyslog + logrotate_rsyslog = dict_search('logrotate.messages', logs_config) + # generate new config file for rsyslog + syslog.debug('Adding logrotate config for rsyslog') + render(logrotate_rsyslog_file, 'logs/logrotate/vyos-rsyslog.j2', + logrotate_rsyslog) + + +def apply(logs_config): + # No further actions needed + pass + + +if __name__ == '__main__': + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + exit(1) diff --git a/src/conf_mode/system-option.py b/src/conf_mode/system-option.py index b1c63e316..36dbf155b 100755 --- a/src/conf_mode/system-option.py +++ b/src/conf_mode/system-option.py @@ -74,8 +74,8 @@ def verify(options): return None def generate(options): - render(curlrc_config, 'system/curlrc.tmpl', options) - render(ssh_config, 'system/ssh_config.tmpl', options) + render(curlrc_config, 'system/curlrc.j2', options) + render(ssh_config, 'system/ssh_config.j2', options) return None def apply(options): diff --git a/src/conf_mode/system-proxy.py b/src/conf_mode/system-proxy.py index 02536c2ab..079c43e7e 100755 --- a/src/conf_mode/system-proxy.py +++ b/src/conf_mode/system-proxy.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -13,83 +13,59 @@ # # 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 sys import os -import re -from vyos import ConfigError -from vyos.config import Config +from sys import exit +from vyos.config import Config +from vyos.template import render +from vyos import ConfigError from vyos import airbag airbag.enable() proxy_def = r'/etc/profile.d/vyos-system-proxy.sh' - -def get_config(): - c = Config() - if not c.exists('system proxy'): +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + base = ['system', 'proxy'] + if not conf.exists(base): return None - c.set_level('system proxy') + proxy = conf.get_config_dict(base, get_first_key=True) + return proxy - cnf = { - 'url': None, - 'port': None, - 'usr': None, - 'passwd': None - } +def verify(proxy): + if not proxy: + return - if c.exists('url'): - cnf['url'] = c.return_value('url') - if c.exists('port'): - cnf['port'] = c.return_value('port') - if c.exists('username'): - cnf['usr'] = c.return_value('username') - if c.exists('password'): - cnf['passwd'] = c.return_value('password') + if 'url' not in proxy or 'port' not in proxy: + raise ConfigError('Proxy URL and port require a value') - return cnf + if ('username' in proxy and 'password' not in proxy) or \ + ('username' not in proxy and 'password' in proxy): + raise ConfigError('Both username and password need to be defined!') +def generate(proxy): + if not proxy: + if os.path.isfile(proxy_def): + os.unlink(proxy_def) + return -def verify(c): - if not c: - return None - if not c['url'] or not c['port']: - raise ConfigError("proxy url and port requires a value") - elif c['usr'] and not c['passwd']: - raise ConfigError("proxy password requires a value") - elif not c['usr'] and c['passwd']: - raise ConfigError("proxy username requires a value") - + render(proxy_def, 'system/proxy.j2', proxy, permission=0o755) -def generate(c): - if not c: - return None - if not c['usr']: - return str("export http_proxy={url}:{port}\nexport https_proxy=$http_proxy\nexport ftp_proxy=$http_proxy" - .format(url=c['url'], port=c['port'])) - else: - return str("export http_proxy=http://{usr}:{passwd}@{url}:{port}\nexport https_proxy=$http_proxy\nexport ftp_proxy=$http_proxy" - .format(url=re.sub('http://', '', c['url']), port=c['port'], usr=c['usr'], passwd=c['passwd'])) - - -def apply(ln): - if not ln and os.path.exists(proxy_def): - os.remove(proxy_def) - else: - open(proxy_def, 'w').write( - "# generated by system-proxy.py\n{}\n".format(ln)) +def apply(proxy): + pass if __name__ == '__main__': try: c = get_config() verify(c) - ln = generate(c) - apply(ln) + generate(c) + apply(c) except ConfigError as e: print(e) - sys.exit(1) + exit(1) diff --git a/src/conf_mode/system-syslog.py b/src/conf_mode/system-syslog.py index 3d8a51cd8..a9d3bbe31 100755 --- a/src/conf_mode/system-syslog.py +++ b/src/conf_mode/system-syslog.py @@ -17,6 +17,7 @@ import os import re +from pathlib import Path from sys import exit from vyos.config import Config @@ -89,7 +90,7 @@ def get_config(config=None): filename: { 'log-file': '/var/log/user/' + filename, 'max-files': '5', - 'action-on-max-size': '/usr/sbin/logrotate /etc/logrotate.d/' + filename, + 'action-on-max-size': '/usr/sbin/logrotate /etc/logrotate.d/vyos-rsyslog-generated-' + filename, 'selectors': '*.err', 'max-size': 262144 } @@ -203,12 +204,19 @@ def generate(c): return None conf = '/etc/rsyslog.d/vyos-rsyslog.conf' - render(conf, 'syslog/rsyslog.conf.tmpl', c) + render(conf, 'syslog/rsyslog.conf.j2', c) + + # cleanup current logrotate config files + logrotate_files = Path('/etc/logrotate.d/').glob('vyos-rsyslog-generated-*') + for file in logrotate_files: + file.unlink() # eventually write for each file its own logrotate file, since size is # defined it shouldn't matter - conf = '/etc/logrotate.d/vyos-rsyslog' - render(conf, 'syslog/logrotate.tmpl', c) + for filename, fileconfig in c.get('files', {}).items(): + if fileconfig['log-file'].startswith('/var/log/user/'): + conf = '/etc/logrotate.d/vyos-rsyslog-generated-' + filename + render(conf, 'syslog/logrotate.j2', { 'config_render': fileconfig }) def verify(c): diff --git a/src/conf_mode/system_console.py b/src/conf_mode/system_console.py index 19b252513..86985d765 100755 --- a/src/conf_mode/system_console.py +++ b/src/conf_mode/system_console.py @@ -103,7 +103,7 @@ def generate(console): config_file = base_dir + f'/serial-getty@{device}.service' getty_wants_symlink = base_dir + f'/getty.target.wants/serial-getty@{device}.service' - render(config_file, 'getty/serial-getty.service.tmpl', device_config) + render(config_file, 'getty/serial-getty.service.j2', device_config) os.symlink(config_file, getty_wants_symlink) # GRUB diff --git a/src/conf_mode/system_lcd.py b/src/conf_mode/system_lcd.py index b5ce32beb..3341dd738 100755 --- a/src/conf_mode/system_lcd.py +++ b/src/conf_mode/system_lcd.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright 2020 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2020-2022 VyOS maintainers and contributors <maintainers@vyos.io> # # 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 @@ -61,9 +61,9 @@ def generate(lcd): lcd['device'] = find_device_file(lcd['device']) # Render config file for daemon LCDd - render(lcdd_conf, 'lcd/LCDd.conf.tmpl', lcd) + render(lcdd_conf, 'lcd/LCDd.conf.j2', lcd) # Render config file for client lcdproc - render(lcdproc_conf, 'lcd/lcdproc.conf.tmpl', lcd) + render(lcdproc_conf, 'lcd/lcdproc.conf.j2', lcd) return None diff --git a/src/conf_mode/system_sysctl.py b/src/conf_mode/system_sysctl.py index 4f16d1ed6..2e0004ffa 100755 --- a/src/conf_mode/system_sysctl.py +++ b/src/conf_mode/system_sysctl.py @@ -50,7 +50,7 @@ def generate(sysctl): os.unlink(config_file) return None - render(config_file, 'system/sysctl.conf.tmpl', sysctl) + render(config_file, 'system/sysctl.conf.j2', sysctl) return None def apply(sysctl): diff --git a/src/conf_mode/tftp_server.py b/src/conf_mode/tftp_server.py index 2409eec1f..c5daccb7f 100755 --- a/src/conf_mode/tftp_server.py +++ b/src/conf_mode/tftp_server.py @@ -22,8 +22,10 @@ from copy import deepcopy from glob import glob from sys import exit +from vyos.base import Warning from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configverify import verify_vrf from vyos.template import render from vyos.template import is_ipv4 from vyos.util import call @@ -65,10 +67,11 @@ def verify(tftpd): if 'listen_address' not in tftpd: raise ConfigError('TFTP server listen address must be configured!') - for address in tftpd['listen_address']: + for address, address_config in tftpd['listen_address'].items(): if not is_addr_assigned(address): - print(f'WARNING: TFTP server listen address "{address}" not ' \ - 'assigned to any interface!') + Warning(f'TFTP server listen address "{address}" not ' \ + 'assigned to any interface!') + verify_vrf(address_config) return None @@ -83,7 +86,7 @@ def generate(tftpd): return None idx = 0 - for address in tftpd['listen_address']: + for address, address_config in tftpd['listen_address'].items(): config = deepcopy(tftpd) port = tftpd['port'] if is_ipv4(address): @@ -91,8 +94,11 @@ def generate(tftpd): else: config['listen_address'] = f'[{address}]:{port} -6' + if 'vrf' in address_config: + config['vrf'] = address_config['vrf'] + file = config_file + str(idx) - render(file, 'tftp-server/default.tmpl', config) + render(file, 'tftp-server/default.j2', config) idx = idx + 1 return None diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index 99b82ca2d..bad9cfbd8 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -503,7 +503,7 @@ def generate(ipsec): charon_radius_conf, interface_conf, swanctl_conf]: if os.path.isfile(config_file): os.unlink(config_file) - render(charon_conf, 'ipsec/charon.tmpl', {'install_routes': default_install_routes}) + render(charon_conf, 'ipsec/charon.j2', {'install_routes': default_install_routes}) return if ipsec['dhcp_no_address']: @@ -553,25 +553,27 @@ def generate(ipsec): if not local_prefixes or not remote_prefixes: continue - passthrough = [] + passthrough = None for local_prefix in local_prefixes: for remote_prefix in remote_prefixes: local_net = ipaddress.ip_network(local_prefix) remote_net = ipaddress.ip_network(remote_prefix) if local_net.overlaps(remote_net): + if passthrough is None: + passthrough = [] passthrough.append(local_prefix) ipsec['site_to_site']['peer'][peer]['tunnel'][tunnel]['passthrough'] = passthrough - render(ipsec_conf, 'ipsec/ipsec.conf.tmpl', ipsec) - render(ipsec_secrets, 'ipsec/ipsec.secrets.tmpl', ipsec) - render(charon_conf, 'ipsec/charon.tmpl', ipsec) - render(charon_dhcp_conf, 'ipsec/charon/dhcp.conf.tmpl', ipsec) - render(charon_radius_conf, 'ipsec/charon/eap-radius.conf.tmpl', ipsec) - render(interface_conf, 'ipsec/interfaces_use.conf.tmpl', ipsec) - render(swanctl_conf, 'ipsec/swanctl.conf.tmpl', ipsec) + render(ipsec_conf, 'ipsec/ipsec.conf.j2', ipsec) + render(ipsec_secrets, 'ipsec/ipsec.secrets.j2', ipsec) + render(charon_conf, 'ipsec/charon.j2', ipsec) + render(charon_dhcp_conf, 'ipsec/charon/dhcp.conf.j2', ipsec) + render(charon_radius_conf, 'ipsec/charon/eap-radius.conf.j2', ipsec) + render(interface_conf, 'ipsec/interfaces_use.conf.j2', ipsec) + render(swanctl_conf, 'ipsec/swanctl.conf.j2', ipsec) def resync_nhrp(ipsec): if ipsec and not ipsec['nhrp_exists']: diff --git a/src/conf_mode/vpn_l2tp.py b/src/conf_mode/vpn_l2tp.py index 818e8fa0b..fd5a4acd8 100755 --- a/src/conf_mode/vpn_l2tp.py +++ b/src/conf_mode/vpn_l2tp.py @@ -358,10 +358,10 @@ def generate(l2tp): if not l2tp: return None - render(l2tp_conf, 'accel-ppp/l2tp.config.tmpl', l2tp) + render(l2tp_conf, 'accel-ppp/l2tp.config.j2', l2tp) if l2tp['auth_mode'] == 'local': - render(l2tp_chap_secrets, 'accel-ppp/chap-secrets.tmpl', l2tp) + render(l2tp_chap_secrets, 'accel-ppp/chap-secrets.j2', l2tp) os.chmod(l2tp_chap_secrets, S_IRUSR | S_IWUSR | S_IRGRP) else: diff --git a/src/conf_mode/vpn_openconnect.py b/src/conf_mode/vpn_openconnect.py index f6db196dc..8e0e30bbf 100755 --- a/src/conf_mode/vpn_openconnect.py +++ b/src/conf_mode/vpn_openconnect.py @@ -23,9 +23,12 @@ from vyos.pki import wrap_certificate from vyos.pki import wrap_private_key from vyos.template import render from vyos.util import call +from vyos.util import is_systemd_service_running +from vyos.util import dict_search from vyos.xml import defaults from vyos import ConfigError from crypt import crypt, mksalt, METHOD_SHA512 +from time import sleep from vyos import airbag airbag.enable() @@ -33,6 +36,7 @@ airbag.enable() cfg_dir = '/run/ocserv' ocserv_conf = cfg_dir + '/ocserv.conf' ocserv_passwd = cfg_dir + '/ocpasswd' +ocserv_otp_usr = cfg_dir + '/users.oath' radius_cfg = cfg_dir + '/radiusclient.conf' radius_servers = cfg_dir + '/radius_servers' @@ -52,6 +56,16 @@ def get_config(): default_values = defaults(base) ocserv = dict_merge(default_values, ocserv) + # workaround a "know limitation" - https://phabricator.vyos.net/T2665 + del ocserv['authentication']['local_users']['username']['otp'] + if not ocserv["authentication"]["local_users"]["username"]: + raise ConfigError('openconnect mode local required at least one user') + default_ocserv_usr_values = default_values['authentication']['local_users']['username']['otp'] + for user, params in ocserv['authentication']['local_users']['username'].items(): + # Not every configuration requires OTP settings + if ocserv['authentication']['local_users']['username'][user].get('otp'): + ocserv['authentication']['local_users']['username'][user]['otp'] = dict_merge(default_ocserv_usr_values, ocserv['authentication']['local_users']['username'][user]['otp']) + if ocserv: ocserv['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) @@ -61,17 +75,34 @@ def get_config(): def verify(ocserv): if ocserv is None: return None - # Check authentication if "authentication" in ocserv: if "mode" in ocserv["authentication"]: if "local" in ocserv["authentication"]["mode"]: - if not ocserv["authentication"]["local_users"] or not ocserv["authentication"]["local_users"]["username"]: - raise ConfigError('openconnect mode local required at leat one user') + if "radius" in ocserv["authentication"]["mode"]: + raise ConfigError('OpenConnect authentication modes are mutually-exclusive, remove either local or radius from your configuration') + if not ocserv["authentication"]["local_users"]: + raise ConfigError('openconnect mode local required at least one user') + if not ocserv["authentication"]["local_users"]["username"]: + raise ConfigError('openconnect mode local required at least one user') else: - for user in ocserv["authentication"]["local_users"]["username"]: - if not "password" in ocserv["authentication"]["local_users"]["username"][user]: - raise ConfigError(f'password required for user {user}') + # For OTP mode: verify that each local user has an OTP key + if "otp" in ocserv["authentication"]["mode"]["local"]: + users_wo_key = [] + for user, user_config in ocserv["authentication"]["local_users"]["username"].items(): + # User has no OTP key defined + if dict_search('otp.key', user_config) == None: + users_wo_key.append(user) + if users_wo_key: + raise ConfigError(f'OTP enabled, but no OTP key is configured for these users:\n{users_wo_key}') + # For password (and default) mode: verify that each local user has password + if "password" in ocserv["authentication"]["mode"]["local"] or "otp" not in ocserv["authentication"]["mode"]["local"]: + users_wo_pswd = [] + for user in ocserv["authentication"]["local_users"]["username"]: + if not "password" in ocserv["authentication"]["local_users"]["username"][user]: + users_wo_pswd.append(user) + if users_wo_pswd: + raise ConfigError(f'password required for users:\n{users_wo_pswd}') else: raise ConfigError('openconnect authentication mode required') else: @@ -120,22 +151,57 @@ def verify(ocserv): else: raise ConfigError('openconnect network settings required') - def generate(ocserv): if not ocserv: return None if "radius" in ocserv["authentication"]["mode"]: # Render radius client configuration - render(radius_cfg, 'ocserv/radius_conf.tmpl', ocserv["authentication"]["radius"]) + render(radius_cfg, 'ocserv/radius_conf.j2', ocserv["authentication"]["radius"]) # Render radius servers - render(radius_servers, 'ocserv/radius_servers.tmpl', ocserv["authentication"]["radius"]) + render(radius_servers, 'ocserv/radius_servers.j2', ocserv["authentication"]["radius"]) + elif "local" in ocserv["authentication"]["mode"]: + # if mode "OTP", generate OTP users file parameters + if "otp" in ocserv["authentication"]["mode"]["local"]: + if "local_users" in ocserv["authentication"]: + for user in ocserv["authentication"]["local_users"]["username"]: + # OTP token type from CLI parameters: + otp_interval = str(ocserv["authentication"]["local_users"]["username"][user]["otp"].get("interval")) + token_type = ocserv["authentication"]["local_users"]["username"][user]["otp"].get("token_type") + otp_length = str(ocserv["authentication"]["local_users"]["username"][user]["otp"].get("otp_length")) + if token_type == "hotp-time": + otp_type = "HOTP/T" + otp_interval + elif token_type == "hotp-event": + otp_type = "HOTP/E" + else: + otp_type = "HOTP/T" + otp_interval + ocserv["authentication"]["local_users"]["username"][user]["otp"]["token_tmpl"] = otp_type + "/" + otp_length + # if there is a password, generate hash + if "password" in ocserv["authentication"]["mode"]["local"] or not "otp" in ocserv["authentication"]["mode"]["local"]: + if "local_users" in ocserv["authentication"]: + for user in ocserv["authentication"]["local_users"]["username"]: + ocserv["authentication"]["local_users"]["username"][user]["hash"] = get_hash(ocserv["authentication"]["local_users"]["username"][user]["password"]) + + if "password-otp" in ocserv["authentication"]["mode"]["local"]: + # Render local users ocpasswd + render(ocserv_passwd, 'ocserv/ocserv_passwd.j2', ocserv["authentication"]["local_users"]) + # Render local users OTP keys + render(ocserv_otp_usr, 'ocserv/ocserv_otp_usr.j2', ocserv["authentication"]["local_users"]) + elif "password" in ocserv["authentication"]["mode"]["local"]: + # Render local users ocpasswd + render(ocserv_passwd, 'ocserv/ocserv_passwd.j2', ocserv["authentication"]["local_users"]) + elif "otp" in ocserv["authentication"]["mode"]["local"]: + # Render local users OTP keys + render(ocserv_otp_usr, 'ocserv/ocserv_otp_usr.j2', ocserv["authentication"]["local_users"]) + else: + # Render local users ocpasswd + render(ocserv_passwd, 'ocserv/ocserv_passwd.j2', ocserv["authentication"]["local_users"]) else: if "local_users" in ocserv["authentication"]: for user in ocserv["authentication"]["local_users"]["username"]: ocserv["authentication"]["local_users"]["username"][user]["hash"] = get_hash(ocserv["authentication"]["local_users"]["username"][user]["password"]) # Render local users - render(ocserv_passwd, 'ocserv/ocserv_passwd.tmpl', ocserv["authentication"]["local_users"]) + render(ocserv_passwd, 'ocserv/ocserv_passwd.j2', ocserv["authentication"]["local_users"]) if "ssl" in ocserv: cert_file_path = os.path.join(cfg_dir, 'cert.pem') @@ -161,17 +227,27 @@ def generate(ocserv): f.write(wrap_certificate(pki_ca_cert['certificate'])) # Render config - render(ocserv_conf, 'ocserv/ocserv_config.tmpl', ocserv) + render(ocserv_conf, 'ocserv/ocserv_config.j2', ocserv) def apply(ocserv): if not ocserv: call('systemctl stop ocserv.service') - for file in [ocserv_conf, ocserv_passwd]: + for file in [ocserv_conf, ocserv_passwd, ocserv_otp_usr]: if os.path.exists(file): os.unlink(file) else: call('systemctl restart ocserv.service') + counter = 0 + while True: + # exit early when service runs + if is_systemd_service_running("ocserv.service"): + break + sleep(0.250) + if counter > 5: + raise ConfigError('openconnect failed to start, check the logs for details') + break + counter += 1 if __name__ == '__main__': diff --git a/src/conf_mode/vpn_pptp.py b/src/conf_mode/vpn_pptp.py index 30abe4782..7550c411e 100755 --- a/src/conf_mode/vpn_pptp.py +++ b/src/conf_mode/vpn_pptp.py @@ -264,10 +264,10 @@ def generate(pptp): if not pptp: return None - render(pptp_conf, 'accel-ppp/pptp.config.tmpl', pptp) + render(pptp_conf, 'accel-ppp/pptp.config.j2', pptp) if pptp['local_users']: - render(pptp_chap_secrets, 'accel-ppp/chap-secrets.tmpl', pptp) + render(pptp_chap_secrets, 'accel-ppp/chap-secrets.j2', pptp) os.chmod(pptp_chap_secrets, S_IRUSR | S_IWUSR | S_IRGRP) else: if os.path.exists(pptp_chap_secrets): diff --git a/src/conf_mode/vpn_sstp.py b/src/conf_mode/vpn_sstp.py index 68980e5ab..db53463cf 100755 --- a/src/conf_mode/vpn_sstp.py +++ b/src/conf_mode/vpn_sstp.py @@ -114,7 +114,7 @@ def generate(sstp): return None # accel-cmd reload doesn't work so any change results in a restart of the daemon - render(sstp_conf, 'accel-ppp/sstp.config.tmpl', sstp) + render(sstp_conf, 'accel-ppp/sstp.config.j2', sstp) cert_name = sstp['ssl']['certificate'] pki_cert = sstp['pki']['certificate'][cert_name] @@ -127,7 +127,7 @@ def generate(sstp): write_file(ca_cert_file_path, wrap_certificate(pki_ca['certificate'])) if dict_search('authentication.mode', sstp) == 'local': - render(sstp_chap_secrets, 'accel-ppp/chap-secrets.config_dict.tmpl', + render(sstp_chap_secrets, 'accel-ppp/chap-secrets.config_dict.j2', sstp, permission=0o640) else: if os.path.exists(sstp_chap_secrets): diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index 38c0c4463..972d0289b 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -29,6 +29,7 @@ from vyos.util import dict_search from vyos.util import get_interface_config from vyos.util import popen from vyos.util import run +from vyos.util import sysctl_write from vyos import ConfigError from vyos import frr from vyos import airbag @@ -37,10 +38,16 @@ airbag.enable() config_file = '/etc/iproute2/rt_tables.d/vyos-vrf.conf' nft_vrf_config = '/tmp/nftables-vrf-zones' -def list_rules(): - command = 'ip -j -4 rule show' - answer = loads(cmd(command)) - return [_ for _ in answer if _] +def has_rule(af : str, priority : int, table : str): + """ Check if a given ip rule exists """ + if af not in ['-4', '-6']: + raise ValueError() + command = f'ip -j {af} rule show' + for tmp in loads(cmd(command)): + if {'priority', 'table'} <= set(tmp): + if tmp['priority'] == priority and tmp['table'] == table: + return True + return False def vrf_interfaces(c, match): matched = [] @@ -69,7 +76,6 @@ def vrf_routing(c, match): c.set_level(old_level) return matched - def get_config(config=None): if config: conf = config @@ -77,7 +83,8 @@ def get_config(config=None): conf = Config() base = ['vrf'] - vrf = conf.get_config_dict(base, get_first_key=True) + vrf = conf.get_config_dict(base, key_mangling=('-', '_'), + no_tag_node_value_mangle=True, get_first_key=True) # determine which VRF has been removed for name in node_changed(conf, base + ['name']): @@ -127,10 +134,10 @@ def verify(vrf): def generate(vrf): - render(config_file, 'vrf/vrf.conf.tmpl', vrf) + render(config_file, 'vrf/vrf.conf.j2', vrf) # Render nftables zones config - render(nft_vrf_config, 'firewall/nftables-vrf-zones.tmpl', vrf) + render(nft_vrf_config, 'firewall/nftables-vrf-zones.j2', vrf) return None @@ -146,15 +153,13 @@ def apply(vrf): # set the default VRF global behaviour bind_all = '0' - if 'bind-to-all' in vrf: + if 'bind_to_all' in vrf: bind_all = '1' - call(f'sysctl -wq net.ipv4.tcp_l3mdev_accept={bind_all}') - call(f'sysctl -wq net.ipv4.udp_l3mdev_accept={bind_all}') + sysctl_write('net.ipv4.tcp_l3mdev_accept', bind_all) + sysctl_write('net.ipv4.udp_l3mdev_accept', bind_all) for tmp in (dict_search('vrf_remove', vrf) or []): if os.path.isdir(f'/sys/class/net/{tmp}'): - call(f'ip -4 route del vrf {tmp} unreachable default metric 4278198272') - call(f'ip -6 route del vrf {tmp} unreachable default metric 4278198272') call(f'ip link delete dev {tmp}') # Remove nftables conntrack zone map item nft_del_element = f'delete element inet vrf_zones ct_iface_map {{ "{tmp}" }}' @@ -165,31 +170,68 @@ def apply(vrf): # check if table already exists _, err = popen('nft list table inet vrf_zones') # If not, create a table - if err: - if os.path.exists(nft_vrf_config): - cmd(f'nft -f {nft_vrf_config}') - os.unlink(nft_vrf_config) + if err and os.path.exists(nft_vrf_config): + cmd(f'nft -f {nft_vrf_config}') + os.unlink(nft_vrf_config) + + # Linux routing uses rules to find tables - routing targets are then + # looked up in those tables. If the lookup got a matching route, the + # process ends. + # + # TL;DR; first table with a matching entry wins! + # + # You can see your routing table lookup rules using "ip rule", sadly the + # local lookup is hit before any VRF lookup. Pinging an addresses from the + # VRF will usually find a hit in the local table, and never reach the VRF + # routing table - this is usually not what you want. Thus we will + # re-arrange the tables and move the local lookup further down once VRFs + # are enabled. + # + # Thanks to https://stbuehler.de/blog/article/2020/02/29/using_vrf__virtual_routing_and_forwarding__on_linux.html + + for afi in ['-4', '-6']: + # move lookup local to pref 32765 (from 0) + if not has_rule(afi, 32765, 'local'): + call(f'ip {afi} rule add pref 32765 table local') + if has_rule(afi, 0, 'local'): + call(f'ip {afi} rule del pref 0') + # make sure that in VRFs after failed lookup in the VRF specific table + # nothing else is reached + if not has_rule(afi, 1000, 'l3mdev'): + # this should be added by the kernel when a VRF is created + # add it here for completeness + call(f'ip {afi} rule add pref 1000 l3mdev protocol kernel') + + # add another rule with an unreachable target which only triggers in VRF context + # if a route could not be reached + if not has_rule(afi, 2000, 'l3mdev'): + call(f'ip {afi} rule add pref 2000 l3mdev unreachable') for name, config in vrf['name'].items(): table = config['table'] - if not os.path.isdir(f'/sys/class/net/{name}'): # For each VRF apart from your default context create a VRF # interface with a separate routing table call(f'ip link add {name} type vrf table {table}') - # The kernel Documentation/networking/vrf.txt also recommends - # adding unreachable routes to the VRF routing tables so that routes - # afterwards are taken. - call(f'ip -4 route add vrf {name} unreachable default metric 4278198272') - call(f'ip -6 route add vrf {name} unreachable default metric 4278198272') - # We also should add proper loopback IP addresses to the newly - # created VRFs for services bound to the loopback address (SNMP, NTP) - call(f'ip -4 addr add 127.0.0.1/8 dev {name}') - call(f'ip -6 addr add ::1/128 dev {name}') # set VRF description for e.g. SNMP monitoring vrf_if = Interface(name) + # We also should add proper loopback IP addresses to the newly added + # VRF for services bound to the loopback address (SNMP, NTP) + vrf_if.add_addr('127.0.0.1/8') + vrf_if.add_addr('::1/128') + # add VRF description if available vrf_if.set_alias(config.get('description', '')) + + # Enable/Disable IPv4 forwarding + tmp = dict_search('ip.disable_forwarding', config) + value = '0' if (tmp != None) else '1' + vrf_if.set_ipv4_forwarding(value) + # Enable/Disable IPv6 forwarding + tmp = dict_search('ipv6.disable_forwarding', config) + value = '0' if (tmp != None) else '1' + vrf_if.set_ipv6_forwarding(value) + # Enable/Disable of an interface must always be done at the end of the # derived class to make use of the ref-counting set_admin_state() # function. We will only enable the interface if 'up' was called as @@ -203,37 +245,9 @@ def apply(vrf): nft_add_element = f'add element inet vrf_zones ct_iface_map {{ "{name}" : {table} }}' cmd(f'nft {nft_add_element}') - # Linux routing uses rules to find tables - routing targets are then - # looked up in those tables. If the lookup got a matching route, the - # process ends. - # - # TL;DR; first table with a matching entry wins! - # - # You can see your routing table lookup rules using "ip rule", sadly the - # local lookup is hit before any VRF lookup. Pinging an addresses from the - # VRF will usually find a hit in the local table, and never reach the VRF - # routing table - this is usually not what you want. Thus we will - # re-arrange the tables and move the local lookup furhter down once VRFs - # are enabled. - - # get current preference on local table - local_pref = [r.get('priority') for r in list_rules() if r.get('table') == 'local'][0] - - # change preference when VRFs are enabled and local lookup table is default - if not local_pref and 'name' in vrf: - for af in ['-4', '-6']: - call(f'ip {af} rule add pref 32765 table local') - call(f'ip {af} rule del pref 0') # return to default lookup preference when no VRF is configured if 'name' not in vrf: - for af in ['-4', '-6']: - call(f'ip {af} rule add pref 0 table local') - call(f'ip {af} rule del pref 32765') - - # clean out l3mdev-table rule if present - if 1000 in [r.get('priority') for r in list_rules() if r.get('priority') == 1000]: - call(f'ip {af} rule del pref 1000') # Remove VRF zones table from nftables tmp = run('nft list table inet vrf_zones') if tmp == 0: diff --git a/src/conf_mode/vrf_vni.py b/src/conf_mode/vrf_vni.py index 50d60f0dc..585fdbebf 100755 --- a/src/conf_mode/vrf_vni.py +++ b/src/conf_mode/vrf_vni.py @@ -40,20 +40,18 @@ def verify(vrf): return None def generate(vrf): - vrf['new_frr_config'] = render_to_string('frr/vrf-vni.frr.tmpl', vrf) + vrf['new_frr_config'] = render_to_string('frr/vrf-vni.frr.j2', vrf) return None def apply(vrf): # add configuration to FRR frr_cfg = frr.FRRConfig() frr_cfg.load_configuration(frr_daemon) - frr_cfg.modify_section(f'^vrf .+$', '') - frr_cfg.add_before(r'(interface .*|line vty)', vrf['new_frr_config']) + frr_cfg.modify_section(f'^vrf .+', stop_pattern='^exit-vrf', remove_stop_mark=True) + if 'new_frr_config' in vrf: + frr_cfg.add_before(frr.default_add_before, vrf['new_frr_config']) frr_cfg.commit_configuration(frr_daemon) - # Save configuration to /run/frr/config/frr.conf - frr.save_configuration() - return None if __name__ == '__main__': diff --git a/src/conf_mode/zone_policy.py b/src/conf_mode/zone_policy.py new file mode 100755 index 000000000..070a4deea --- /dev/null +++ b/src/conf_mode/zone_policy.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021-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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from json import loads +from sys import exit + +from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.template import render +from vyos.util import cmd +from vyos.util import dict_search_args +from vyos.util import run +from vyos.xml import defaults +from vyos import ConfigError +from vyos import airbag +airbag.enable() + +nftables_conf = '/run/nftables_zone.conf' + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + base = ['zone-policy'] + zone_policy = conf.get_config_dict(base, key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True) + + zone_policy['firewall'] = conf.get_config_dict(['firewall'], + key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True) + + if 'zone' in zone_policy: + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + default_values = defaults(base + ['zone']) + for zone in zone_policy['zone']: + zone_policy['zone'][zone] = dict_merge(default_values, + zone_policy['zone'][zone]) + + return zone_policy + +def verify(zone_policy): + # bail out early - looks like removal from running config + if not zone_policy: + return None + + local_zone = False + interfaces = [] + + if 'zone' in zone_policy: + for zone, zone_conf in zone_policy['zone'].items(): + if 'local_zone' not in zone_conf and 'interface' not in zone_conf: + raise ConfigError(f'Zone "{zone}" has no interfaces and is not the local zone') + + if 'local_zone' in zone_conf: + if local_zone: + raise ConfigError('There cannot be multiple local zones') + if 'interface' in zone_conf: + raise ConfigError('Local zone cannot have interfaces assigned') + if 'intra_zone_filtering' in zone_conf: + raise ConfigError('Local zone cannot use intra-zone-filtering') + local_zone = True + + if 'interface' in zone_conf: + found_duplicates = [intf for intf in zone_conf['interface'] if intf in interfaces] + + if found_duplicates: + raise ConfigError(f'Interfaces cannot be assigned to multiple zones') + + interfaces += zone_conf['interface'] + + if 'intra_zone_filtering' in zone_conf: + intra_zone = zone_conf['intra_zone_filtering'] + + if len(intra_zone) > 1: + raise ConfigError('Only one intra-zone-filtering action must be specified') + + if 'firewall' in intra_zone: + v4_name = dict_search_args(intra_zone, 'firewall', 'name') + if v4_name and not dict_search_args(zone_policy, 'firewall', 'name', v4_name): + raise ConfigError(f'Firewall name "{v4_name}" does not exist') + + v6_name = dict_search_args(intra_zone, 'firewall', 'ipv6-name') + if v6_name and not dict_search_args(zone_policy, 'firewall', 'ipv6-name', v6_name): + raise ConfigError(f'Firewall ipv6-name "{v6_name}" does not exist') + + if not v4_name and not v6_name: + raise ConfigError('No firewall names specified for intra-zone-filtering') + + if 'from' in zone_conf: + for from_zone, from_conf in zone_conf['from'].items(): + if from_zone not in zone_policy['zone']: + raise ConfigError(f'Zone "{zone}" refers to a non-existent or deleted zone "{from_zone}"') + + v4_name = dict_search_args(from_conf, 'firewall', 'name') + if v4_name: + if 'name' not in zone_policy['firewall']: + raise ConfigError(f'Firewall name "{v4_name}" does not exist') + + if not dict_search_args(zone_policy, 'firewall', 'name', v4_name): + raise ConfigError(f'Firewall name "{v4_name}" does not exist') + + v6_name = dict_search_args(from_conf, 'firewall', 'v6_name') + if v6_name: + if 'ipv6_name' not in zone_policy['firewall']: + raise ConfigError(f'Firewall ipv6-name "{v6_name}" does not exist') + + if not dict_search_args(zone_policy, 'firewall', 'ipv6_name', v6_name): + raise ConfigError(f'Firewall ipv6-name "{v6_name}" does not exist') + + return None + +def has_ipv4_fw(zone_conf): + if 'from' not in zone_conf: + return False + zone_from = zone_conf['from'] + return any([True for fz in zone_from if dict_search_args(zone_from, fz, 'firewall', 'name')]) + +def has_ipv6_fw(zone_conf): + if 'from' not in zone_conf: + return False + zone_from = zone_conf['from'] + return any([True for fz in zone_from if dict_search_args(zone_from, fz, 'firewall', 'ipv6_name')]) + +def get_local_from(zone_policy, local_zone_name): + # Get all zone firewall names from the local zone + out = {} + for zone, zone_conf in zone_policy['zone'].items(): + if zone == local_zone_name: + continue + if 'from' not in zone_conf: + continue + if local_zone_name in zone_conf['from']: + out[zone] = zone_conf['from'][local_zone_name] + return out + +def cleanup_commands(): + commands = [] + for table in ['ip filter', 'ip6 filter']: + json_str = cmd(f'nft -j list table {table}') + obj = loads(json_str) + if 'nftables' not in obj: + continue + for item in obj['nftables']: + if 'rule' in item: + chain = item['rule']['chain'] + handle = item['rule']['handle'] + if 'expr' not in item['rule']: + continue + for expr in item['rule']['expr']: + target = dict_search_args(expr, 'jump', 'target') + if not target: + continue + if target.startswith("VZONE") or target.startswith("VYOS_STATE_POLICY"): + commands.append(f'delete rule {table} {chain} handle {handle}') + for item in obj['nftables']: + if 'chain' in item: + if item['chain']['name'].startswith("VZONE"): + chain = item['chain']['name'] + commands.append(f'delete chain {table} {chain}') + return commands + +def generate(zone_policy): + data = zone_policy or {} + + if os.path.exists(nftables_conf): # Check to see if we've run before + data['cleanup_commands'] = cleanup_commands() + + if 'zone' in data: + for zone, zone_conf in data['zone'].items(): + zone_conf['ipv4'] = has_ipv4_fw(zone_conf) + zone_conf['ipv6'] = has_ipv6_fw(zone_conf) + + if 'local_zone' in zone_conf: + zone_conf['from_local'] = get_local_from(data, zone) + + render(nftables_conf, 'zone_policy/nftables.j2', data) + return None + +def apply(zone_policy): + install_result = run(f'nft -f {nftables_conf}') + if install_result != 0: + raise ConfigError('Failed to apply zone-policy') + + 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/etc/cron.d/check-wwan b/src/etc/cron.d/check-wwan deleted file mode 100644 index 28190776f..000000000 --- a/src/etc/cron.d/check-wwan +++ /dev/null @@ -1 +0,0 @@ -*/5 * * * * root /usr/libexec/vyos/vyos-check-wwan.py diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper b/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper index 74a7e83bf..5d879471d 100644 --- a/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper +++ b/src/etc/dhcp/dhclient-enter-hooks.d/03-vyos-ipwrapper @@ -26,7 +26,7 @@ function iptovtysh () { local VTYSH_GATEWAY="" local VTYSH_DEV="" local VTYSH_TAG="210" - local VTYSH_DISTANCE="" + local VTYSH_DISTANCE=$IF_METRIC # convert default route to 0.0.0.0/0 if [ "$4" == "default" ] ; then VTYSH_NETADDR="0.0.0.0/0" diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/04-vyos-resolvconf b/src/etc/dhcp/dhclient-enter-hooks.d/04-vyos-resolvconf index 24090e2a8..b1902b585 100644 --- a/src/etc/dhcp/dhclient-enter-hooks.d/04-vyos-resolvconf +++ b/src/etc/dhcp/dhclient-enter-hooks.d/04-vyos-resolvconf @@ -1,44 +1,48 @@ -# modified make_resolv_conf () for VyOS -make_resolv_conf() { - hostsd_client="/usr/bin/vyos-hostsd-client" - hostsd_changes= +# modified make_resolv_conf() for VyOS +# should be used only if vyos-hostsd is running - if [ -n "$new_domain_name" ]; then - logmsg info "Deleting search domains with tag \"dhcp-$interface\" via vyos-hostsd-client" - $hostsd_client --delete-search-domains --tag "dhcp-$interface" - logmsg info "Adding domain name \"$new_domain_name\" as search domain with tag \"dhcp-$interface\" via vyos-hostsd-client" - $hostsd_client --add-search-domains "$new_domain_name" --tag "dhcp-$interface" - hostsd_changes=y - fi +if /usr/bin/systemctl -q is-active vyos-hostsd; then + make_resolv_conf() { + hostsd_client="/usr/bin/vyos-hostsd-client" + hostsd_changes= - if [ -n "$new_dhcp6_domain_search" ]; then - logmsg info "Deleting search domains with tag \"dhcpv6-$interface\" via vyos-hostsd-client" - $hostsd_client --delete-search-domains --tag "dhcpv6-$interface" - logmsg info "Adding search domain \"$new_dhcp6_domain_search\" with tag \"dhcpv6-$interface\" via vyos-hostsd-client" - $hostsd_client --add-search-domains "$new_dhcp6_domain_search" --tag "dhcpv6-$interface" - hostsd_changes=y - fi + if [ -n "$new_domain_name" ]; then + logmsg info "Deleting search domains with tag \"dhcp-$interface\" via vyos-hostsd-client" + $hostsd_client --delete-search-domains --tag "dhcp-$interface" + logmsg info "Adding domain name \"$new_domain_name\" as search domain with tag \"dhcp-$interface\" via vyos-hostsd-client" + $hostsd_client --add-search-domains "$new_domain_name" --tag "dhcp-$interface" + hostsd_changes=y + fi - if [ -n "$new_domain_name_servers" ]; then - logmsg info "Deleting nameservers with tag \"dhcp-$interface\" via vyos-hostsd-client" - $hostsd_client --delete-name-servers --tag "dhcp-$interface" - logmsg info "Adding nameservers \"$new_domain_name_servers\" with tag \"dhcp-$interface\" via vyos-hostsd-client" - $hostsd_client --add-name-servers $new_domain_name_servers --tag "dhcp-$interface" - hostsd_changes=y - fi + if [ -n "$new_dhcp6_domain_search" ]; then + logmsg info "Deleting search domains with tag \"dhcpv6-$interface\" via vyos-hostsd-client" + $hostsd_client --delete-search-domains --tag "dhcpv6-$interface" + logmsg info "Adding search domain \"$new_dhcp6_domain_search\" with tag \"dhcpv6-$interface\" via vyos-hostsd-client" + $hostsd_client --add-search-domains "$new_dhcp6_domain_search" --tag "dhcpv6-$interface" + hostsd_changes=y + fi - if [ -n "$new_dhcp6_name_servers" ]; then - logmsg info "Deleting nameservers with tag \"dhcpv6-$interface\" via vyos-hostsd-client" - $hostsd_client --delete-name-servers --tag "dhcpv6-$interface" - logmsg info "Adding nameservers \"$new_dhcpv6_name_servers\" with tag \"dhcpv6-$interface\" via vyos-hostsd-client" - $hostsd_client --add-name-servers $new_dhcpv6_name_servers --tag "dhcpv6-$interface" - hostsd_changes=y - fi + if [ -n "$new_domain_name_servers" ]; then + logmsg info "Deleting nameservers with tag \"dhcp-$interface\" via vyos-hostsd-client" + $hostsd_client --delete-name-servers --tag "dhcp-$interface" + logmsg info "Adding nameservers \"$new_domain_name_servers\" with tag \"dhcp-$interface\" via vyos-hostsd-client" + $hostsd_client --add-name-servers $new_domain_name_servers --tag "dhcp-$interface" + hostsd_changes=y + fi - if [ $hostsd_changes ]; then - logmsg info "Applying changes via vyos-hostsd-client" - $hostsd_client --apply - else - logmsg info "No changes to apply via vyos-hostsd-client" - fi -} + if [ -n "$new_dhcp6_name_servers" ]; then + logmsg info "Deleting nameservers with tag \"dhcpv6-$interface\" via vyos-hostsd-client" + $hostsd_client --delete-name-servers --tag "dhcpv6-$interface" + logmsg info "Adding nameservers \"$new_dhcpv6_name_servers\" with tag \"dhcpv6-$interface\" via vyos-hostsd-client" + $hostsd_client --add-name-servers $new_dhcpv6_name_servers --tag "dhcpv6-$interface" + hostsd_changes=y + fi + + if [ $hostsd_changes ]; then + logmsg info "Applying changes via vyos-hostsd-client" + $hostsd_client --apply + else + logmsg info "No changes to apply via vyos-hostsd-client" + fi + } +fi diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup b/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup index fec792b64..ad6a1d5eb 100644 --- a/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup +++ b/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup @@ -4,14 +4,19 @@ # NOTE: here we use 'ip' wrapper, therefore a route will be actually deleted via /usr/sbin/ip or vtysh, according to the system state hostsd_client="/usr/bin/vyos-hostsd-client" hostsd_changes= +# check vyos-hostsd status +/usr/bin/systemctl -q is-active vyos-hostsd +hostsd_status=$? if [[ $reason =~ (EXPIRE|FAIL|RELEASE|STOP) ]]; then - # delete search domains and nameservers via vyos-hostsd - logmsg info "Deleting search domains with tag \"dhcp-$interface\" via vyos-hostsd-client" - $hostsd_client --delete-search-domains --tag "dhcp-$interface" - logmsg info "Deleting nameservers with tag \"dhcp-${interface}\" via vyos-hostsd-client" - $hostsd_client --delete-name-servers --tag "dhcp-${interface}" - hostsd_changes=y + if [[ $hostsd_status -eq 0 ]]; then + # delete search domains and nameservers via vyos-hostsd + logmsg info "Deleting search domains with tag \"dhcp-$interface\" via vyos-hostsd-client" + $hostsd_client --delete-search-domains --tag "dhcp-$interface" + logmsg info "Deleting nameservers with tag \"dhcp-${interface}\" via vyos-hostsd-client" + $hostsd_client --delete-name-servers --tag "dhcp-${interface}" + hostsd_changes=y + fi if_metric="$IF_METRIC" @@ -92,12 +97,14 @@ if [[ $reason =~ (EXPIRE|FAIL|RELEASE|STOP) ]]; then fi if [[ $reason =~ (EXPIRE6|RELEASE6|STOP6) ]]; then - # delete search domains and nameservers via vyos-hostsd - logmsg info "Deleting search domains with tag \"dhcpv6-$interface\" via vyos-hostsd-client" - $hostsd_client --delete-search-domains --tag "dhcpv6-$interface" - logmsg info "Deleting nameservers with tag \"dhcpv6-${interface}\" via vyos-hostsd-client" - $hostsd_client --delete-name-servers --tag "dhcpv6-${interface}" - hostsd_changes=y + if [[ $hostsd_status -eq 0 ]]; then + # delete search domains and nameservers via vyos-hostsd + logmsg info "Deleting search domains with tag \"dhcpv6-$interface\" via vyos-hostsd-client" + $hostsd_client --delete-search-domains --tag "dhcpv6-$interface" + logmsg info "Deleting nameservers with tag \"dhcpv6-${interface}\" via vyos-hostsd-client" + $hostsd_client --delete-name-servers --tag "dhcpv6-${interface}" + hostsd_changes=y + fi fi if [ $hostsd_changes ]; then diff --git a/src/etc/logrotate.d/conntrackd b/src/etc/logrotate.d/conntrackd new file mode 100644 index 000000000..b0b09dec1 --- /dev/null +++ b/src/etc/logrotate.d/conntrackd @@ -0,0 +1,9 @@ +/var/log/conntrackd-stats.log { + weekly + rotate 2 + missingok + + postrotate + systemctl restart conntrackd.service > /dev/null + endscript +} diff --git a/src/etc/logrotate.d/vyos-rsyslog b/src/etc/logrotate.d/vyos-rsyslog new file mode 100644 index 000000000..3c087b94e --- /dev/null +++ b/src/etc/logrotate.d/vyos-rsyslog @@ -0,0 +1,12 @@ +/var/log/messages { + create + missingok + nomail + notifempty + rotate 10 + size 1M + postrotate + # inform rsyslog service about rotation + /usr/lib/rsyslog/rsyslog-rotate + endscript +} diff --git a/src/etc/ppp/ip-up.d/99-vyos-pppoe-callback b/src/etc/ppp/ip-up.d/99-vyos-pppoe-callback index bb918a468..fa1917ab1 100755 --- a/src/etc/ppp/ip-up.d/99-vyos-pppoe-callback +++ b/src/etc/ppp/ip-up.d/99-vyos-pppoe-callback @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -23,14 +23,9 @@ from sys import argv from sys import exit -from syslog import syslog -from syslog import openlog -from syslog import LOG_PID -from syslog import LOG_INFO - from vyos.configquery import ConfigTreeQuery +from vyos.configdict import get_interface_dict from vyos.ifconfig import PPPoEIf -from vyos.util import read_file # When the ppp link comes up, this script is called with the following # parameters @@ -45,15 +40,10 @@ if (len(argv) < 7): exit(1) interface = argv[6] -dialer_pid = read_file(f'/var/run/{interface}.pid') - -openlog(ident=f'pppd[{dialer_pid}]', facility=LOG_INFO) -syslog('executing ' + argv[0]) conf = ConfigTreeQuery() -pppoe = conf.get_config_dict(['interfaces', 'pppoe', argv[6]], - get_first_key=True, key_mangling=('-', '_')) -pppoe['ifname'] = argv[6] +_, pppoe = get_interface_dict(conf.config, ['interfaces', 'pppoe'], interface) -p = PPPoEIf(pppoe['ifname']) +# Update the config +p = PPPoEIf(interface) p.update(pppoe) diff --git a/src/etc/systemd/system/keepalived.service.d/override.conf b/src/etc/systemd/system/keepalived.service.d/override.conf deleted file mode 100644 index 1c68913f2..000000000 --- a/src/etc/systemd/system/keepalived.service.d/override.conf +++ /dev/null @@ -1,13 +0,0 @@ -[Unit] -ConditionPathExists= -ConditionPathExists=/run/keepalived/keepalived.conf -After= -After=vyos-router.service - -[Service] -KillMode=process -EnvironmentFile= -ExecStart= -ExecStart=/usr/sbin/keepalived --use-file /run/keepalived/keepalived.conf --pid /run/keepalived/keepalived.pid --dont-fork --snmp -PIDFile= -PIDFile=/run/keepalived/keepalived.pid diff --git a/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py b/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py new file mode 100755 index 000000000..bf4bfd05d --- /dev/null +++ b/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +import json +import re +import time + +from vyos.util import cmd + + +def get_nft_filter_chains(): + """ + Get list of nft chains for table filter + """ + nft = cmd('/usr/sbin/nft --json list table ip filter') + nft = json.loads(nft) + chain_list = [] + + for output in nft['nftables']: + if 'chain' in output: + chain = output['chain']['name'] + chain_list.append(chain) + + return chain_list + + +def get_nftables_details(name): + """ + Get dict, counters packets and bytes for chain + """ + command = f'/usr/sbin/nft list chain ip filter {name}' + try: + results = cmd(command) + except: + return {} + + # Trick to remove 'NAME_' from chain name in the comment + # It was added to any chain T4218 + # counter packets 0 bytes 0 return comment "FOO default-action accept" + comment_name = name.replace("NAME_", "") + out = {} + for line in results.split('\n'): + comment_search = re.search(rf'{comment_name}[\- ](\d+|default-action)', line) + if not comment_search: + continue + + rule = {} + rule_id = comment_search[1] + counter_search = re.search(r'counter packets (\d+) bytes (\d+)', line) + if counter_search: + rule['packets'] = counter_search[1] + rule['bytes'] = counter_search[2] + + rule['conditions'] = re.sub(r'(\b(counter packets \d+ bytes \d+|drop|reject|return|log)\b|comment "[\w\-]+")', '', line).strip() + out[rule_id] = rule + return out + + +def get_nft_telegraf(name): + """ + Get data for telegraf in influxDB format + """ + for rule, rule_config in get_nftables_details(name).items(): + print(f'nftables,table=filter,chain={name},' + f'ruleid={rule} ' + f'pkts={rule_config["packets"]}i,' + f'bytes={rule_config["bytes"]}i ' + f'{str(int(time.time()))}000000000') + + +chains = get_nft_filter_chains() + +for chain in chains: + get_nft_telegraf(chain) diff --git a/src/etc/telegraf/custom_scripts/show_interfaces_input_filter.py b/src/etc/telegraf/custom_scripts/show_interfaces_input_filter.py new file mode 100755 index 000000000..0c7474156 --- /dev/null +++ b/src/etc/telegraf/custom_scripts/show_interfaces_input_filter.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 + +from vyos.ifconfig import Section +from vyos.ifconfig import Interface + +import time + +def get_interfaces(type='', vlan=True): + """ + Get interfaces: + ['dum0', 'eth0', 'eth1', 'eth1.5', 'lo', 'tun0'] + """ + interfaces = [] + ifaces = Section.interfaces(type) + for iface in ifaces: + if vlan == False and '.' in iface: + continue + interfaces.append(iface) + + return interfaces + +def get_interface_addresses(iface, link_local_v6=False): + """ + Get IP and IPv6 addresses from interface in one string + By default don't get IPv6 link-local addresses + If interface doesn't have address, return "-" + """ + addresses = [] + addrs = Interface(iface).get_addr() + + for addr in addrs: + if link_local_v6 == False: + if addr.startswith('fe80::'): + continue + addresses.append(addr) + + if not addresses: + return "-" + + return (" ".join(addresses)) + +def get_interface_description(iface): + """ + Get interface description + If none return "empty" + """ + description = Interface(iface).get_alias() + + if not description: + return "empty" + + return description + +def get_interface_admin_state(iface): + """ + Interface administrative state + up => 0, down => 2 + """ + state = Interface(iface).get_admin_state() + if state == 'up': + admin_state = 0 + if state == 'down': + admin_state = 2 + + return admin_state + +def get_interface_oper_state(iface): + """ + Interface operational state + up => 0, down => 1 + """ + state = Interface(iface).operational.get_state() + if state == 'down': + oper_state = 1 + else: + oper_state = 0 + + return oper_state + +interfaces = get_interfaces() + +for iface in interfaces: + print(f'show_interfaces,interface={iface} ' + f'ip_addresses="{get_interface_addresses(iface)}",' + f'state={get_interface_admin_state(iface)}i,' + f'link={get_interface_oper_state(iface)}i,' + f'description="{get_interface_description(iface)}" ' + f'{str(int(time.time()))}000000000') diff --git a/src/etc/telegraf/custom_scripts/vyos_services_input_filter.py b/src/etc/telegraf/custom_scripts/vyos_services_input_filter.py new file mode 100755 index 000000000..df4eed131 --- /dev/null +++ b/src/etc/telegraf/custom_scripts/vyos_services_input_filter.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 time +from vyos.configquery import ConfigTreeQuery +from vyos.util import is_systemd_service_running, process_named_running + +# Availible services and prouceses +# 1 - service +# 2 - process +services = { + "protocols bgp" : "bgpd", + "protocols ospf" : "ospfd", + "protocols ospfv3" : "ospf6d", + "protocols rip" : "ripd", + "protocols ripng" : "ripngd", + "protocols isis" : "isisd", + "service pppoe" : "accel-ppp@pppoe.service", + "vpn l2tp remote-access" : "accel-ppp@l2tp.service", + "vpn pptp remote-access" : "accel-ppp@pptp.service", + "vpn sstp" : "accel-ppp@sstp.service", + "vpn ipsec" : "charon" +} + +# Configured services +conf_services = { + 'zebra' : 0, + 'staticd' : 0, +} +# Get configured service and create list to check if process running +config = ConfigTreeQuery() +for service in services: + if config.exists(service): + conf_services[services[service]] = 0 + +for conf_service in conf_services: + status = 0 + if ".service" in conf_service: + # Check systemd service + if is_systemd_service_running(conf_service): + status = 1 + else: + # Check process + if process_named_running(conf_service): + status = 1 + print(f'vyos_services,service="{conf_service}" ' + f'status={str(status)}i {str(int(time.time()))}000000000') diff --git a/src/helpers/strip-private.py b/src/helpers/strip-private.py index e4e1fe11d..eb584edaf 100755 --- a/src/helpers/strip-private.py +++ b/src/helpers/strip-private.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -# Copyright 2021 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2021-2022 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 @@ -111,6 +111,10 @@ if __name__ == "__main__": (True, re.compile(r'public-keys \S+'), 'public-keys xxxx@xxx.xxx'), (True, re.compile(r'type \'ssh-(rsa|dss)\''), 'type ssh-xxx'), (True, re.compile(r' key \S+'), ' key xxxxxx'), + # Strip bucket + (True, re.compile(r' bucket \S+'), ' bucket xxxxxx'), + # Strip tokens + (True, re.compile(r' token \S+'), ' token xxxxxx'), # Strip OpenVPN secrets (True, re.compile(r'(shared-secret-key-file|ca-cert-file|cert-file|dh-file|key-file|client) (\S+)'), r'\1 xxxxxx'), # Strip IPSEC secrets @@ -123,8 +127,8 @@ if __name__ == "__main__": # Strip MAC addresses (args.mac, re.compile(r'([0-9a-fA-F]{2}\:){5}([0-9a-fA-F]{2}((\:{0,1})){3})'), r'xx:xx:xx:xx:xx:\2'), - # Strip host-name, domain-name, and domain-search - (args.hostname, re.compile(r'(host-name|domain-name|domain-search) \S+'), r'\1 xxxxxx'), + # Strip host-name, domain-name, domain-search and url + (args.hostname, re.compile(r'(host-name|domain-name|domain-search|url) \S+'), r'\1 xxxxxx'), # Strip user-names (args.username, re.compile(r'(user|username|user-id) \S+'), r'\1 xxxxxx'), diff --git a/src/helpers/system-versions-foot.py b/src/helpers/system-versions-foot.py index c33e41d79..2aa687221 100755 --- a/src/helpers/system-versions-foot.py +++ b/src/helpers/system-versions-foot.py @@ -21,7 +21,7 @@ import vyos.systemversions as systemversions import vyos.defaults import vyos.version -sys_versions = systemversions.get_system_versions() +sys_versions = systemversions.get_system_component_version() component_string = formatversions.format_versions_string(sys_versions) diff --git a/src/helpers/vyos-boot-config-loader.py b/src/helpers/vyos-boot-config-loader.py index c5bf22f10..b9cc87bfa 100755 --- a/src/helpers/vyos-boot-config-loader.py +++ b/src/helpers/vyos-boot-config-loader.py @@ -23,12 +23,12 @@ import grp import traceback from datetime import datetime -from vyos.defaults import directories +from vyos.defaults import directories, config_status from vyos.configsession import ConfigSession, ConfigSessionError from vyos.configtree import ConfigTree from vyos.util import cmd -STATUS_FILE = '/tmp/vyos-config-status' +STATUS_FILE = config_status TRACE_FILE = '/tmp/boot-config-trace' CFG_GROUP = 'vyattacfg' diff --git a/src/helpers/vyos-check-wwan.py b/src/helpers/vyos-check-wwan.py index c6e6c54b7..2ff9a574f 100755 --- a/src/helpers/vyos-check-wwan.py +++ b/src/helpers/vyos-check-wwan.py @@ -18,7 +18,6 @@ from vyos.configquery import VbashOpRun from vyos.configquery import ConfigTreeQuery from vyos.util import is_wwan_connected -from vyos.util import call conf = ConfigTreeQuery() dict = conf.get_config_dict(['interfaces', 'wwan'], key_mangling=('-', '_'), @@ -30,8 +29,7 @@ for interface, interface_config in dict.items(): # do not restart this interface as it's disabled by the user continue - #op = VbashOpRun() - #op.run(['connect', 'interface', interface]) - call(f'VYOS_TAGNODE_VALUE={interface} /usr/libexec/vyos/conf_mode/interfaces-wwan.py') + op = VbashOpRun() + op.run(['connect', 'interface', interface]) exit(0) diff --git a/src/helpers/vyos-vrrp-conntracksync.sh b/src/helpers/vyos-vrrp-conntracksync.sh index 4501aa63e..0cc718938 100755 --- a/src/helpers/vyos-vrrp-conntracksync.sh +++ b/src/helpers/vyos-vrrp-conntracksync.sh @@ -14,12 +14,10 @@ # Modified by : Mohit Mehta <mohit@vyatta.com> # Slight modifications were made to this script for running with Vyatta # The original script came from 0.9.14 debian conntrack-tools package -# -# CONNTRACKD_BIN=/usr/sbin/conntrackd CONNTRACKD_LOCK=/var/lock/conntrack.lock -CONNTRACKD_CONFIG=/etc/conntrackd/conntrackd.conf +CONNTRACKD_CONFIG=/run/conntrackd/conntrackd.conf FACILITY=daemon LEVEL=notice TAG=conntrack-tools @@ -29,6 +27,10 @@ FAILOVER_STATE="/var/run/vyatta-conntrackd-failover-state" $LOGCMD "vyatta-vrrp-conntracksync invoked at `date`" +if ! systemctl is-active --quiet conntrackd.service; then + echo "conntrackd service not running" + exit 1 +fi if [ ! -e $FAILOVER_STATE ]; then mkdir -p /var/run diff --git a/src/helpers/vyos_net_name b/src/helpers/vyos_net_name index e21d8c9ff..1798e92db 100755 --- a/src/helpers/vyos_net_name +++ b/src/helpers/vyos_net_name @@ -20,19 +20,20 @@ import os import re import time import logging +import tempfile import threading from sys import argv from vyos.configtree import ConfigTree from vyos.defaults import directories -from vyos.util import cmd +from vyos.util import cmd, boot_configuration_complete +from vyos.migrator import VirtualMigrator vyos_udev_dir = directories['vyos_udev_dir'] vyos_log_dir = '/run/udev/log' vyos_log_file = os.path.join(vyos_log_dir, 'vyos-net-name') config_path = '/opt/vyatta/etc/config/config.boot' -config_status = '/tmp/vyos-config-status' lock = threading.Lock() @@ -43,13 +44,6 @@ except FileExistsError: logging.basicConfig(filename=vyos_log_file, level=logging.DEBUG) -def boot_configuration_complete() -> bool: - """ Check if vyos-router has completed, hence hotplug event - """ - if os.path.isfile(config_status): - return True - return False - def is_available(intfs: dict, intf_name: str) -> bool: """ Check if interface name is already assigned """ @@ -147,14 +141,20 @@ def get_configfile_interfaces() -> dict: try: config = ConfigTree(config_file) except Exception: - logging.debug(f"updating component version string syntax") try: - # this will update the component version string in place, for - # updates 1.2 --> 1.3/1.4 - os.system(f'/usr/libexec/vyos/run-config-migration.py {config_path} --virtual --set-vintage=vyos') - with open(config_path) as f: - config_file = f.read() + logging.debug(f"updating component version string syntax") + # this will update the component version string syntax, + # required for updates 1.2 --> 1.3/1.4 + with tempfile.NamedTemporaryFile() as fp: + with open(fp.name, 'w') as fd: + fd.write(config_file) + virtual_migration = VirtualMigrator(fp.name) + virtual_migration.run() + with open(fp.name) as fd: + config_file = fd.read() + config = ConfigTree(config_file) + except Exception as e: logging.critical(f"ConfigTree error: {e}") @@ -254,4 +254,3 @@ if not boot_configuration_complete(): else: logging.debug("boot configuration complete") lock.release() - diff --git a/src/migration-scripts/bgp/0-to-1 b/src/migration-scripts/bgp/0-to-1 index b1d5a6514..5e9dffe1f 100755 --- a/src/migration-scripts/bgp/0-to-1 +++ b/src/migration-scripts/bgp/0-to-1 @@ -33,7 +33,7 @@ with open(file_name, 'r') as f: base = ['protocols', 'bgp'] config = ConfigTree(config_file) -if not config.exists(base): +if not config.exists(base) or not config.is_tag(base): # Nothing to do exit(0) diff --git a/src/migration-scripts/bgp/1-to-2 b/src/migration-scripts/bgp/1-to-2 index 4c6d5ceb8..e2d3fcd33 100755 --- a/src/migration-scripts/bgp/1-to-2 +++ b/src/migration-scripts/bgp/1-to-2 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 @@ -20,7 +20,6 @@ from sys import argv from sys import exit from vyos.configtree import ConfigTree -from vyos.template import is_ipv4 if (len(argv) < 1): print("Must specify file name!") @@ -51,23 +50,21 @@ if config.exists(base + ['parameters', 'default', 'no-ipv4-unicast']): # Check if the "default" node is now empty, if so - remove it if len(config.list_nodes(base + ['parameters'])) == 0: config.delete(base + ['parameters']) +else: + # As we now install a new default option into BGP we need to migrate all + # existing BGP neighbors and restore the old behavior + if config.exists(base + ['neighbor']): + for neighbor in config.list_nodes(base + ['neighbor']): + peer_group = base + ['neighbor', neighbor, 'peer-group'] + if config.exists(peer_group): + peer_group_name = config.return_value(peer_group) + # peer group enables old behavior for neighbor - bail out + if config.exists(base + ['peer-group', peer_group_name, 'address-family', 'ipv4-unicast']): + continue - exit(0) - -# As we now install a new default option into BGP we need to migrate all -# existing BGP neighbors and restore the old behavior -if config.exists(base + ['neighbor']): - for neighbor in config.list_nodes(base + ['neighbor']): - peer_group = base + ['neighbor', neighbor, 'peer-group'] - if config.exists(peer_group): - peer_group_name = config.return_value(peer_group) - # peer group enables old behavior for neighbor - bail out - if config.exists(base + ['peer-group', peer_group_name, 'address-family', 'ipv4-unicast']): - continue - - afi_ipv4 = base + ['neighbor', neighbor, 'address-family', 'ipv4-unicast'] - if not config.exists(afi_ipv4): - config.set(afi_ipv4) + afi_ipv4 = base + ['neighbor', neighbor, 'address-family', 'ipv4-unicast'] + if not config.exists(afi_ipv4): + config.set(afi_ipv4) try: with open(file_name, 'w') as f: diff --git a/src/migration-scripts/dns-forwarding/1-to-2 b/src/migration-scripts/dns-forwarding/1-to-2 index ba10c26f2..a8c930be7 100755 --- a/src/migration-scripts/dns-forwarding/1-to-2 +++ b/src/migration-scripts/dns-forwarding/1-to-2 @@ -16,7 +16,7 @@ # # This migration script will remove the deprecated 'listen-on' statement -# from the dns forwarding service and will add the corresponding +# from the dns forwarding service and will add the corresponding # listen-address nodes instead. This is required as PowerDNS can only listen # on interface addresses and not on interface names. @@ -37,53 +37,50 @@ with open(file_name, 'r') as f: config = ConfigTree(config_file) base = ['service', 'dns', 'forwarding'] -if not config.exists(base): +if not config.exists(base + ['listen-on']): # Nothing to do exit(0) -if config.exists(base + ['listen-on']): - listen_intf = config.return_values(base + ['listen-on']) - # Delete node with abandoned command - config.delete(base + ['listen-on']) +listen_intf = config.return_values(base + ['listen-on']) +# Delete node with abandoned command +config.delete(base + ['listen-on']) - # retrieve interface addresses for every configured listen-on interface - listen_addr = [] - for intf in listen_intf: - # we need to evaluate the interface section before manipulating the 'intf' variable - section = Interface.section(intf) - if not section: - raise ValueError(f'Invalid interface name {intf}') +# retrieve interface addresses for every configured listen-on interface +listen_addr = [] +for intf in listen_intf: + # we need to evaluate the interface section before manipulating the 'intf' variable + section = Interface.section(intf) + if not section: + raise ValueError(f'Invalid interface name {intf}') - # we need to treat vif and vif-s interfaces differently, - # both "real interfaces" use dots for vlan identifiers - those - # need to be exchanged with vif and vif-s identifiers - if intf.count('.') == 1: - # this is a regular VLAN interface - intf = intf.split('.')[0] + ' vif ' + intf.split('.')[1] - elif intf.count('.') == 2: - # this is a QinQ VLAN interface - intf = intf.split('.')[0] + ' vif-s ' + intf.split('.')[1] + ' vif-c ' + intf.split('.')[2] - - # retrieve corresponding interface addresses in CIDR format - # those need to be converted in pure IP addresses without network information - path = ['interfaces', section, intf, 'address'] - try: - for addr in config.return_values(path): - listen_addr.append( ip_interface(addr).ip ) - except: - # Some interface types do not use "address" option (e.g. OpenVPN) - # and may not even have a fixed address - print("Could not retrieve the address of the interface {} from the config".format(intf)) - print("You will need to update your DNS forwarding configuration manually") - - for addr in listen_addr: - config.set(base + ['listen-address'], value=addr, replace=False) + # we need to treat vif and vif-s interfaces differently, + # both "real interfaces" use dots for vlan identifiers - those + # need to be exchanged with vif and vif-s identifiers + if intf.count('.') == 1: + # this is a regular VLAN interface + intf = intf.split('.')[0] + ' vif ' + intf.split('.')[1] + elif intf.count('.') == 2: + # this is a QinQ VLAN interface + intf = intf.split('.')[0] + ' vif-s ' + intf.split('.')[1] + ' vif-c ' + intf.split('.')[2] + # retrieve corresponding interface addresses in CIDR format + # those need to be converted in pure IP addresses without network information + path = ['interfaces', section, intf, 'address'] 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)) - exit(1) + for addr in config.return_values(path): + listen_addr.append( ip_interface(addr).ip ) + except: + # Some interface types do not use "address" option (e.g. OpenVPN) + # and may not even have a fixed address + print("Could not retrieve the address of the interface {} from the config".format(intf)) + print("You will need to update your DNS forwarding configuration manually") -exit(0) +for addr in listen_addr: + config.set(base + ['listen-address'], value=addr, replace=False) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/firewall/6-to-7 b/src/migration-scripts/firewall/6-to-7 new file mode 100755 index 000000000..5f4cff90d --- /dev/null +++ b/src/migration-scripts/firewall/6-to-7 @@ -0,0 +1,226 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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/>. + +# T2199: Remove unavailable nodes due to XML/Python implementation using nftables +# monthdays: nftables does not have a monthdays equivalent +# utc: nftables userspace uses localtime and calculates the UTC offset automatically +# icmp/v6: migrate previously available `type-name` to valid type/code +# T4178: Update tcp flags to use multi value node + +import re + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree +from vyos.ifconfig import Section + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['firewall'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) + +icmp_remove = ['any'] +icmp_translations = { + 'ping': 'echo-request', + 'pong': 'echo-reply', + 'ttl-exceeded': 'time-exceeded', + # Network Unreachable + 'network-unreachable': [3, 0], + 'host-unreachable': [3, 1], + 'protocol-unreachable': [3, 2], + 'port-unreachable': [3, 3], + 'fragmentation-needed': [3, 4], + 'source-route-failed': [3, 5], + 'network-unknown': [3, 6], + 'host-unknown': [3, 7], + 'network-prohibited': [3, 9], + 'host-prohibited': [3, 10], + 'TOS-network-unreachable': [3, 11], + 'TOS-host-unreachable': [3, 12], + 'communication-prohibited': [3, 13], + 'host-precedence-violation': [3, 14], + 'precedence-cutoff': [3, 15], + # Redirect + 'network-redirect': [5, 0], + 'host-redirect': [5, 1], + 'TOS-network-redirect': [5, 2], + 'TOS host-redirect': [5, 3], + # Time Exceeded + 'ttl-zero-during-transit': [11, 0], + 'ttl-zero-during-reassembly': [11, 1], + # Parameter Problem + 'ip-header-bad': [12, 0], + 'required-option-missing': [12, 1] +} + +icmpv6_remove = [] +icmpv6_translations = { + 'ping': 'echo-request', + 'pong': 'echo-reply', + # Destination Unreachable + 'no-route': [1, 0], + 'communication-prohibited': [1, 1], + 'address-unreachble': [1, 3], + 'port-unreachable': [1, 4], + # Redirect + 'redirect': 'nd-redirect', + # Time Exceeded + 'ttl-zero-during-transit': [3, 0], + 'ttl-zero-during-reassembly': [3, 1], + # Parameter Problem + 'bad-header': [4, 0], + 'unknown-header-type': [4, 1], + 'unknown-option': [4, 2] +} + +if config.exists(base + ['name']): + for name in config.list_nodes(base + ['name']): + if not config.exists(base + ['name', name, 'rule']): + continue + + for rule in config.list_nodes(base + ['name', name, 'rule']): + rule_recent = base + ['name', name, 'rule', rule, 'recent'] + rule_time = base + ['name', name, 'rule', rule, 'time'] + rule_tcp_flags = base + ['name', name, 'rule', rule, 'tcp', 'flags'] + rule_icmp = base + ['name', name, 'rule', rule, 'icmp'] + + if config.exists(rule_time + ['monthdays']): + config.delete(rule_time + ['monthdays']) + + if config.exists(rule_time + ['utc']): + config.delete(rule_time + ['utc']) + + if config.exists(rule_recent + ['time']): + tmp = int(config.return_value(rule_recent + ['time'])) + unit = 'minute' + if tmp > 600: + unit = 'hour' + elif tmp < 10: + unit = 'second' + config.set(rule_recent + ['time'], value=unit) + + if config.exists(rule_tcp_flags): + tmp = config.return_value(rule_tcp_flags) + config.delete(rule_tcp_flags) + for flag in tmp.split(","): + if flag[0] == '!': + config.set(rule_tcp_flags + ['not', flag[1:].lower()]) + else: + config.set(rule_tcp_flags + [flag.lower()]) + + if config.exists(rule_icmp + ['type-name']): + tmp = config.return_value(rule_icmp + ['type-name']) + if tmp in icmp_remove: + config.delete(rule_icmp + ['type-name']) + elif tmp in icmp_translations: + translate = icmp_translations[tmp] + if isinstance(translate, str): + config.set(rule_icmp + ['type-name'], value=translate) + elif isinstance(translate, list): + config.delete(rule_icmp + ['type-name']) + config.set(rule_icmp + ['type'], value=translate[0]) + config.set(rule_icmp + ['code'], value=translate[1]) + + for src_dst in ['destination', 'source']: + pg_base = base + ['name', name, 'rule', rule, src_dst, 'group', 'port-group'] + proto_base = base + ['name', name, 'rule', rule, 'protocol'] + if config.exists(pg_base) and not config.exists(proto_base): + config.set(proto_base, value='tcp_udp') + +if config.exists(base + ['ipv6-name']): + for name in config.list_nodes(base + ['ipv6-name']): + if not config.exists(base + ['ipv6-name', name, 'rule']): + continue + + for rule in config.list_nodes(base + ['ipv6-name', name, 'rule']): + rule_recent = base + ['ipv6-name', name, 'rule', rule, 'recent'] + rule_time = base + ['ipv6-name', name, 'rule', rule, 'time'] + rule_tcp_flags = base + ['ipv6-name', name, 'rule', rule, 'tcp', 'flags'] + rule_icmp = base + ['ipv6-name', name, 'rule', rule, 'icmpv6'] + + if config.exists(rule_time + ['monthdays']): + config.delete(rule_time + ['monthdays']) + + if config.exists(rule_time + ['utc']): + config.delete(rule_time + ['utc']) + + if config.exists(rule_recent + ['time']): + tmp = int(config.return_value(rule_recent + ['time'])) + unit = 'minute' + if tmp > 600: + unit = 'hour' + elif tmp < 10: + unit = 'second' + config.set(rule_recent + ['time'], value=unit) + + if config.exists(rule_tcp_flags): + tmp = config.return_value(rule_tcp_flags) + config.delete(rule_tcp_flags) + for flag in tmp.split(","): + if flag[0] == '!': + config.set(rule_tcp_flags + ['not', flag[1:].lower()]) + else: + config.set(rule_tcp_flags + [flag.lower()]) + + if config.exists(base + ['ipv6-name', name, 'rule', rule, 'protocol']): + tmp = config.return_value(base + ['ipv6-name', name, 'rule', rule, 'protocol']) + if tmp == 'icmpv6': + config.set(base + ['ipv6-name', name, 'rule', rule, 'protocol'], value='ipv6-icmp') + + if config.exists(rule_icmp + ['type']): + tmp = config.return_value(rule_icmp + ['type']) + type_code_match = re.match(r'^(\d+)/(\d+)$', tmp) + + if type_code_match: + config.set(rule_icmp + ['type'], value=type_code_match[1]) + config.set(rule_icmp + ['code'], value=type_code_match[2]) + elif tmp in icmpv6_remove: + config.delete(rule_icmp + ['type']) + elif tmp in icmpv6_translations: + translate = icmpv6_translations[tmp] + if isinstance(translate, str): + config.delete(rule_icmp + ['type']) + config.set(rule_icmp + ['type-name'], value=translate) + elif isinstance(translate, list): + config.set(rule_icmp + ['type'], value=translate[0]) + config.set(rule_icmp + ['code'], value=translate[1]) + else: + config.rename(rule_icmp + ['type'], 'type-name') + + for src_dst in ['destination', 'source']: + pg_base = base + ['ipv6-name', name, 'rule', rule, src_dst, 'group', 'port-group'] + proto_base = base + ['ipv6-name', name, 'rule', rule, 'protocol'] + if config.exists(pg_base) and not config.exists(proto_base): + config.set(proto_base, value='tcp_udp') + +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)) + exit(1) diff --git a/src/migration-scripts/flow-accounting/0-to-1 b/src/migration-scripts/flow-accounting/0-to-1 new file mode 100755 index 000000000..72cce77b0 --- /dev/null +++ b/src/migration-scripts/flow-accounting/0-to-1 @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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/>. + +# T4099: flow-accounting: sync "source-ip" and "source-address" between netflow +# and sflow ion CLI +# T4105: flow-accounting: drop "sflow agent-address auto" + +from sys import argv +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['system', 'flow-accounting'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) + +# T4099 +tmp = base + ['netflow', 'source-ip'] +if config.exists(tmp): + config.rename(tmp, 'source-address') + +# T4105 +tmp = base + ['sflow', 'agent-address'] +if config.exists(tmp): + value = config.return_value(tmp) + if value == 'auto': + # delete the "auto" + config.delete(tmp) + + # 1) check if BGP router-id is set + # 2) check if OSPF router-id is set + # 3) check if OSPFv3 router-id is set + router_id = None + for protocol in ['bgp', 'ospf', 'ospfv3']: + if config.exists(['protocols', protocol, 'parameters', 'router-id']): + router_id = config.return_value(['protocols', protocol, 'parameters', 'router-id']) + break + if router_id: + config.set(tmp, value=router_id) + +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)) + exit(1) diff --git a/src/migration-scripts/interfaces/25-to-26 b/src/migration-scripts/interfaces/25-to-26 new file mode 100755 index 000000000..a8936235e --- /dev/null +++ b/src/migration-scripts/interfaces/25-to-26 @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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/>. + +# T4384: pppoe: replace default-route CLI option with common CLI nodes already +# present for DHCP + +from sys import argv + +from vyos.ethtool import Ethtool +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['interfaces', 'pppoe'] +config = ConfigTree(config_file) + +if not config.exists(base): + exit(0) + +for ifname in config.list_nodes(base): + tmp_config = base + [ifname, 'default-route'] + if config.exists(tmp_config): + # Retrieve current config value + value = config.return_value(tmp_config) + # Delete old Config node + config.delete(tmp_config) + if value == 'none': + config.set(base + [ifname, 'no-default-route']) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/ipsec/8-to-9 b/src/migration-scripts/ipsec/8-to-9 new file mode 100755 index 000000000..eb44b6216 --- /dev/null +++ b/src/migration-scripts/ipsec/8-to-9 @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 argv +from sys import exit + +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['vpn', 'ipsec', 'ike-group'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) +else: + for ike_group in config.list_nodes(base): + base_closeaction = base + [ike_group, 'close-action'] + if config.exists(base_closeaction) and config.return_value(base_closeaction) == 'clear': + config.set(base_closeaction, 'none', replace=True) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/openconnect/1-to-2 b/src/migration-scripts/openconnect/1-to-2 new file mode 100755 index 000000000..7031fb252 --- /dev/null +++ b/src/migration-scripts/openconnect/1-to-2 @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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/>. + +# Delete depricated outside-nexthop address + +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) + +cfg_base = ['vpn', 'openconnect'] + +if not config.exists(cfg_base): + # Nothing to do + sys.exit(0) +else: + if config.exists(cfg_base + ['authentication', 'mode']): + if config.return_value(cfg_base + ['authentication', 'mode']) == 'radius': + # if "mode value radius", change to "tag node mode + valueless node radius" + config.delete(cfg_base + ['authentication','mode', 'radius']) + config.set(cfg_base + ['authentication', 'mode', 'radius'], value=None, replace=True) + elif not config.exists(cfg_base + ['authentication', 'mode', 'local']): + # if "mode local", change to "tag node mode + node local value password" + config.delete(cfg_base + ['authentication', 'mode', 'local']) + config.set(cfg_base + ['authentication', 'mode', 'local'], value='password', replace=True) + 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/ospf/0-to-1 b/src/migration-scripts/ospf/0-to-1 new file mode 100755 index 000000000..678569d9e --- /dev/null +++ b/src/migration-scripts/ospf/0-to-1 @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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/>. + +# T3753: upgrade to FRR8 and move CLI options to better fit with the new FRR CLI + +from sys import argv +from vyos.configtree import ConfigTree + +def ospf_passive_migration(config, ospf_base): + if config.exists(ospf_base): + if config.exists(ospf_base + ['passive-interface']): + default = False + for interface in config.return_values(ospf_base + ['passive-interface']): + if interface == 'default': + default = True + continue + config.set(ospf_base + ['interface', interface, 'passive']) + + config.delete(ospf_base + ['passive-interface']) + config.set(ospf_base + ['passive-interface'], value='default') + + if config.exists(ospf_base + ['passive-interface-exclude']): + for interface in config.return_values(ospf_base + ['passive-interface-exclude']): + config.set(ospf_base + ['interface', interface, 'passive', 'disable']) + config.delete(ospf_base + ['passive-interface-exclude']) + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +config = ConfigTree(config_file) + +ospfv3_base = ['protocols', 'ospfv3'] +if config.exists(ospfv3_base): + area_base = ospfv3_base + ['area'] + if config.exists(area_base): + for area in config.list_nodes(area_base): + if not config.exists(area_base + [area, 'interface']): + continue + + for interface in config.return_values(area_base + [area, 'interface']): + config.set(ospfv3_base + ['interface', interface, 'area'], value=area) + config.set_tag(ospfv3_base + ['interface']) + + config.delete(area_base + [area, 'interface']) + +# Migrate OSPF syntax in default VRF +ospf_base = ['protocols', 'ospf'] +ospf_passive_migration(config, ospf_base) + +vrf_base = ['vrf', 'name'] +if config.exists(vrf_base): + for vrf in config.list_nodes(vrf_base): + vrf_ospf_base = vrf_base + [vrf, 'protocols', 'ospf'] + if config.exists(vrf_ospf_base): + ospf_passive_migration(config, vrf_ospf_base) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/policy/1-to-2 b/src/migration-scripts/policy/1-to-2 new file mode 100755 index 000000000..eebbf9d41 --- /dev/null +++ b/src/migration-scripts/policy/1-to-2 @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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/>. + +# T4170: rename "policy ipv6-route" to "policy route6" to match common +# IPv4/IPv6 schema +# T4178: Update tcp flags to use multi value node + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['policy', 'ipv6-route'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) + +config.rename(base, 'route6') +config.set_tag(['policy', 'route6']) + +for route in ['route', 'route6']: + route_path = ['policy', route] + if config.exists(route_path): + for name in config.list_nodes(route_path): + if config.exists(route_path + [name, 'rule']): + for rule in config.list_nodes(route_path + [name, 'rule']): + rule_tcp_flags = route_path + [name, 'rule', rule, 'tcp', 'flags'] + + if config.exists(rule_tcp_flags): + tmp = config.return_value(rule_tcp_flags) + config.delete(rule_tcp_flags) + for flag in tmp.split(","): + for flag in tmp.split(","): + if flag[0] == '!': + config.set(rule_tcp_flags + ['not', flag[1:].lower()]) + else: + config.set(rule_tcp_flags + [flag.lower()]) + +if config.exists(['interfaces']): + def if_policy_rename(config, path): + if config.exists(path + ['policy', 'ipv6-route']): + config.rename(path + ['policy', 'ipv6-route'], 'route6') + + for if_type in config.list_nodes(['interfaces']): + for ifname in config.list_nodes(['interfaces', if_type]): + if_path = ['interfaces', if_type, ifname] + if_policy_rename(config, if_path) + + for vif_type in ['vif', 'vif-s']: + if config.exists(if_path + [vif_type]): + for vifname in config.list_nodes(if_path + [vif_type]): + if_policy_rename(config, if_path + [vif_type, vifname]) + + if config.exists(if_path + [vif_type, vifname, 'vif-c']): + for vifcname in config.list_nodes(if_path + [vif_type, vifname, 'vif-c']): + if_policy_rename(config, if_path + [vif_type, vifname, 'vif-c', vifcname]) +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/quagga/9-to-10 b/src/migration-scripts/quagga/9-to-10 new file mode 100755 index 000000000..249738822 --- /dev/null +++ b/src/migration-scripts/quagga/9-to-10 @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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/>. + +# re-organize route-map as-path + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree + +if (len(argv) < 2): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['policy', 'route-map'] + +config = ConfigTree(config_file) +if not config.exists(base): + # Nothing to do + exit(0) + +for route_map in config.list_nodes(base): + # Bail out Early + if not config.exists(base + [route_map, 'rule']): + continue + + for rule in config.list_nodes(base + [route_map, 'rule']): + rule_base = base + [route_map, 'rule', rule] + if config.exists(rule_base + ['set', 'as-path-exclude']): + tmp = config.return_value(rule_base + ['set', 'as-path-exclude']) + config.delete(rule_base + ['set', 'as-path-exclude']) + config.set(rule_base + ['set', 'as-path', 'exclude'], value=tmp) + + if config.exists(rule_base + ['set', 'as-path-prepend']): + tmp = config.return_value(rule_base + ['set', 'as-path-prepend']) + config.delete(rule_base + ['set', 'as-path-prepend']) + config.set(rule_base + ['set', 'as-path', 'prepend'], value=tmp) + +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)) + exit(1) diff --git a/src/migration-scripts/ssh/1-to-2 b/src/migration-scripts/ssh/1-to-2 index bc8815753..31c40df16 100755 --- a/src/migration-scripts/ssh/1-to-2 +++ b/src/migration-scripts/ssh/1-to-2 @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -30,26 +30,52 @@ file_name = argv[1] with open(file_name, 'r') as f: config_file = f.read() -base = ['service', 'ssh', 'loglevel'] +base = ['service', 'ssh'] config = ConfigTree(config_file) if not config.exists(base): # Nothing to do exit(0) -else: - # red in configured loglevel and convert it to lower case - tmp = config.return_value(base).lower() +path_loglevel = base + ['loglevel'] +if config.exists(path_loglevel): + # red in configured loglevel and convert it to lower case + tmp = config.return_value(path_loglevel).lower() # VyOS 1.2 had no proper value validation on the CLI thus the # user could use any arbitrary values - sanitize them if tmp not in ['quiet', 'fatal', 'error', 'info', 'verbose']: tmp = 'info' + config.set(path_loglevel, value=tmp) + +# T4273: migrate ssh cipher list to multi node +path_ciphers = base + ['ciphers'] +if config.exists(path_ciphers): + tmp = [] + # get curtrent cipher list - comma delimited + for cipher in config.return_values(path_ciphers): + tmp.extend(cipher.split(',')) + # delete old cipher suite representation + config.delete(path_ciphers) - config.set(base, value=tmp) + for cipher in tmp: + config.set(path_ciphers, value=cipher, 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)) - exit(1) +# T4273: migrate ssh key-exchange list to multi node +path_kex = base + ['key-exchange'] +if config.exists(path_kex): + tmp = [] + # get curtrent cipher list - comma delimited + for kex in config.return_values(path_kex): + tmp.extend(kex.split(',')) + # delete old cipher suite representation + config.delete(path_kex) + + for kex in tmp: + config.set(path_kex, value=kex, 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)) + exit(1) diff --git a/src/migration-scripts/system/22-to-23 b/src/migration-scripts/system/22-to-23 new file mode 100755 index 000000000..7f832e48a --- /dev/null +++ b/src/migration-scripts/system/22-to-23 @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from sys import exit, argv +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['system', 'ipv6'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) + +# T4346: drop support to disbale IPv6 address family within the OS Kernel +if config.exists(base + ['disable']): + config.delete(base + ['disable']) + # IPv6 address family disable was the only CLI option set - we can cleanup + # the entire tree + if len(config.list_nodes(base)) == 0: + config.delete(base) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/migration-scripts/system/23-to-24 b/src/migration-scripts/system/23-to-24 new file mode 100755 index 000000000..5ea71d51a --- /dev/null +++ b/src/migration-scripts/system/23-to-24 @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os + +from ipaddress import ip_interface +from ipaddress import ip_address +from sys import exit, argv +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['protocols', 'static', 'arp'] +tmp_base = ['protocols', 'static', 'arp-tmp'] +config = ConfigTree(config_file) + +def fixup_cli(config, path, interface): + if config.exists(path + ['address']): + for address in config.return_values(path + ['address']): + tmp = ip_interface(address) + if ip_address(host) in tmp.network.hosts(): + mac = config.return_value(tmp_base + [host, 'hwaddr']) + iface_path = ['protocols', 'static', 'arp', 'interface'] + config.set(iface_path + [interface, 'address', host, 'mac'], value=mac) + config.set_tag(iface_path) + config.set_tag(iface_path + [interface, 'address']) + continue + +if not config.exists(base): + # Nothing to do + exit(0) + +# We need a temporary copy of the config tree as the original one needs to be +# deleted first due to a change iun thge tagNode structure. +config.copy(base, tmp_base) +config.delete(base) + +for host in config.list_nodes(tmp_base): + for type in config.list_nodes(['interfaces']): + for interface in config.list_nodes(['interfaces', type]): + if_base = ['interfaces', type, interface] + fixup_cli(config, if_base, interface) + + if config.exists(if_base + ['vif']): + for vif in config.list_nodes(if_base + ['vif']): + vif_base = ['interfaces', type, interface, 'vif', vif] + fixup_cli(config, vif_base, f'{interface}.{vif}') + + if config.exists(if_base + ['vif-s']): + for vif_s in config.list_nodes(if_base + ['vif-s']): + vif_s_base = ['interfaces', type, interface, 'vif-s', vif_s] + fixup_cli(config, vif_s_base, f'{interface}.{vif_s}') + + if config.exists(if_base + ['vif-s', vif_s, 'vif-c']): + for vif_c in config.list_nodes(if_base + ['vif-s', vif_s, 'vif-c']): + vif_c_base = ['interfaces', type, interface, 'vif-s', vif_s, 'vif-c', vif_c] + fixup_cli(config, vif_c_base, f'{interface}.{vif_s}.{vif_c}') + +config.delete(tmp_base) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print(f'Failed to save the modified config: {e}') + exit(1) diff --git a/src/op_mode/conntrack_sync.py b/src/op_mode/conntrack_sync.py index 66ecf8439..e45c38f07 100755 --- a/src/op_mode/conntrack_sync.py +++ b/src/op_mode/conntrack_sync.py @@ -20,12 +20,15 @@ import xmltodict from argparse import ArgumentParser from vyos.configquery import CliShellApiConfigQuery +from vyos.configquery import ConfigTreeQuery +from vyos.util import call from vyos.util import cmd from vyos.util import run from vyos.template import render_to_string conntrackd_bin = '/usr/sbin/conntrackd' conntrackd_config = '/run/conntrackd/conntrackd.conf' +failover_state_file = '/var/run/vyatta-conntrackd-failover-state' parser = ArgumentParser(description='Conntrack Sync') group = parser.add_mutually_exclusive_group() @@ -36,6 +39,8 @@ group.add_argument('--show-internal', help='Show internal (main) tracking cache' group.add_argument('--show-external', help='Show external (main) tracking cache', action='store_true') group.add_argument('--show-internal-expect', help='Show internal (expect) tracking cache', action='store_true') group.add_argument('--show-external-expect', help='Show external (expect) tracking cache', action='store_true') +group.add_argument('--show-statistics', help='Show connection syncing statistics', action='store_true') +group.add_argument('--show-status', help='Show conntrack-sync status', action='store_true') def is_configured(): """ Check if conntrack-sync service is configured """ @@ -72,7 +77,7 @@ def xml_to_stdout(xml): parsed = xmltodict.parse(line) out.append(parsed) - print(render_to_string('conntrackd/conntrackd.op-mode.tmpl', {'data' : out})) + print(render_to_string('conntrackd/conntrackd.op-mode.j2', {'data' : out})) if __name__ == '__main__': args = parser.parse_args() @@ -131,6 +136,46 @@ if __name__ == '__main__': out = cmd(f'sudo {conntrackd_bin} -C {conntrackd_config} {opt} -x') xml_to_stdout(out) + elif args.show_statistics: + is_configured() + config = ConfigTreeQuery() + print('\nMain Table Statistics:\n') + call(f'sudo {conntrackd_bin} -C {conntrackd_config} -s') + print() + if config.exists(['service', 'conntrack-sync', 'expect-sync']): + print('\nExpect Table Statistics:\n') + call(f'sudo {conntrackd_bin} -C {conntrackd_config} -s exp') + print() + + elif args.show_status: + is_configured() + config = ConfigTreeQuery() + ct_sync_intf = config.list_nodes(['service', 'conntrack-sync', 'interface']) + ct_sync_intf = ', '.join(ct_sync_intf) + failover_state = "no transition yet!" + expect_sync_protocols = "disabled" + + if config.exists(['service', 'conntrack-sync', 'failover-mechanism', 'vrrp']): + failover_mechanism = "vrrp" + vrrp_sync_grp = config.value(['service', 'conntrack-sync', 'failover-mechanism', 'vrrp', 'sync-group']) + + if os.path.isfile(failover_state_file): + with open(failover_state_file, "r") as f: + failover_state = f.readline() + + if config.exists(['service', 'conntrack-sync', 'expect-sync']): + expect_sync_protocols = config.values(['service', 'conntrack-sync', 'expect-sync']) + if 'all' in expect_sync_protocols: + expect_sync_protocols = ["ftp", "sip", "h323", "nfs", "sqlnet"] + expect_sync_protocols = ', '.join(expect_sync_protocols) + + show_status = (f'\nsync-interface : {ct_sync_intf}\n' + f'failover-mechanism : {failover_mechanism} [sync-group {vrrp_sync_grp}]\n' + f'last state transition : {failover_state}' + f'ExpectationSync : {expect_sync_protocols}') + + print(show_status) + else: parser.print_help() exit(1) diff --git a/src/op_mode/containers_op.py b/src/op_mode/containers_op.py deleted file mode 100755 index bc317029c..000000000 --- a/src/op_mode/containers_op.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2021 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 - -from getpass import getuser -from vyos.configquery import ConfigTreeQuery -from vyos.util import cmd - -parser = argparse.ArgumentParser() -parser.add_argument("-a", "--all", action="store_true", help="Show all containers") -parser.add_argument("-i", "--image", action="store_true", help="Show container images") -parser.add_argument("-n", "--networks", action="store_true", help="Show container images") -parser.add_argument("-p", "--pull", action="store", help="Pull image for container") -parser.add_argument("-d", "--remove", action="store", help="Delete container image") -parser.add_argument("-u", "--update", action="store", help="Update given container image") - -config = ConfigTreeQuery() -base = ['container'] -if not config.exists(base): - print('Containers not configured') - exit(0) - -if getuser() != 'root': - raise OSError('This functions needs to be run as root to return correct results!') - -if __name__ == '__main__': - args = parser.parse_args() - - if args.all: - print(cmd('podman ps --all')) - - elif args.image: - print(cmd('podman image ls')) - - elif args.networks: - print(cmd('podman network ls')) - - elif args.pull: - image = args.pull - try: - print(cmd(f'podman image pull {image}')) - except: - print(f'Can\'t find or download image "{image}"') - - elif args.remove: - image = args.remove - try: - print(cmd(f'podman image rm {image}')) - except: - print(f'Can\'t delete image "{image}"') - - elif args.update: - tmp = config.get_config_dict(base + ['name', args.update], - key_mangling=('-', '_'), get_first_key=True) - try: - image = tmp['image'] - print(cmd(f'podman image pull {image}')) - except: - print(f'Can\'t find or download image "{image}"') - else: - parser.print_help() - exit(1) - - exit(0) diff --git a/src/op_mode/cpu_summary.py b/src/op_mode/cpu_summary.py index cfd321522..3bdf5a718 100755 --- a/src/op_mode/cpu_summary.py +++ b/src/op_mode/cpu_summary.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -19,18 +19,30 @@ from vyos.util import colon_separated_to_dict FILE_NAME = '/proc/cpuinfo' -with open(FILE_NAME, 'r') as f: - data_raw = f.read() +def get_raw_data(): + with open(FILE_NAME, 'r') as f: + data_raw = f.read() -data = colon_separated_to_dict(data_raw) + data = colon_separated_to_dict(data_raw) -# Accumulate all data in a dict for future support for machine-readable output -cpu_data = {} -cpu_data['cpu_number'] = len(data['processor']) -cpu_data['models'] = list(set(data['model name'])) + # Accumulate all data in a dict for future support for machine-readable output + cpu_data = {} + cpu_data['cpu_number'] = len(data['processor']) + cpu_data['models'] = list(set(data['model name'])) -# Strip extra whitespace from CPU model names, /proc/cpuinfo is prone to that -cpu_data['models'] = map(lambda s: re.sub(r'\s+', ' ', s), cpu_data['models']) + # Strip extra whitespace from CPU model names, /proc/cpuinfo is prone to that + cpu_data['models'] = list(map(lambda s: re.sub(r'\s+', ' ', s), cpu_data['models'])) + + return cpu_data + +def get_formatted_output(): + cpu_data = get_raw_data() + + out = "CPU(s): {0}\n".format(cpu_data['cpu_number']) + out += "CPU model(s): {0}".format(",".join(cpu_data['models'])) + + return out + +if __name__ == '__main__': + print(get_formatted_output()) -print("CPU(s): {0}".format(cpu_data['cpu_number'])) -print("CPU model(s): {0}".format(",".join(cpu_data['models']))) diff --git a/src/op_mode/firewall.py b/src/op_mode/firewall.py new file mode 100755 index 000000000..3146fc357 --- /dev/null +++ b/src/op_mode/firewall.py @@ -0,0 +1,361 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 ipaddress +import json +import re +import tabulate + +from vyos.config import Config +from vyos.util import cmd +from vyos.util import dict_search_args + +def get_firewall_interfaces(conf, firewall, name=None, ipv6=False): + interfaces = conf.get_config_dict(['interfaces'], key_mangling=('-', '_'), + get_first_key=True, no_tag_node_value_mangle=True) + + directions = ['in', 'out', 'local'] + + def parse_if(ifname, if_conf): + if 'firewall' in if_conf: + for direction in directions: + if direction in if_conf['firewall']: + fw_conf = if_conf['firewall'][direction] + name_str = f'({ifname},{direction})' + + if 'name' in fw_conf: + fw_name = fw_conf['name'] + + if not name: + firewall['name'][fw_name]['interface'].append(name_str) + elif not ipv6 and name == fw_name: + firewall['interface'].append(name_str) + + if 'ipv6_name' in fw_conf: + fw_name = fw_conf['ipv6_name'] + + if not name: + firewall['ipv6_name'][fw_name]['interface'].append(name_str) + elif ipv6 and name == fw_name: + firewall['interface'].append(name_str) + + for iftype in ['vif', 'vif_s', 'vif_c']: + if iftype in if_conf: + for vifname, vif_conf in if_conf[iftype].items(): + parse_if(f'{ifname}.{vifname}', vif_conf) + + for iftype, iftype_conf in interfaces.items(): + for ifname, if_conf in iftype_conf.items(): + parse_if(ifname, if_conf) + + return firewall + +def get_config_firewall(conf, name=None, ipv6=False, interfaces=True): + config_path = ['firewall'] + if name: + config_path += ['ipv6-name' if ipv6 else 'name', name] + + firewall = conf.get_config_dict(config_path, key_mangling=('-', '_'), + get_first_key=True, no_tag_node_value_mangle=True) + if firewall and interfaces: + if name: + firewall['interface'] = [] + else: + if 'name' in firewall: + for fw_name, name_conf in firewall['name'].items(): + name_conf['interface'] = [] + + if 'ipv6_name' in firewall: + for fw_name, name_conf in firewall['ipv6_name'].items(): + name_conf['interface'] = [] + + get_firewall_interfaces(conf, firewall, name, ipv6) + return firewall + +def get_nftables_details(name, ipv6=False): + suffix = '6' if ipv6 else '' + name_prefix = 'NAME6_' if ipv6 else 'NAME_' + command = f'sudo nft list chain ip{suffix} filter {name_prefix}{name}' + try: + results = cmd(command) + except: + return {} + + out = {} + for line in results.split('\n'): + comment_search = re.search(rf'{name}[\- ](\d+|default-action)', line) + if not comment_search: + continue + + rule = {} + rule_id = comment_search[1] + counter_search = re.search(r'counter packets (\d+) bytes (\d+)', line) + if counter_search: + rule['packets'] = counter_search[1] + rule['bytes'] = counter_search[2] + + rule['conditions'] = re.sub(r'(\b(counter packets \d+ bytes \d+|drop|reject|return|log)\b|comment "[\w\-]+")', '', line).strip() + out[rule_id] = rule + return out + +def output_firewall_name(name, name_conf, ipv6=False, single_rule_id=None): + ip_str = 'IPv6' if ipv6 else 'IPv4' + print(f'\n---------------------------------\n{ip_str} Firewall "{name}"\n') + + if name_conf['interface']: + print('Active on: {0}\n'.format(" ".join(name_conf['interface']))) + + details = get_nftables_details(name, ipv6) + rows = [] + + if 'rule' in name_conf: + for rule_id, rule_conf in name_conf['rule'].items(): + if single_rule_id and rule_id != single_rule_id: + continue + + if 'disable' in rule_conf: + continue + + row = [rule_id, rule_conf['action'], rule_conf['protocol'] if 'protocol' in rule_conf else 'all'] + if rule_id in details: + rule_details = details[rule_id] + row.append(rule_details.get('packets', 0)) + row.append(rule_details.get('bytes', 0)) + row.append(rule_details['conditions']) + rows.append(row) + + if 'default_action' in name_conf and not single_rule_id: + row = ['default', name_conf['default_action'], 'all'] + if 'default-action' in details: + rule_details = details['default-action'] + row.append(rule_details.get('packets', 0)) + row.append(rule_details.get('bytes', 0)) + rows.append(row) + + if rows: + header = ['Rule', 'Action', 'Protocol', 'Packets', 'Bytes', 'Conditions'] + print(tabulate.tabulate(rows, header) + '\n') + +def output_firewall_name_statistics(name, name_conf, ipv6=False, single_rule_id=None): + ip_str = 'IPv6' if ipv6 else 'IPv4' + print(f'\n---------------------------------\n{ip_str} Firewall "{name}"\n') + + if name_conf['interface']: + print('Active on: {0}\n'.format(" ".join(name_conf['interface']))) + + details = get_nftables_details(name, ipv6) + rows = [] + + if 'rule' in name_conf: + for rule_id, rule_conf in name_conf['rule'].items(): + if single_rule_id and rule_id != single_rule_id: + continue + + if 'disable' in rule_conf: + continue + + source_addr = dict_search_args(rule_conf, 'source', 'address') or '0.0.0.0/0' + dest_addr = dict_search_args(rule_conf, 'destination', 'address') or '0.0.0.0/0' + + row = [rule_id] + if rule_id in details: + rule_details = details[rule_id] + row.append(rule_details.get('packets', 0)) + row.append(rule_details.get('bytes', 0)) + else: + row.append('0') + row.append('0') + row.append(rule_conf['action']) + row.append(source_addr) + row.append(dest_addr) + rows.append(row) + + if 'default_action' in name_conf and not single_rule_id: + row = ['default'] + if 'default-action' in details: + rule_details = details['default-action'] + row.append(rule_details.get('packets', 0)) + row.append(rule_details.get('bytes', 0)) + else: + row.append('0') + row.append('0') + row.append(name_conf['default_action']) + row.append('0.0.0.0/0') # Source + row.append('0.0.0.0/0') # Dest + rows.append(row) + + if rows: + header = ['Rule', 'Packets', 'Bytes', 'Action', 'Source', 'Destination'] + print(tabulate.tabulate(rows, header) + '\n') + +def show_firewall(): + print('Rulesets Information') + + conf = Config() + firewall = get_config_firewall(conf) + + if not firewall: + return + + if 'name' in firewall: + for name, name_conf in firewall['name'].items(): + output_firewall_name(name, name_conf, ipv6=False) + + if 'ipv6_name' in firewall: + for name, name_conf in firewall['ipv6_name'].items(): + output_firewall_name(name, name_conf, ipv6=True) + +def show_firewall_name(name, ipv6=False): + print('Ruleset Information') + + conf = Config() + firewall = get_config_firewall(conf, name, ipv6) + if firewall: + output_firewall_name(name, firewall, ipv6) + +def show_firewall_rule(name, rule_id, ipv6=False): + print('Rule Information') + + conf = Config() + firewall = get_config_firewall(conf, name, ipv6) + if firewall: + output_firewall_name(name, firewall, ipv6, rule_id) + +def show_firewall_group(name=None): + conf = Config() + firewall = get_config_firewall(conf, interfaces=False) + + if 'group' not in firewall: + return + + def find_references(group_type, group_name): + out = [] + for name_type in ['name', 'ipv6_name']: + if name_type not in firewall: + continue + for name, name_conf in firewall[name_type].items(): + if 'rule' not in name_conf: + continue + for rule_id, rule_conf in name_conf['rule'].items(): + source_group = dict_search_args(rule_conf, 'source', 'group', group_type) + dest_group = dict_search_args(rule_conf, 'destination', 'group', group_type) + if source_group and group_name == source_group: + out.append(f'{name}-{rule_id}') + elif dest_group and group_name == dest_group: + out.append(f'{name}-{rule_id}') + return out + + header = ['Name', 'Type', 'References', 'Members'] + rows = [] + + for group_type, group_type_conf in firewall['group'].items(): + for group_name, group_conf in group_type_conf.items(): + if name and name != group_name: + continue + + references = find_references(group_type, group_name) + row = [group_name, group_type, '\n'.join(references) or 'N/A'] + if 'address' in group_conf: + row.append("\n".join(sorted(group_conf['address'], key=ipaddress.ip_address))) + elif 'network' in group_conf: + row.append("\n".join(sorted(group_conf['network'], key=ipaddress.ip_network))) + elif 'mac_address' in group_conf: + row.append("\n".join(sorted(group_conf['mac_address']))) + elif 'port' in group_conf: + row.append("\n".join(sorted(group_conf['port']))) + else: + row.append('N/A') + rows.append(row) + + if rows: + print('Firewall Groups\n') + print(tabulate.tabulate(rows, header)) + +def show_summary(): + print('Ruleset Summary') + + conf = Config() + firewall = get_config_firewall(conf) + + if not firewall: + return + + header = ['Ruleset Name', 'Description', 'References'] + v4_out = [] + v6_out = [] + + if 'name' in firewall: + for name, name_conf in firewall['name'].items(): + description = name_conf.get('description', '') + interfaces = ", ".join(name_conf['interface']) + v4_out.append([name, description, interfaces]) + + if 'ipv6_name' in firewall: + for name, name_conf in firewall['ipv6_name'].items(): + description = name_conf.get('description', '') + interfaces = ", ".join(name_conf['interface']) + v6_out.append([name, description, interfaces or 'N/A']) + + if v6_out: + print('\nIPv6 name:\n') + print(tabulate.tabulate(v6_out, header) + '\n') + + if v4_out: + print('\nIPv4 name:\n') + print(tabulate.tabulate(v4_out, header) + '\n') + + show_firewall_group() + +def show_statistics(): + print('Rulesets Statistics') + + conf = Config() + firewall = get_config_firewall(conf) + + if not firewall: + return + + if 'name' in firewall: + for name, name_conf in firewall['name'].items(): + output_firewall_name_statistics(name, name_conf, ipv6=False) + + if 'ipv6_name' in firewall: + for name, name_conf in firewall['ipv6_name'].items(): + output_firewall_name_statistics(name, name_conf, ipv6=True) + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--action', help='Action', required=False) + parser.add_argument('--name', help='Firewall name', required=False, action='store', nargs='?', default='') + parser.add_argument('--rule', help='Firewall Rule ID', required=False) + parser.add_argument('--ipv6', help='IPv6 toggle', action='store_true') + + args = parser.parse_args() + + if args.action == 'show': + if not args.rule: + show_firewall_name(args.name, args.ipv6) + else: + show_firewall_rule(args.name, args.rule, args.ipv6) + elif args.action == 'show_all': + show_firewall() + elif args.action == 'show_group': + show_firewall_group(args.name) + elif args.action == 'show_statistics': + show_statistics() + elif args.action == 'show_summary': + show_summary() diff --git a/src/op_mode/format_disk.py b/src/op_mode/format_disk.py index df4486bce..b3ba44e87 100755 --- a/src/op_mode/format_disk.py +++ b/src/op_mode/format_disk.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019 VyOS maintainers and contributors +# Copyright (C) 2019-2021 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 @@ -17,11 +17,10 @@ import argparse import os import re -import sys + from datetime import datetime -from time import sleep -from vyos.util import is_admin, ask_yes_no +from vyos.util import ask_yes_no from vyos.util import call from vyos.util import cmd from vyos.util import DEVNULL @@ -38,16 +37,17 @@ def list_disks(): def is_busy(disk: str): """Check if given disk device is busy by re-reading it's partition table""" - return call(f'sudo blockdev --rereadpt /dev/{disk}', stderr=DEVNULL) != 0 + return call(f'blockdev --rereadpt /dev/{disk}', stderr=DEVNULL) != 0 def backup_partitions(disk: str): """Save sfdisk partitions output to a backup file""" - device_path = '/dev/' + disk - backup_ts = datetime.now().strftime('%Y-%m-%d-%H:%M') - backup_file = '/var/tmp/backup_{}.{}'.format(disk, backup_ts) - cmd(f'sudo /sbin/sfdisk -d {device_path} > {backup_file}') + device_path = f'/dev/{disk}' + backup_ts = datetime.now().strftime('%Y%m%d-%H%M') + backup_file = f'/var/tmp/backup_{disk}.{backup_ts}' + call(f'sfdisk -d {device_path} > {backup_file}') + print(f'Partition table backup saved to {backup_file}') def list_partitions(disk: str): @@ -65,11 +65,11 @@ def list_partitions(disk: str): def delete_partition(disk: str, partition_idx: int): - cmd(f'sudo /sbin/parted /dev/{disk} rm {partition_idx}') + cmd(f'parted /dev/{disk} rm {partition_idx}') def format_disk_like(target: str, proto: str): - cmd(f'sudo /sbin/sfdisk -d /dev/{proto} | sudo /sbin/sfdisk --force /dev/{target}') + cmd(f'sfdisk -d /dev/{proto} | sfdisk --force /dev/{target}') if __name__ == '__main__': @@ -79,10 +79,6 @@ if __name__ == '__main__': group.add_argument('-p', '--proto', type=str, required=True, help='Prototype device to use as reference') args = parser.parse_args() - if not is_admin(): - print('Must be admin or root to format disk') - sys.exit(1) - target_disk = args.target eligible_target_disks = list_disks() @@ -90,54 +86,48 @@ if __name__ == '__main__': eligible_proto_disks = eligible_target_disks.copy() eligible_proto_disks.remove(target_disk) - fmt = { - 'target_disk': target_disk, - 'proto_disk': proto_disk, - } - if proto_disk == target_disk: print('The two disk drives must be different.') - sys.exit(1) + exit(1) - if not os.path.exists('/dev/' + proto_disk): - print('Device /dev/{proto_disk} does not exist'.format_map(fmt)) - sys.exit(1) + if not os.path.exists(f'/dev/{proto_disk}'): + print(f'Device /dev/{proto_disk} does not exist') + exit(1) if not os.path.exists('/dev/' + target_disk): - print('Device /dev/{target_disk} does not exist'.format_map(fmt)) - sys.exit(1) + print(f'Device /dev/{target_disk} does not exist') + exit(1) if target_disk not in eligible_target_disks: - print('Device {target_disk} can not be formatted'.format_map(fmt)) - sys.exit(1) + print(f'Device {target_disk} can not be formatted') + exit(1) if proto_disk not in eligible_proto_disks: - print('Device {proto_disk} can not be used as a prototype for {target_disk}'.format_map(fmt)) - sys.exit(1) + print(f'Device {proto_disk} can not be used as a prototype for {target_disk}') + exit(1) if is_busy(target_disk): - print("Disk device {target_disk} is busy. Can't format it now".format_map(fmt)) - sys.exit(1) + print(f'Disk device {target_disk} is busy, unable to format') + exit(1) - print('This will re-format disk {target_disk} so that it has the same disk\n' - 'partion sizes and offsets as {proto_disk}. This will not copy\n' - 'data from {proto_disk} to {target_disk}. But this will erase all\n' - 'data on {target_disk}.\n'.format_map(fmt)) + print(f'\nThis will re-format disk {target_disk} so that it has the same disk' + f'\npartion sizes and offsets as {proto_disk}. This will not copy' + f'\ndata from {proto_disk} to {target_disk}. But this will erase all' + f'\ndata on {target_disk}.\n') - if not ask_yes_no("Do you wish to proceed?"): - print('OK. Disk drive {target_disk} will not be re-formated'.format_map(fmt)) - sys.exit(0) + if not ask_yes_no('Do you wish to proceed?'): + print(f'Disk drive {target_disk} will not be re-formated') + exit(0) - print('OK. Re-formating disk drive {target_disk}...'.format_map(fmt)) + print(f'Re-formating disk drive {target_disk}...') print('Making backup copy of partitions...') backup_partitions(target_disk) - sleep(1) print('Deleting old partitions...') for p in list_partitions(target_disk): delete_partition(disk=target_disk, partition_idx=p) - print('Creating new partitions on {target_disk} based on {proto_disk}...'.format_map(fmt)) + print(f'Creating new partitions on {target_disk} based on {proto_disk}...') format_disk_like(target=target_disk, proto=proto_disk) - print('Done.') + print('Done!') diff --git a/src/op_mode/generate_openconnect_otp_key.py b/src/op_mode/generate_openconnect_otp_key.py new file mode 100755 index 000000000..363bcf3ea --- /dev/null +++ b/src/op_mode/generate_openconnect_otp_key.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 os + +from vyos.util import popen +from secrets import token_hex +from base64 import b32encode + +if os.geteuid() != 0: + exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.") + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("-u", "--username", type=str, help='Username used for authentication', required=True) + parser.add_argument("-i", "--interval", type=str, help='Duration of single time interval', default="30", required=False) + parser.add_argument("-d", "--digits", type=str, help='The number of digits in the one-time password', default="6", required=False) + args = parser.parse_args() + + hostname = os.uname()[1] + username = args.username + digits = args.digits + period = args.interval + + # check variables: + if int(digits) < 6 or int(digits) > 8: + print("") + quit("The number of digits in the one-time password must be between '6' and '8'") + + if int(period) < 5 or int(period) > 86400: + print("") + quit("Time token interval must be between '5' and '86400' seconds") + + # generate OTP key, URL & QR: + key_hex = token_hex(20) + key_base32 = b32encode(bytes.fromhex(key_hex)).decode() + + otp_url=''.join(["otpauth://totp/",username,"@",hostname,"?secret=",key_base32,"&digits=",digits,"&period=",period]) + qrcode,err = popen('qrencode -t ansiutf8', input=otp_url) + + print("# You can share it with the user, he just needs to scan the QR in his OTP app") + print("# username: ", username) + print("# OTP KEY: ", key_base32) + print("# OTP URL: ", otp_url) + print(qrcode) + print('# To add this OTP key to configuration, run the following commands:') + print(f"set vpn openconnect authentication local-users username {username} otp key '{key_hex}'") + if period != "30": + print(f"set vpn openconnect authentication local-users username {username} otp interval '{period}'") + if digits != "6": + print(f"set vpn openconnect authentication local-users username {username} otp otp-length '{digits}'") diff --git a/src/op_mode/generate_ovpn_client_file.py b/src/op_mode/generate_ovpn_client_file.py new file mode 100755 index 000000000..0628e6135 --- /dev/null +++ b/src/op_mode/generate_ovpn_client_file.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 os + +from jinja2 import Template +from textwrap import fill + +from vyos.configquery import ConfigTreeQuery +from vyos.ifconfig import Section +from vyos.util import cmd + + +client_config = """ + +client +nobind +remote {{ remote_host }} {{ port }} +remote-cert-tls server +proto {{ 'tcp-client' if protocol == 'tcp-active' else 'udp' }} +dev {{ device }} +dev-type {{ device }} +persist-key +persist-tun +verb 3 + +# Encryption options +{% if encryption is defined and encryption is not none %} +{% if encryption.cipher is defined and encryption.cipher is not none %} +cipher {{ encryption.cipher }} +{% if encryption.cipher == 'bf128' %} +keysize 128 +{% elif encryption.cipher == 'bf256' %} +keysize 256 +{% endif %} +{% endif %} +{% if encryption.ncp_ciphers is defined and encryption.ncp_ciphers is not none %} +data-ciphers {{ encryption.ncp_ciphers }} +{% endif %} +{% endif %} + +{% if hash is defined and hash is not none %} +auth {{ hash }} +{% endif %} +keysize 256 +comp-lzo {{ '' if use_lzo_compression is defined else 'no' }} + +<ca> +-----BEGIN CERTIFICATE----- +{{ ca }} +-----END CERTIFICATE----- + +</ca> + +<cert> +-----BEGIN CERTIFICATE----- +{{ cert }} +-----END CERTIFICATE----- + +</cert> + +<key> +-----BEGIN PRIVATE KEY----- +{{ key }} +-----END PRIVATE KEY----- + +</key> + +""" + +config = ConfigTreeQuery() +base = ['interfaces', 'openvpn'] + +if not config.exists(base): + print('OpenVPN not configured') + exit(0) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("-i", "--interface", type=str, help='OpenVPN interface the client is connecting to', required=True) + parser.add_argument("-a", "--ca", type=str, help='OpenVPN CA cerificate', required=True) + parser.add_argument("-c", "--cert", type=str, help='OpenVPN client cerificate', required=True) + parser.add_argument("-k", "--key", type=str, help='OpenVPN client cerificate key', action="store") + args = parser.parse_args() + + interface = args.interface + ca = args.ca + cert = args.cert + key = args.key + if not key: + key = args.cert + + if interface not in Section.interfaces('openvpn'): + exit(f'OpenVPN interface "{interface}" does not exist!') + + if not config.exists(['pki', 'ca', ca, 'certificate']): + exit(f'OpenVPN CA certificate "{ca}" does not exist!') + + if not config.exists(['pki', 'certificate', cert, 'certificate']): + exit(f'OpenVPN certificate "{cert}" does not exist!') + + if not config.exists(['pki', 'certificate', cert, 'private', 'key']): + exit(f'OpenVPN certificate key "{key}" does not exist!') + + ca = config.value(['pki', 'ca', ca, 'certificate']) + ca = fill(ca, width=64) + cert = config.value(['pki', 'certificate', cert, 'certificate']) + cert = fill(cert, width=64) + key = config.value(['pki', 'certificate', key, 'private', 'key']) + key = fill(key, width=64) + remote_host = config.value(base + [interface, 'local-host']) + + ovpn_conf = config.get_config_dict(base + [interface], key_mangling=('-', '_'), get_first_key=True) + + port = '1194' if 'local_port' not in ovpn_conf else ovpn_conf['local_port'] + proto = 'udp' if 'protocol' not in ovpn_conf else ovpn_conf['protocol'] + device = 'tun' if 'device_type' not in ovpn_conf else ovpn_conf['device_type'] + + config = { + 'interface' : interface, + 'ca' : ca, + 'cert' : cert, + 'key' : key, + 'device' : device, + 'port' : port, + 'proto' : proto, + 'remote_host' : remote_host, + 'address' : [], + } + +# Clear out terminal first +print('\x1b[2J\x1b[H') +client = Template(client_config, trim_blocks=True).render(config) +print(client) diff --git a/src/op_mode/generate_public_key_command.py b/src/op_mode/generate_public_key_command.py index 7a7b6c923..f071ae350 100755 --- a/src/op_mode/generate_public_key_command.py +++ b/src/op_mode/generate_public_key_command.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 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 @@ -29,8 +29,12 @@ def get_key(path): key_string = vyos.remote.get_remote_config(path) return key_string.split() -username = sys.argv[1] -algorithm, key, identifier = get_key(sys.argv[2]) +try: + username = sys.argv[1] + algorithm, key, identifier = get_key(sys.argv[2]) +except Exception as e: + print("Failed to retrieve the public key: {}".format(e)) + sys.exit(1) print('# To add this key as an embedded key, run the following commands:') print('configure') @@ -39,3 +43,4 @@ print(f'set system login user {username} authentication public-keys {identifier} print('commit') print('save') print('exit') + diff --git a/src/op_mode/ikev2_profile_generator.py b/src/op_mode/ikev2_profile_generator.py index 990b06c12..21561d16f 100755 --- a/src/op_mode/ikev2_profile_generator.py +++ b/src/op_mode/ikev2_profile_generator.py @@ -222,9 +222,9 @@ except KeyboardInterrupt: print('\n\n==== <snip> ====') if args.os == 'ios': - print(render_to_string('ipsec/ios_profile.tmpl', data)) + print(render_to_string('ipsec/ios_profile.j2', data)) print('==== </snip> ====\n') print('Save the XML from above to a new file named "vyos.mobileconfig" and E-Mail it to your phone.') elif args.os == 'windows': - print(render_to_string('ipsec/windows_profile.tmpl', data)) + print(render_to_string('ipsec/windows_profile.j2', data)) print('==== </snip> ====\n') diff --git a/src/op_mode/lldp_op.py b/src/op_mode/lldp_op.py index 731e71891..17f6bf552 100755 --- a/src/op_mode/lldp_op.py +++ b/src/op_mode/lldp_op.py @@ -54,12 +54,15 @@ def parse_data(data, interface): 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] - cap = '' for capability in capabilities: if capability['enabled']: if capability['type'] == 'Router': diff --git a/src/op_mode/monitor_bandwidth_test.sh b/src/op_mode/monitor_bandwidth_test.sh index 900223bca..a6ad0b42c 100755 --- a/src/op_mode/monitor_bandwidth_test.sh +++ b/src/op_mode/monitor_bandwidth_test.sh @@ -24,6 +24,9 @@ elif [[ $(dig $1 AAAA +short | grep -v '\.$' | wc -l) -gt 0 ]]; then # Set address family to IPv6 when FQDN has at least one AAAA record OPT="-V" +else + # It's not IPv6, no option needed + OPT="" fi /usr/bin/iperf $OPT -c $1 $2 diff --git a/src/op_mode/policy_route.py b/src/op_mode/policy_route.py new file mode 100755 index 000000000..5be40082f --- /dev/null +++ b/src/op_mode/policy_route.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 re +import tabulate + +from vyos.config import Config +from vyos.util import cmd +from vyos.util import dict_search_args + +def get_policy_interfaces(conf, policy, name=None, ipv6=False): + interfaces = conf.get_config_dict(['interfaces'], key_mangling=('-', '_'), + get_first_key=True, no_tag_node_value_mangle=True) + + routes = ['route', 'route6'] + + def parse_if(ifname, if_conf): + if 'policy' in if_conf: + for route in routes: + if route in if_conf['policy']: + route_name = if_conf['policy'][route] + name_str = f'({ifname},{route})' + + if not name: + policy[route][route_name]['interface'].append(name_str) + elif not ipv6 and name == route_name: + policy['interface'].append(name_str) + + for iftype in ['vif', 'vif_s', 'vif_c']: + if iftype in if_conf: + for vifname, vif_conf in if_conf[iftype].items(): + parse_if(f'{ifname}.{vifname}', vif_conf) + + for iftype, iftype_conf in interfaces.items(): + for ifname, if_conf in iftype_conf.items(): + parse_if(ifname, if_conf) + +def get_config_policy(conf, name=None, ipv6=False, interfaces=True): + config_path = ['policy'] + if name: + config_path += ['route6' if ipv6 else 'route', name] + + policy = conf.get_config_dict(config_path, key_mangling=('-', '_'), + get_first_key=True, no_tag_node_value_mangle=True) + if policy and interfaces: + if name: + policy['interface'] = [] + else: + if 'route' in policy: + for route_name, route_conf in policy['route'].items(): + route_conf['interface'] = [] + + if 'route6' in policy: + for route_name, route_conf in policy['route6'].items(): + route_conf['interface'] = [] + + get_policy_interfaces(conf, policy, name, ipv6) + + return policy + +def get_nftables_details(name, ipv6=False): + suffix = '6' if ipv6 else '' + command = f'sudo nft list chain ip{suffix} mangle VYOS_PBR{suffix}_{name}' + try: + results = cmd(command) + except: + return {} + + out = {} + for line in results.split('\n'): + comment_search = re.search(rf'{name}[\- ](\d+|default-action)', line) + if not comment_search: + continue + + rule = {} + rule_id = comment_search[1] + counter_search = re.search(r'counter packets (\d+) bytes (\d+)', line) + if counter_search: + rule['packets'] = counter_search[1] + rule['bytes'] = counter_search[2] + + rule['conditions'] = re.sub(r'(\b(counter packets \d+ bytes \d+|drop|reject|return|log)\b|comment "[\w\-]+")', '', line).strip() + out[rule_id] = rule + return out + +def output_policy_route(name, route_conf, ipv6=False, single_rule_id=None): + ip_str = 'IPv6' if ipv6 else 'IPv4' + print(f'\n---------------------------------\n{ip_str} Policy Route "{name}"\n') + + if route_conf['interface']: + print('Active on: {0}\n'.format(" ".join(route_conf['interface']))) + + details = get_nftables_details(name, ipv6) + rows = [] + + if 'rule' in route_conf: + for rule_id, rule_conf in route_conf['rule'].items(): + if single_rule_id and rule_id != single_rule_id: + continue + + if 'disable' in rule_conf: + continue + + action = rule_conf['action'] if 'action' in rule_conf else 'set' + protocol = rule_conf['protocol'] if 'protocol' in rule_conf else 'all' + + row = [rule_id, action, protocol] + if rule_id in details: + rule_details = details[rule_id] + row.append(rule_details.get('packets', 0)) + row.append(rule_details.get('bytes', 0)) + row.append(rule_details['conditions']) + rows.append(row) + + if 'default_action' in route_conf and not single_rule_id: + row = ['default', route_conf['default_action'], 'all'] + if 'default-action' in details: + rule_details = details['default-action'] + row.append(rule_details.get('packets', 0)) + row.append(rule_details.get('bytes', 0)) + rows.append(row) + + if rows: + header = ['Rule', 'Action', 'Protocol', 'Packets', 'Bytes', 'Conditions'] + print(tabulate.tabulate(rows, header) + '\n') + +def show_policy(ipv6=False): + print('Ruleset Information') + + conf = Config() + policy = get_config_policy(conf) + + if not policy: + return + + if not ipv6 and 'route' in policy: + for route, route_conf in policy['route'].items(): + output_policy_route(route, route_conf, ipv6=False) + + if ipv6 and 'route6' in policy: + for route, route_conf in policy['route6'].items(): + output_policy_route(route, route_conf, ipv6=True) + +def show_policy_name(name, ipv6=False): + print('Ruleset Information') + + conf = Config() + policy = get_config_policy(conf, name, ipv6) + if policy: + output_policy_route(name, policy, ipv6) + +def show_policy_rule(name, rule_id, ipv6=False): + print('Rule Information') + + conf = Config() + policy = get_config_policy(conf, name, ipv6) + if policy: + output_policy_route(name, policy, ipv6, rule_id) + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--action', help='Action', required=False) + parser.add_argument('--name', help='Policy name', required=False, action='store', nargs='?', default='') + parser.add_argument('--rule', help='Policy Rule ID', required=False) + parser.add_argument('--ipv6', help='IPv6 toggle', action='store_true') + + args = parser.parse_args() + + if args.action == 'show': + if not args.rule: + show_policy_name(args.name, args.ipv6) + else: + show_policy_rule(args.name, args.rule, args.ipv6) + elif args.action == 'show_all': + show_policy(args.ipv6) diff --git a/src/op_mode/powerctrl.py b/src/op_mode/powerctrl.py index 679b03c0b..fd4f86d88 100755 --- a/src/op_mode/powerctrl.py +++ b/src/op_mode/powerctrl.py @@ -33,10 +33,12 @@ def utc2local(datetime): def parse_time(s): try: - if re.match(r'^\d{1,2}$', s): - if (int(s) > 59): + if re.match(r'^\d{1,9999}$', s): + if (int(s) > 59) and (int(s) < 1440): s = str(int(s)//60) + ":" + str(int(s)%60) return datetime.strptime(s, "%H:%M").time() + if (int(s) >= 1440): + return s.split() else: return datetime.strptime(s, "%M").time() else: @@ -141,7 +143,7 @@ def execute_shutdown(time, reboot=True, ask=True): cmd(f'/usr/bin/wall "{wall_msg}"') else: if not ts: - exit(f'Invalid time "{time[0]}". The valid format is HH:MM') + exit(f'Invalid time "{time[0]}". Uses 24 Hour Clock format') else: exit(f'Invalid date "{time[1]}". A valid format is YYYY-MM-DD [HH:MM]') else: @@ -172,7 +174,12 @@ def main(): action.add_argument("--reboot", "-r", help="Reboot the system", nargs="*", - metavar="Minutes|HH:MM") + metavar="HH:MM") + + action.add_argument("--reboot_in", "-i", + help="Reboot the system", + nargs="*", + metavar="Minutes") action.add_argument("--poweroff", "-p", help="Poweroff the system", @@ -190,7 +197,17 @@ def main(): try: if args.reboot is not None: + for r in args.reboot: + if ':' not in r and '/' not in r and '.' not in r: + print("Incorrect format! Use HH:MM") + exit(1) execute_shutdown(args.reboot, reboot=True, ask=args.yes) + if args.reboot_in is not None: + for i in args.reboot_in: + if ':' in i: + print("Incorrect format! Use Minutes") + exit(1) + execute_shutdown(args.reboot_in, reboot=True, ask=args.yes) if args.poweroff is not None: execute_shutdown(args.poweroff, reboot=False, ask=args.yes) if args.cancel: diff --git a/src/op_mode/ppp-server-ctrl.py b/src/op_mode/ppp-server-ctrl.py index 670cdf879..e93963fdd 100755 --- a/src/op_mode/ppp-server-ctrl.py +++ b/src/op_mode/ppp-server-ctrl.py @@ -60,7 +60,7 @@ def main(): output, err = popen(cmd_dict['cmd_base'].format(cmd_dict['vpn_types'][args.proto]) + args.action + ses_pattern, stderr=DEVNULL, decode='utf-8') if not err: try: - print(output) + print(f' {output}') except: sys.exit(0) else: diff --git a/src/op_mode/restart_frr.py b/src/op_mode/restart_frr.py index 109c8dd7b..91b25567a 100755 --- a/src/op_mode/restart_frr.py +++ b/src/op_mode/restart_frr.py @@ -22,6 +22,7 @@ import psutil from logging.handlers import SysLogHandler from shutil import rmtree +from vyos.base import Warning from vyos.util import call from vyos.util import ask_yes_no from vyos.util import process_named_running @@ -138,7 +139,7 @@ def _reload_config(daemon): # define program arguments cmd_args_parser = argparse.ArgumentParser(description='restart frr daemons') cmd_args_parser.add_argument('--action', choices=['restart'], required=True, help='action to frr daemons') -cmd_args_parser.add_argument('--daemon', choices=['bfdd', 'bgpd', 'ospfd', 'ospf6d', 'isisd', 'ripd', 'ripngd', 'staticd', 'zebra'], required=False, nargs='*', help='select single or multiple daemons') +cmd_args_parser.add_argument('--daemon', choices=['bfdd', 'bgpd', 'ldpd', 'ospfd', 'ospf6d', 'isisd', 'ripd', 'ripngd', 'staticd', 'zebra'], required=False, nargs='*', help='select single or multiple daemons') # parse arguments cmd_args = cmd_args_parser.parse_args() @@ -163,7 +164,7 @@ if cmd_args.action == 'restart': if cmd_args.daemon != ['']: for daemon in cmd_args.daemon: if not process_named_running(daemon): - print('WARNING: some of listed daemons are not running!') + Warning('some of listed daemons are not running!') # run command to restart daemon for daemon in cmd_args.daemon: diff --git a/src/op_mode/show_configuration_json.py b/src/op_mode/show_configuration_json.py new file mode 100755 index 000000000..fdece533b --- /dev/null +++ b/src/op_mode/show_configuration_json.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 json + +from vyos.configquery import ConfigTreeQuery + + +config = ConfigTreeQuery() +c = config.get_config_dict() + +parser = argparse.ArgumentParser() +parser.add_argument("-p", "--pretty", action="store_true", help="Show pretty configuration in JSON format") + + +if __name__ == '__main__': + args = parser.parse_args() + + if args.pretty: + print(json.dumps(c, indent=4)) + else: + print(json.dumps(c)) diff --git a/src/op_mode/show_cpu.py b/src/op_mode/show_cpu.py index 0040e950d..9973d9789 100755 --- a/src/op_mode/show_cpu.py +++ b/src/op_mode/show_cpu.py @@ -21,7 +21,7 @@ from sys import exit from vyos.util import popen, DEVNULL OUT_TMPL_SRC = """ -{% if cpu %} +{%- if cpu -%} {% if 'vendor' in cpu %}CPU Vendor: {{cpu.vendor}}{% endif %} {% if 'model' in cpu %}Model: {{cpu.model}}{% endif %} {% if 'cpus' in cpu %}Total CPUs: {{cpu.cpus}}{% endif %} @@ -31,31 +31,42 @@ OUT_TMPL_SRC = """ {% if 'mhz' in cpu %}Current MHz: {{cpu.mhz}}{% endif %} {% if 'mhz_min' in cpu %}Minimum MHz: {{cpu.mhz_min}}{% endif %} {% if 'mhz_max' in cpu %}Maximum MHz: {{cpu.mhz_max}}{% endif %} -{% endif %} +{%- endif -%} """ -cpu = {} -cpu_json, code = popen('lscpu -J', stderr=DEVNULL) - -if code == 0: - cpu_info = json.loads(cpu_json) - if len(cpu_info) > 0 and 'lscpu' in cpu_info: - for prop in cpu_info['lscpu']: - if (prop['field'].find('Thread(s)') > -1): cpu['threads'] = prop['data'] - if (prop['field'].find('Core(s)')) > -1: cpu['cores'] = prop['data'] - if (prop['field'].find('Socket(s)')) > -1: cpu['sockets'] = prop['data'] - if (prop['field'].find('CPU(s):')) > -1: cpu['cpus'] = prop['data'] - if (prop['field'].find('CPU MHz')) > -1: cpu['mhz'] = prop['data'] - if (prop['field'].find('CPU min MHz')) > -1: cpu['mhz_min'] = prop['data'] - if (prop['field'].find('CPU max MHz')) > -1: cpu['mhz_max'] = prop['data'] - if (prop['field'].find('Vendor ID')) > -1: cpu['vendor'] = prop['data'] - if (prop['field'].find('Model name')) > -1: cpu['model'] = prop['data'] - -if len(cpu) > 0: - tmp = { 'cpu':cpu } +def get_raw_data(): + cpu = {} + cpu_json, code = popen('lscpu -J', stderr=DEVNULL) + + if code == 0: + cpu_info = json.loads(cpu_json) + if len(cpu_info) > 0 and 'lscpu' in cpu_info: + for prop in cpu_info['lscpu']: + if (prop['field'].find('Thread(s)') > -1): cpu['threads'] = prop['data'] + if (prop['field'].find('Core(s)')) > -1: cpu['cores'] = prop['data'] + if (prop['field'].find('Socket(s)')) > -1: cpu['sockets'] = prop['data'] + if (prop['field'].find('CPU(s):')) > -1: cpu['cpus'] = prop['data'] + if (prop['field'].find('CPU MHz')) > -1: cpu['mhz'] = prop['data'] + if (prop['field'].find('CPU min MHz')) > -1: cpu['mhz_min'] = prop['data'] + if (prop['field'].find('CPU max MHz')) > -1: cpu['mhz_max'] = prop['data'] + if (prop['field'].find('Vendor ID')) > -1: cpu['vendor'] = prop['data'] + if (prop['field'].find('Model name')) > -1: cpu['model'] = prop['data'] + + return cpu + +def get_formatted_output(): + cpu = get_raw_data() + + tmp = {'cpu':cpu} tmpl = Template(OUT_TMPL_SRC) - print(tmpl.render(tmp)) - exit(0) -else: - print('CPU information could not be determined\n') - exit(1) + return tmpl.render(tmp) + +if __name__ == '__main__': + cpu = get_raw_data() + + if len(cpu) > 0: + print(get_formatted_output()) + else: + print('CPU information could not be determined\n') + exit(1) + diff --git a/src/op_mode/show_dhcp.py b/src/op_mode/show_dhcp.py index cd6e8ed43..4b1758eea 100755 --- a/src/op_mode/show_dhcp.py +++ b/src/op_mode/show_dhcp.py @@ -26,6 +26,7 @@ from datetime import datetime from isc_dhcp_leases import Lease, IscDhcpLeases +from vyos.base import Warning from vyos.config import Config from vyos.util import is_systemd_service_running @@ -213,7 +214,7 @@ if __name__ == '__main__': # if dhcp server is down, inactive leases may still be shown as active, so warn the user. if not is_systemd_service_running('isc-dhcp-server.service'): - print("WARNING: DHCP server is configured but not started. Data may be stale.") + Warning('DHCP server is configured but not started. Data may be stale.') if args.leases: leases = get_leases(conf, lease_file, args.state, args.pool, args.sort) diff --git a/src/op_mode/show_dhcpv6.py b/src/op_mode/show_dhcpv6.py index 1f987ff7b..b34b730e6 100755 --- a/src/op_mode/show_dhcpv6.py +++ b/src/op_mode/show_dhcpv6.py @@ -26,6 +26,7 @@ from datetime import datetime from isc_dhcp_leases import Lease, IscDhcpLeases +from vyos.base import Warning from vyos.config import Config from vyos.util import is_systemd_service_running @@ -203,7 +204,7 @@ if __name__ == '__main__': # if dhcp server is down, inactive leases may still be shown as active, so warn the user. if not is_systemd_service_running('isc-dhcp-server6.service'): - print("WARNING: DHCPv6 server is configured but not started. Data may be stale.") + Warning('DHCPv6 server is configured but not started. Data may be stale.') if args.leases: leases = get_leases(conf, lease_file, args.state, args.pool, args.sort) diff --git a/src/op_mode/show_ipsec_sa.py b/src/op_mode/show_ipsec_sa.py index e72f0f965..5b8f00dba 100755 --- a/src/op_mode/show_ipsec_sa.py +++ b/src/op_mode/show_ipsec_sa.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019 VyOS maintainers and contributors +# Copyright (C) 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 @@ -14,119 +14,117 @@ # 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 re -import sys +from re import split as re_split +from sys import exit -import vici -import tabulate -import hurry.filesize +from hurry import filesize +from tabulate import tabulate +from vici import Session as vici_session + +from vyos.util import seconds_to_human -import vyos.util def convert(text): return int(text) if text.isdigit() else text.lower() + def alphanum_key(key): - return [convert(c) for c in re.split('([0-9]+)', str(key))] + return [convert(c) for c in re_split('([0-9]+)', str(key))] -def format_output(conns, sas): + +def format_output(sas): sa_data = [] - for peer, parent_conn in conns.items(): - if peer not in sas: - continue - - parent_sa = sas[peer] - child_sas = parent_sa['child-sas'] - installed_sas = {v['name'].decode(): v for k, v in child_sas.items() if v["state"] == b"INSTALLED"} - - # parent_sa["state"] = IKE state, child_sas["state"] = ESP state - state = 'down' - uptime = 'N/A' - - if parent_sa["state"] == b"ESTABLISHED" and installed_sas: - state = "up" - - remote_host = parent_sa["remote-host"].decode() - remote_id = parent_sa["remote-id"].decode() - - if remote_host == remote_id: - remote_id = "N/A" - - # The counters can only be obtained from the child SAs - for child_conn in parent_conn['children']: - if child_conn not in installed_sas: - data = [child_conn, "down", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A"] - sa_data.append(data) - continue - - isa = installed_sas[child_conn] - csa_name = isa['name'] - csa_name = csa_name.decode() - - bytes_in = hurry.filesize.size(int(isa["bytes-in"].decode())) - bytes_out = hurry.filesize.size(int(isa["bytes-out"].decode())) - bytes_str = "{0}/{1}".format(bytes_in, bytes_out) - - pkts_in = hurry.filesize.size(int(isa["packets-in"].decode()), system=hurry.filesize.si) - pkts_out = hurry.filesize.size(int(isa["packets-out"].decode()), system=hurry.filesize.si) - pkts_str = "{0}/{1}".format(pkts_in, pkts_out) - # Remove B from <1K values - pkts_str = re.sub(r'B', r'', pkts_str) - - uptime = vyos.util.seconds_to_human(isa['install-time'].decode()) - - enc = isa["encr-alg"].decode() - if "encr-keysize" in isa: - key_size = isa["encr-keysize"].decode() - else: - key_size = "" - if "integ-alg" in isa: - hash = isa["integ-alg"].decode() - else: - hash = "" - if "dh-group" in isa: - dh_group = isa["dh-group"].decode() - else: - dh_group = "" - - proposal = enc - if key_size: - proposal = "{0}_{1}".format(proposal, key_size) - if hash: - proposal = "{0}/{1}".format(proposal, hash) - if dh_group: - proposal = "{0}/{1}".format(proposal, dh_group) - - data = [csa_name, state, uptime, bytes_str, pkts_str, remote_host, remote_id, proposal] - sa_data.append(data) + for sa in sas: + for parent_sa in sa.values(): + # create an item for each child-sa + for child_sa in parent_sa.get('child-sas', {}).values(): + # prepare a list for output data + sa_out_name = sa_out_state = sa_out_uptime = sa_out_bytes = sa_out_packets = sa_out_remote_addr = sa_out_remote_id = sa_out_proposal = 'N/A' + + # collect raw data + sa_name = child_sa.get('name') + sa_state = child_sa.get('state') + sa_uptime = child_sa.get('install-time') + sa_bytes_in = child_sa.get('bytes-in') + sa_bytes_out = child_sa.get('bytes-out') + sa_packets_in = child_sa.get('packets-in') + sa_packets_out = child_sa.get('packets-out') + sa_remote_addr = parent_sa.get('remote-host') + sa_remote_id = parent_sa.get('remote-id') + sa_proposal_encr_alg = child_sa.get('encr-alg') + sa_proposal_integ_alg = child_sa.get('integ-alg') + sa_proposal_encr_keysize = child_sa.get('encr-keysize') + sa_proposal_dh_group = child_sa.get('dh-group') + + # format data to display + if sa_name: + sa_out_name = sa_name.decode() + if sa_state: + if sa_state == b'INSTALLED': + sa_out_state = 'up' + else: + sa_out_state = 'down' + if sa_uptime: + sa_out_uptime = seconds_to_human(sa_uptime.decode()) + if sa_bytes_in and sa_bytes_out: + bytes_in = filesize.size(int(sa_bytes_in.decode())) + bytes_out = filesize.size(int(sa_bytes_out.decode())) + sa_out_bytes = f'{bytes_in}/{bytes_out}' + if sa_packets_in and sa_packets_out: + packets_in = filesize.size(int(sa_packets_in.decode()), + system=filesize.si) + packets_out = filesize.size(int(sa_packets_out.decode()), + system=filesize.si) + sa_out_packets = f'{packets_in}/{packets_out}' + if sa_remote_addr: + sa_out_remote_addr = sa_remote_addr.decode() + if sa_remote_id: + sa_out_remote_id = sa_remote_id.decode() + # format proposal + if sa_proposal_encr_alg: + sa_out_proposal = sa_proposal_encr_alg.decode() + if sa_proposal_encr_keysize: + sa_proposal_encr_keysize_str = sa_proposal_encr_keysize.decode() + sa_out_proposal = f'{sa_out_proposal}_{sa_proposal_encr_keysize_str}' + if sa_proposal_integ_alg: + sa_proposal_integ_alg_str = sa_proposal_integ_alg.decode() + sa_out_proposal = f'{sa_out_proposal}/{sa_proposal_integ_alg_str}' + if sa_proposal_dh_group: + sa_proposal_dh_group_str = sa_proposal_dh_group.decode() + sa_out_proposal = f'{sa_out_proposal}/{sa_proposal_dh_group_str}' + + # add a new item to output data + sa_data.append([ + sa_out_name, sa_out_state, sa_out_uptime, sa_out_bytes, + sa_out_packets, sa_out_remote_addr, sa_out_remote_id, + sa_out_proposal + ]) + + # return output data return sa_data + if __name__ == '__main__': try: - session = vici.Session() - conns = {} - sas = {} + session = vici_session() + sas = list(session.list_sas()) - for conn in session.list_conns(): - for key in conn: - conns[key] = conn[key] - - for sa in session.list_sas(): - for key in sa: - sas[key] = sa[key] - - headers = ["Connection", "State", "Uptime", "Bytes In/Out", "Packets In/Out", "Remote address", "Remote ID", "Proposal"] - sa_data = format_output(conns, sas) + sa_data = format_output(sas) sa_data = sorted(sa_data, key=alphanum_key) - output = tabulate.tabulate(sa_data, headers) + + headers = [ + "Connection", "State", "Uptime", "Bytes In/Out", "Packets In/Out", + "Remote address", "Remote ID", "Proposal" + ] + output = tabulate(sa_data, headers) print(output) except PermissionError: print("You do not have a permission to connect to the IPsec daemon") - sys.exit(1) + exit(1) except ConnectionRefusedError: print("IPsec is not runing") - sys.exit(1) + exit(1) except Exception as e: print("An error occured: {0}".format(e)) - sys.exit(1) + exit(1) diff --git a/src/op_mode/show_nat_rules.py b/src/op_mode/show_nat_rules.py index d68def26a..98adb31dd 100755 --- a/src/op_mode/show_nat_rules.py +++ b/src/op_mode/show_nat_rules.py @@ -32,7 +32,7 @@ args = parser.parse_args() if args.source or args.destination: tmp = cmd('sudo nft -j list table ip nat') tmp = json.loads(tmp) - + format_nat_rule = '{0: <10} {1: <50} {2: <50} {3: <10}' print(format_nat_rule.format("Rule", "Source" if args.source else "Destination", "Translation", "Outbound Interface" if args.source else "Inbound Interface")) print(format_nat_rule.format("----", "------" if args.source else "-----------", "-----------", "------------------" if args.source else "-----------------")) @@ -40,7 +40,7 @@ if args.source or args.destination: data_json = jmespath.search('nftables[?rule].rule[?chain]', tmp) for idx in range(0, len(data_json)): data = data_json[idx] - + # The following key values must exist # When the rule JSON does not have some keys, this is not a rule we can work with continue_rule = False @@ -50,9 +50,9 @@ if args.source or args.destination: continue if continue_rule: continue - + comment = data['comment'] - + # Check the annotation to see if the annotation format is created by VYOS continue_rule = True for comment_prefix in ['SRC-NAT-', 'DST-NAT-']: @@ -60,7 +60,7 @@ if args.source or args.destination: continue_rule = False if continue_rule: continue - + rule = int(''.join(list(filter(str.isdigit, comment)))) chain = data['chain'] if not ((args.source and chain == 'POSTROUTING') or (not args.source and chain == 'PREROUTING')): @@ -88,7 +88,7 @@ if args.source or args.destination: else: port_range = srcdest_json['set'][0]['range'] srcdest += 'port ' + str(port_range[0]) + '-' + str(port_range[1]) + ' ' - + tran_addr_json = dict_search('snat' if args.source else 'dnat', data['expr'][i]) if tran_addr_json: if isinstance(tran_addr_json['addr'],str): @@ -98,10 +98,10 @@ if args.source or args.destination: len_tmp = dict_search('snat.addr.prefix.len' if args.source else 'dnat.addr.prefix.len', data['expr'][3]) if addr_tmp and len_tmp: tran_addr += addr_tmp + '/' + str(len_tmp) + ' ' - + if isinstance(tran_addr_json['port'],int): - tran_addr += 'port ' + tran_addr_json['port'] - + tran_addr += 'port ' + str(tran_addr_json['port']) + else: if 'masquerade' in data['expr'][i]: tran_addr = 'masquerade' @@ -112,10 +112,10 @@ if args.source or args.destination: srcdests.append(srcdest) srcdest = '' print(format_nat_rule.format(rule, srcdests[0], tran_addr, interface)) - + for i in range(1, len(srcdests)): print(format_nat_rule.format(' ', srcdests[i], ' ', ' ')) - + exit(0) else: parser.print_help() diff --git a/src/op_mode/show_openvpn.py b/src/op_mode/show_openvpn.py index f7b99cc0d..9a5adcffb 100755 --- a/src/op_mode/show_openvpn.py +++ b/src/op_mode/show_openvpn.py @@ -26,10 +26,10 @@ outp_tmpl = """ {% if clients %} OpenVPN status on {{ intf }} -Client CN Remote Host Local Host TX bytes RX bytes Connected Since ---------- ----------- ---------- -------- -------- --------------- +Client CN Remote Host Tunnel IP Local Host TX bytes RX bytes Connected Since +--------- ----------- --------- ---------- -------- -------- --------------- {% for c in clients %} -{{ "%-15s"|format(c.name) }} {{ "%-21s"|format(c.remote) }} {{ "%-21s"|format(local) }} {{ "%-9s"|format(c.tx_bytes) }} {{ "%-9s"|format(c.rx_bytes) }} {{ c.online_since }} +{{ "%-15s"|format(c.name) }} {{ "%-21s"|format(c.remote) }} {{ "%-15s"|format(c.tunnel) }} {{ "%-21s"|format(local) }} {{ "%-9s"|format(c.tx_bytes) }} {{ "%-9s"|format(c.rx_bytes) }} {{ c.online_since }} {% endfor %} {% endif %} """ @@ -50,6 +50,19 @@ def bytes2HR(size): output="{0:.1f} {1}".format(size, suff[suffIdx]) return output +def get_vpn_tunnel_address(peer, interface): + lst = [] + status_file = '/var/run/openvpn/{}.status'.format(interface) + + with open(status_file, 'r') as f: + lines = f.readlines() + for line in lines: + if peer in line: + lst.append(line) + tunnel_ip = lst[1].split(',')[0] + + return tunnel_ip + def get_status(mode, interface): status_file = '/var/run/openvpn/{}.status'.format(interface) # this is an empirical value - I assume we have no more then 999999 @@ -110,7 +123,7 @@ def get_status(mode, interface): 'tx_bytes': bytes2HR(line.split(',')[3]), 'online_since': line.split(',')[4] } - + client["tunnel"] = get_vpn_tunnel_address(client['remote'], interface) data['clients'].append(client) continue else: @@ -173,5 +186,7 @@ if __name__ == '__main__': if len(remote_host) >= 1: client['remote'] = str(remote_host[0]) + ':' + remote_port + client['tunnel'] = 'N/A' + tmpl = jinja2.Template(outp_tmpl) print(tmpl.render(data)) diff --git a/src/op_mode/show_ram.py b/src/op_mode/show_ram.py index 5818ec132..2b0be3965 100755 --- a/src/op_mode/show_ram.py +++ b/src/op_mode/show_ram.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 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 @@ -55,10 +55,17 @@ def get_system_memory_human(): return mem -if __name__ == '__main__': - mem = get_system_memory_human() +def get_raw_data(): + return get_system_memory_human() + +def get_formatted_output(): + mem = get_raw_data() - print("Total: {}".format(mem["total"])) - print("Free: {}".format(mem["free"])) - print("Used: {}".format(mem["used"])) + out = "Total: {}\n".format(mem["total"]) + out += "Free: {}\n".format(mem["free"]) + out += "Used: {}".format(mem["used"]) + return out + +if __name__ == '__main__': + print(get_formatted_output()) diff --git a/src/op_mode/show_uptime.py b/src/op_mode/show_uptime.py index c3dea52e6..b70c60cf8 100755 --- a/src/op_mode/show_uptime.py +++ b/src/op_mode/show_uptime.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright (C) 2021-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 as @@ -26,25 +26,41 @@ def get_uptime_seconds(): def get_load_averages(): from re import search from vyos.util import cmd + from vyos.cpu import get_core_count data = cmd("uptime") matches = search(r"load average:\s*(?P<one>[0-9\.]+)\s*,\s*(?P<five>[0-9\.]+)\s*,\s*(?P<fifteen>[0-9\.]+)\s*", data) + core_count = get_core_count() + res = {} - res[1] = float(matches["one"]) - res[5] = float(matches["five"]) - res[15] = float(matches["fifteen"]) + res[1] = float(matches["one"]) / core_count + res[5] = float(matches["five"]) / core_count + res[15] = float(matches["fifteen"]) / core_count return res -if __name__ == '__main__': +def get_raw_data(): from vyos.util import seconds_to_human - print("Uptime: {}\n".format(seconds_to_human(get_uptime_seconds()))) + res = {} + res["uptime_seconds"] = get_uptime_seconds() + res["uptime"] = seconds_to_human(get_uptime_seconds()) + res["load_average"] = get_load_averages() + + return res + +def get_formatted_output(): + data = get_raw_data() - avgs = get_load_averages() + out = "Uptime: {}\n\n".format(data["uptime"]) + avgs = data["load_average"] + out += "Load averages:\n" + out += "1 minute: {:.01f}%\n".format(avgs[1]*100) + out += "5 minutes: {:.01f}%\n".format(avgs[5]*100) + out += "15 minutes: {:.01f}%\n".format(avgs[15]*100) - print("Load averages:") - print("1 minute: {:.02f}%".format(avgs[1]*100)) - print("5 minutes: {:.02f}%".format(avgs[5]*100)) - print("15 minutes: {:.02f}%".format(avgs[15]*100)) + return out + +if __name__ == '__main__': + print(get_formatted_output()) diff --git a/src/op_mode/show_version.py b/src/op_mode/show_version.py index 7962e1e7b..b82ab6eca 100755 --- a/src/op_mode/show_version.py +++ b/src/op_mode/show_version.py @@ -26,10 +26,6 @@ from jinja2 import Template from sys import exit from vyos.util import call -parser = argparse.ArgumentParser() -parser.add_argument("-f", "--funny", action="store_true", help="Add something funny to the output") -parser.add_argument("-j", "--json", action="store_true", help="Produce JSON output") - version_output_tmpl = """ Version: VyOS {{version}} Release train: {{release_train}} @@ -51,7 +47,20 @@ Hardware UUID: {{hardware_uuid}} Copyright: VyOS maintainers and contributors """ +def get_raw_data(): + version_data = vyos.version.get_full_version_data() + return version_data + +def get_formatted_output(): + version_data = get_raw_data() + tmpl = Template(version_output_tmpl) + return tmpl.render(version_data) + if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("-f", "--funny", action="store_true", help="Add something funny to the output") + parser.add_argument("-j", "--json", action="store_true", help="Produce JSON output") + args = parser.parse_args() version_data = vyos.version.get_full_version_data() @@ -60,9 +69,8 @@ if __name__ == '__main__': import json print(json.dumps(version_data)) exit(0) - - tmpl = Template(version_output_tmpl) - print(tmpl.render(version_data)) + else: + print(get_formatted_output()) if args.funny: print(vyos.limericks.get_random()) diff --git a/src/op_mode/show_virtual_server.py b/src/op_mode/show_virtual_server.py new file mode 100755 index 000000000..377180dec --- /dev/null +++ b/src/op_mode/show_virtual_server.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 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 +# 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 vyos.configquery import ConfigTreeQuery +from vyos.util import call + +def is_configured(): + """ Check if high-availability virtual-server is configured """ + config = ConfigTreeQuery() + if not config.exists(['high-availability', 'virtual-server']): + return False + return True + +if __name__ == '__main__': + + if is_configured() == False: + print('Virtual server not configured!') + exit(0) + + call('sudo ipvsadm --list --numeric') diff --git a/src/op_mode/traceroute.py b/src/op_mode/traceroute.py new file mode 100755 index 000000000..4299d6e5f --- /dev/null +++ b/src/op_mode/traceroute.py @@ -0,0 +1,207 @@ +#! /usr/bin/env python3 + +# Copyright (C) 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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os +import sys +import socket +import ipaddress + +options = { + 'backward-hops': { + 'traceroute': '{command} --back', + 'type': 'noarg', + 'help': 'Display number of backward hops when they different from the forwarded path' + }, + 'bypass': { + 'traceroute': '{command} -r', + 'type': 'noarg', + 'help': 'Bypass the normal routing tables and send directly to a host on an attached network' + }, + 'do-not-fragment': { + 'traceroute': '{command} -F', + 'type': 'noarg', + 'help': 'Do not fragment probe packets.' + }, + 'first-ttl': { + 'traceroute': '{command} -f {value}', + 'type': '<ttl>', + 'help': 'Specifies with what TTL to start. Defaults to 1.' + }, + 'icmp': { + 'traceroute': '{command} -I', + 'type': 'noarg', + 'help': 'Use ICMP ECHO for tracerouting' + }, + 'interface': { + 'traceroute': '{command} -i {value}', + 'type': '<interface>', + 'help': 'Source interface' + }, + 'lookup-as': { + 'traceroute': '{command} -A', + 'type': 'noarg', + 'help': 'Perform AS path lookups' + }, + 'mark': { + 'traceroute': '{command} --fwmark={value}', + 'type': '<fwmark>', + 'help': 'Set the firewall mark for outgoing packets' + }, + 'no-resolve': { + 'traceroute': '{command} -n', + 'type': 'noarg', + 'help': 'Do not resolve hostnames' + }, + 'port': { + 'traceroute': '{command} -p {value}', + 'type': '<port>', + 'help': 'Destination port' + }, + 'source-address': { + 'traceroute': '{command} -s {value}', + 'type': '<x.x.x.x> <h:h:h:h:h:h:h:h>', + 'help': 'Specify source IP v4/v6 address' + }, + 'tcp': { + 'traceroute': '{command} -T', + 'type': 'noarg', + 'help': 'Use TCP SYN for tracerouting (default port is 80)' + }, + 'tos': { + 'traceroute': '{commad} -t {value}', + 'type': '<tos>', + 'help': 'Mark packets with specified TOS' + }, + 'ttl': { + 'traceroute': '{command} -m {value}', + 'type': '<ttl>', + 'help': 'Maximum number of hops' + }, + 'udp': { + 'traceroute': '{command} -U', + 'type': 'noarg', + 'help': 'Use UDP to particular port for tracerouting (default port is 53)' + }, + 'vrf': { + 'traceroute': 'sudo ip vrf exec {value} {command}', + 'type': '<vrf>', + 'help': 'Use specified VRF table', + 'dflt': 'default'} +} + +traceroute = { + 4: '/bin/traceroute -4', + 6: '/bin/traceroute -6', +} + + +class List (list): + def first (self): + return self.pop(0) if self else '' + + def last(self): + return self.pop() if self else '' + + def prepend(self,value): + self.insert(0,value) + + +def expension_failure(option, completions): + reason = 'Ambiguous' if completions else 'Invalid' + sys.stderr.write('\n\n {} command: {} [{}]\n\n'.format(reason,' '.join(sys.argv), option)) + if completions: + sys.stderr.write(' Possible completions:\n ') + sys.stderr.write('\n '.join(completions)) + sys.stderr.write('\n') + sys.stdout.write('<nocomps>') + sys.exit(1) + + +def complete(prefix): + return [o for o in options if o.startswith(prefix)] + + +def convert(command, args): + while args: + shortname = args.first() + longnames = complete(shortname) + if len(longnames) != 1: + expension_failure(shortname, longnames) + longname = longnames[0] + if options[longname]['type'] == 'noarg': + command = options[longname]['traceroute'].format( + command=command, value='') + elif not args: + sys.exit(f'traceroute: missing argument for {longname} option') + else: + command = options[longname]['traceroute'].format( + command=command, value=args.first()) + return command + + +if __name__ == '__main__': + args = List(sys.argv[1:]) + host = args.first() + + if not host: + sys.exit("traceroute: Missing host") + + if host == '--get-options': + args.first() # pop traceroute + args.first() # pop IP + while args: + option = args.first() + + matched = complete(option) + if not args: + sys.stdout.write(' '.join(matched)) + sys.exit(0) + + if len(matched) > 1 : + sys.stdout.write(' '.join(matched)) + sys.exit(0) + + if options[matched[0]]['type'] == 'noarg': + continue + + value = args.first() + if not args: + matched = complete(option) + sys.stdout.write(options[matched[0]]['type']) + sys.exit(0) + + for name,option in options.items(): + if 'dflt' in option and name not in args: + args.append(name) + args.append(option['dflt']) + + try: + ip = socket.gethostbyname(host) + except UnicodeError: + sys.exit(f'tracroute: Unknown host: {host}') + except socket.gaierror: + ip = host + + try: + version = ipaddress.ip_address(ip).version + except ValueError: + sys.exit(f'traceroute: Unknown host: {host}') + + command = convert(traceroute[version],args) + + # print(f'{command} {host}') + os.system(f'{command} {host}') + diff --git a/src/op_mode/vpn_ipsec.py b/src/op_mode/vpn_ipsec.py index 40854fa8f..8955e5a59 100755 --- a/src/op_mode/vpn_ipsec.py +++ b/src/op_mode/vpn_ipsec.py @@ -88,7 +88,22 @@ def reset_profile(profile, tunnel): def debug_peer(peer, tunnel): if not peer or peer == "all": - call('sudo /usr/sbin/ipsec statusall') + debug_commands = [ + "sudo ipsec statusall", + "sudo swanctl -L", + "sudo swanctl -l", + "sudo swanctl -P", + "sudo ip x sa show", + "sudo ip x policy show", + "sudo ip tunnel show", + "sudo ip address", + "sudo ip rule show", + "sudo ip route | head -100", + "sudo ip route show table 220" + ] + for debug_cmd in debug_commands: + print(f'\n### {debug_cmd} ###') + call(debug_cmd) return if not tunnel or tunnel == 'all': diff --git a/src/op_mode/vrrp.py b/src/op_mode/vrrp.py index 2c1db20bf..dab146d28 100755 --- a/src/op_mode/vrrp.py +++ b/src/op_mode/vrrp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -23,6 +23,7 @@ import tabulate import vyos.util +from vyos.configquery import ConfigTreeQuery from vyos.ifconfig.vrrp import VRRP from vyos.ifconfig.vrrp import VRRPError, VRRPNoData @@ -35,7 +36,17 @@ group.add_argument("-d", "--data", action="store_true", help="Print detailed VRR args = parser.parse_args() +def is_configured(): + """ Check if VRRP is configured """ + config = ConfigTreeQuery() + if not config.exists(['high-availability', 'vrrp', 'group']): + return False + return True + # Exit early if VRRP is dead or not configured +if is_configured() == False: + print('VRRP not configured!') + exit(0) if not VRRP.is_running(): print('VRRP is not running') sys.exit(0) diff --git a/src/op_mode/zone_policy.py b/src/op_mode/zone_policy.py new file mode 100755 index 000000000..7b43018c2 --- /dev/null +++ b/src/op_mode/zone_policy.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 tabulate + +from vyos.config import Config +from vyos.util import dict_search_args + +def get_config_zone(conf, name=None): + config_path = ['zone-policy'] + if name: + config_path += ['zone', name] + + zone_policy = conf.get_config_dict(config_path, key_mangling=('-', '_'), + get_first_key=True, no_tag_node_value_mangle=True) + return zone_policy + +def output_zone_name(zone, zone_conf): + print(f'\n---------------------------------\nZone: "{zone}"\n') + + interfaces = ', '.join(zone_conf['interface']) if 'interface' in zone_conf else '' + if 'local_zone' in zone_conf: + interfaces = 'LOCAL' + + print(f'Interfaces: {interfaces}\n') + + header = ['From Zone', 'Firewall'] + rows = [] + + if 'from' in zone_conf: + for from_name, from_conf in zone_conf['from'].items(): + row = [from_name] + v4_name = dict_search_args(from_conf, 'firewall', 'name') + v6_name = dict_search_args(from_conf, 'firewall', 'ipv6_name') + + if v4_name: + rows.append(row + [v4_name]) + + if v6_name: + rows.append(row + [f'{v6_name} [IPv6]']) + + if rows: + print('From Zones:\n') + print(tabulate.tabulate(rows, header)) + +def show_zone_policy(zone): + conf = Config() + zone_policy = get_config_zone(conf, zone) + + if not zone_policy: + return + + if 'zone' in zone_policy: + for zone, zone_conf in zone_policy['zone'].items(): + output_zone_name(zone, zone_conf) + elif zone: + output_zone_name(zone, zone_policy) + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--action', help='Action', required=False) + parser.add_argument('--name', help='Zone name', required=False, action='store', nargs='?', default='') + + args = parser.parse_args() + + if args.action == 'show': + show_zone_policy(args.name) diff --git a/src/services/api/graphql/README.graphql b/src/services/api/graphql/README.graphql index 29f58f709..1133d79ed 100644 --- a/src/services/api/graphql/README.graphql +++ b/src/services/api/graphql/README.graphql @@ -1,7 +1,12 @@ +The following examples are in the form as entered in the GraphQL +'playground', which is found at: + +https://{{ host_address }}/graphql + Example using GraphQL mutations to configure a DHCP server: -This assumes that the http-api is running: +All examples assume that the http-api is running: 'set service https api' @@ -58,8 +63,8 @@ N.B. fileName can be empty (fileName: "") or data can be empty (data: {}) to save to /config/config.boot; to save to an alternative path, specify fileName. -Similarly, using the same 'endpoint' (meaning the form of the request and -resolver; the actual enpoint for all GraphQL requests is +Similarly, using an analogous 'endpoint' (meaning the form of the request +and resolver; the actual enpoint for all GraphQL requests is https://hostname/graphql), one can load an arbitrary config file from a path. @@ -73,17 +78,73 @@ mutation { } } +Op-mode 'show' commands may be requested by path, e.g.: + +query { + Show (data: {path: ["interfaces", "ethernet", "detail"]}) { + success + errors + data { + result + } + } +} -The GraphQL playground will be found at: +N.B. to see the output the 'data' field 'result' must be present in the +request. -https://{{ host_address }}/graphql +Mutations to manipulate firewall address groups: -An equivalent curl command to the first example above would be: +mutation { + CreateFirewallAddressGroup (data: {name: "ADDR-GRP", address: "10.0.0.1"}) { + success + errors + } +} + +mutation { + UpdateFirewallAddressGroupMembers (data: {name: "ADDR-GRP", + address: ["10.0.0.1-10.0.0.8", "192.168.0.1"]}) { + success + errors + } +} + +mutation { + RemoveFirewallAddressGroupMembers (data: {name: "ADDR-GRP", + address: "192.168.0.1"}) { + success + errors + } +} + +N.B. The schema for the above specify that 'address' be of the form 'list of +strings' (SDL type [String!]! for UpdateFirewallAddressGroupMembers, where +the ! indicates that the input is required; SDL type [String] in +CreateFirewallAddressGroup, since a group may be created without any +addresses). However, notice that a single string may be passed without being +a member of a list, in which case the specification allows for 'input +coercion': + +http://spec.graphql.org/October2021/#sec-Scalars.Input-Coercion + +Similarly, IPv6 versions of the above: + +CreateFirewallAddressIpv6Group +UpdateFirewallAddressIpv6GroupMembers +RemoveFirewallAddressIpv6GroupMembers + + +Instead of using the GraphQL playground, an equivalent curl command to the +first example above would be: curl -k 'https://192.168.100.168/graphql' -H 'Content-Type: application/json' --data-binary '{"query": "mutation {createInterfaceEthernet (data: {interface: \"eth1\", address: \"192.168.0.1/24\", description: \"BOB\"}) {success errors data {address}}}"}' Note that the 'mutation' term is prefaced by 'query' in the curl command. +Curl equivalents may be read from within the GraphQL playground at the 'copy +curl' button. + What's here: services @@ -97,15 +158,22 @@ services │  │  └── schema │  │  ├── config_file.graphql │  │  ├── dhcp_server.graphql +│  │  ├── firewall_group.graphql │  │  ├── interface_ethernet.graphql -│  │  └── schema.graphql +│  │  ├── schema.graphql +│  │  ├── show_config.graphql +│  │  └── show.graphql │  ├── README.graphql │  ├── recipes │  │  ├── __init__.py +│  │  ├── remove_firewall_address_group_members.py │  │  ├── session.py │  │  └── templates │  │  ├── create_dhcp_server.tmpl -│  │  └── create_interface_ethernet.tmpl +│  │  ├── create_firewall_address_group.tmpl +│  │  ├── create_interface_ethernet.tmpl +│  │  ├── remove_firewall_address_group_members.tmpl +│  │  └── update_firewall_address_group_members.tmpl │  └── state.py ├── vyos-configd ├── vyos-hostsd diff --git a/src/services/api/graphql/bindings.py b/src/services/api/graphql/bindings.py index 1fbe13d0c..84d719fda 100644 --- a/src/services/api/graphql/bindings.py +++ b/src/services/api/graphql/bindings.py @@ -1,4 +1,20 @@ +# Copyright 2021 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# 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 vyos.defaults +from . graphql.queries import query from . graphql.mutations import mutation from . graphql.directives import directives_dict from ariadne import make_executable_schema, load_schema_from_path, snake_case_fallback_resolvers @@ -8,6 +24,6 @@ def generate_schema(): type_defs = load_schema_from_path(api_schema_dir) - schema = make_executable_schema(type_defs, mutation, snake_case_fallback_resolvers, directives=directives_dict) + schema = make_executable_schema(type_defs, query, mutation, snake_case_fallback_resolvers, directives=directives_dict) return schema diff --git a/src/services/api/graphql/graphql/directives.py b/src/services/api/graphql/graphql/directives.py index f5cd88acd..0a9298f55 100644 --- a/src/services/api/graphql/graphql/directives.py +++ b/src/services/api/graphql/graphql/directives.py @@ -1,5 +1,21 @@ +# Copyright 2021 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# 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/>. + from ariadne import SchemaDirectiveVisitor, ObjectType -from . mutations import make_configure_resolver, make_config_file_resolver +from . queries import * +from . mutations import * def non(arg): pass @@ -19,19 +35,45 @@ class VyosDirective(SchemaDirectiveVisitor): class ConfigureDirective(VyosDirective): """ Class providing implementation of 'configure' directive in schema. - """ def visit_field_definition(self, field, object_type): super().visit_field_definition(field, object_type, make_resolver=make_configure_resolver) +class ShowConfigDirective(VyosDirective): + """ + Class providing implementation of 'show' directive in schema. + """ + def visit_field_definition(self, field, object_type): + super().visit_field_definition(field, object_type, + make_resolver=make_show_config_resolver) + class ConfigFileDirective(VyosDirective): """ Class providing implementation of 'configfile' directive in schema. - """ def visit_field_definition(self, field, object_type): super().visit_field_definition(field, object_type, make_resolver=make_config_file_resolver) -directives_dict = {"configure": ConfigureDirective, "configfile": ConfigFileDirective} +class ShowDirective(VyosDirective): + """ + Class providing implementation of 'show' directive in schema. + """ + def visit_field_definition(self, field, object_type): + super().visit_field_definition(field, object_type, + make_resolver=make_show_resolver) + +class ImageDirective(VyosDirective): + """ + Class providing implementation of 'image' directive in schema. + """ + def visit_field_definition(self, field, object_type): + super().visit_field_definition(field, object_type, + make_resolver=make_image_resolver) + +directives_dict = {"configure": ConfigureDirective, + "showconfig": ShowConfigDirective, + "configfile": ConfigFileDirective, + "show": ShowDirective, + "image": ImageDirective} diff --git a/src/services/api/graphql/graphql/mutations.py b/src/services/api/graphql/graphql/mutations.py index 8a28b13d7..0c3eb702a 100644 --- a/src/services/api/graphql/graphql/mutations.py +++ b/src/services/api/graphql/graphql/mutations.py @@ -1,3 +1,17 @@ +# Copyright 2021 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# 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/>. from importlib import import_module from typing import Any, Dict @@ -10,7 +24,7 @@ from api.graphql.recipes.session import Session mutation = ObjectType("Mutation") -def make_resolver(mutation_name, class_name, session_func): +def make_mutation_resolver(mutation_name, class_name, session_func): """Dynamically generate a resolver for the mutation named in the schema by 'mutation_name'. @@ -51,7 +65,8 @@ def make_resolver(mutation_name, class_name, session_func): klass = type(class_name, (Session,), {}) k = klass(session, data) method = getattr(k, session_func) - method() + result = method() + data['result'] = result return { "success": True, @@ -65,16 +80,20 @@ def make_resolver(mutation_name, class_name, session_func): return func_impl +def make_prefix_resolver(mutation_name, prefix=[]): + for pre in prefix: + Pre = pre.capitalize() + if Pre in mutation_name: + class_name = mutation_name.replace(Pre, '', 1) + return make_mutation_resolver(mutation_name, class_name, pre) + raise Exception + def make_configure_resolver(mutation_name): class_name = mutation_name - return make_resolver(mutation_name, class_name, 'configure') + return make_mutation_resolver(mutation_name, class_name, 'configure') def make_config_file_resolver(mutation_name): - if 'Save' in mutation_name: - class_name = mutation_name.replace('Save', '', 1) - return make_resolver(mutation_name, class_name, 'save') - elif 'Load' in mutation_name: - class_name = mutation_name.replace('Load', '', 1) - return make_resolver(mutation_name, class_name, 'load') - else: - raise Exception + return make_prefix_resolver(mutation_name, prefix=['save', 'load']) + +def make_image_resolver(mutation_name): + return make_prefix_resolver(mutation_name, prefix=['add', 'delete']) diff --git a/src/services/api/graphql/graphql/queries.py b/src/services/api/graphql/graphql/queries.py new file mode 100644 index 000000000..e1868091e --- /dev/null +++ b/src/services/api/graphql/graphql/queries.py @@ -0,0 +1,89 @@ +# Copyright 2021 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# 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/>. + +from importlib import import_module +from typing import Any, Dict +from ariadne import ObjectType, convert_kwargs_to_snake_case, convert_camel_case_to_snake +from graphql import GraphQLResolveInfo +from makefun import with_signature + +from .. import state +from api.graphql.recipes.session import Session + +query = ObjectType("Query") + +def make_query_resolver(query_name, class_name, session_func): + """Dynamically generate a resolver for the query named in the + schema by 'query_name'. + + Dynamic generation is provided using the package 'makefun' (via the + decorator 'with_signature'), which provides signature-preserving + function wrappers; it provides several improvements over, say, + functools.wraps. + + :raise Exception: + raising ConfigErrors, or internal errors + """ + + func_base_name = convert_camel_case_to_snake(class_name) + resolver_name = f'resolve_{func_base_name}' + func_sig = '(obj: Any, info: GraphQLResolveInfo, data: Dict)' + + @query.field(query_name) + @convert_kwargs_to_snake_case + @with_signature(func_sig, func_name=resolver_name) + async def func_impl(*args, **kwargs): + try: + if 'data' not in kwargs: + return { + "success": False, + "errors": ['missing data'] + } + + data = kwargs['data'] + session = state.settings['app'].state.vyos_session + + # one may override the session functions with a local subclass + try: + mod = import_module(f'api.graphql.recipes.{func_base_name}') + klass = getattr(mod, class_name) + except ImportError: + # otherwise, dynamically generate subclass to invoke subclass + # name based templates + klass = type(class_name, (Session,), {}) + k = klass(session, data) + method = getattr(k, session_func) + result = method() + data['result'] = result + + return { + "success": True, + "data": data + } + except Exception as error: + return { + "success": False, + "errors": [str(error)] + } + + return func_impl + +def make_show_config_resolver(query_name): + class_name = query_name + return make_query_resolver(query_name, class_name, 'show_config') + +def make_show_resolver(query_name): + class_name = query_name + return make_query_resolver(query_name, class_name, 'show') diff --git a/src/services/api/graphql/graphql/schema/firewall_group.graphql b/src/services/api/graphql/graphql/schema/firewall_group.graphql index efe7de632..d89904b9e 100644 --- a/src/services/api/graphql/graphql/schema/firewall_group.graphql +++ b/src/services/api/graphql/graphql/schema/firewall_group.graphql @@ -45,3 +45,51 @@ type RemoveFirewallAddressGroupMembersResult { success: Boolean! errors: [String] } + +input CreateFirewallAddressIpv6GroupInput { + name: String! + address: [String] +} + +type CreateFirewallAddressIpv6Group { + name: String! + address: [String] +} + +type CreateFirewallAddressIpv6GroupResult { + data: CreateFirewallAddressIpv6Group + success: Boolean! + errors: [String] +} + +input UpdateFirewallAddressIpv6GroupMembersInput { + name: String! + address: [String!]! +} + +type UpdateFirewallAddressIpv6GroupMembers { + name: String! + address: [String!]! +} + +type UpdateFirewallAddressIpv6GroupMembersResult { + data: UpdateFirewallAddressIpv6GroupMembers + success: Boolean! + errors: [String] +} + +input RemoveFirewallAddressIpv6GroupMembersInput { + name: String! + address: [String!]! +} + +type RemoveFirewallAddressIpv6GroupMembers { + name: String! + address: [String!]! +} + +type RemoveFirewallAddressIpv6GroupMembersResult { + data: RemoveFirewallAddressIpv6GroupMembers + success: Boolean! + errors: [String] +} diff --git a/src/services/api/graphql/graphql/schema/image.graphql b/src/services/api/graphql/graphql/schema/image.graphql new file mode 100644 index 000000000..7d1b4f9d0 --- /dev/null +++ b/src/services/api/graphql/graphql/schema/image.graphql @@ -0,0 +1,29 @@ +input AddSystemImageInput { + location: String! +} + +type AddSystemImage { + location: String + result: String +} + +type AddSystemImageResult { + data: AddSystemImage + success: Boolean! + errors: [String] +} + +input DeleteSystemImageInput { + name: String! +} + +type DeleteSystemImage { + name: String + result: String +} + +type DeleteSystemImageResult { + data: DeleteSystemImage + success: Boolean! + errors: [String] +} diff --git a/src/services/api/graphql/graphql/schema/schema.graphql b/src/services/api/graphql/graphql/schema/schema.graphql index 9e97a0d60..952e46f34 100644 --- a/src/services/api/graphql/graphql/schema/schema.graphql +++ b/src/services/api/graphql/graphql/schema/schema.graphql @@ -3,12 +3,16 @@ schema { mutation: Mutation } -type Query { - _dummy: String -} - directive @configure on FIELD_DEFINITION directive @configfile on FIELD_DEFINITION +directive @show on FIELD_DEFINITION +directive @showconfig on FIELD_DEFINITION +directive @image on FIELD_DEFINITION + +type Query { + Show(data: ShowInput) : ShowResult @show + ShowConfig(data: ShowConfigInput) : ShowConfigResult @showconfig +} type Mutation { CreateDhcpServer(data: DhcpServerConfigInput) : CreateDhcpServerResult @configure @@ -16,6 +20,11 @@ type Mutation { CreateFirewallAddressGroup(data: CreateFirewallAddressGroupInput) : CreateFirewallAddressGroupResult @configure UpdateFirewallAddressGroupMembers(data: UpdateFirewallAddressGroupMembersInput) : UpdateFirewallAddressGroupMembersResult @configure RemoveFirewallAddressGroupMembers(data: RemoveFirewallAddressGroupMembersInput) : RemoveFirewallAddressGroupMembersResult @configure + CreateFirewallAddressIpv6Group(data: CreateFirewallAddressIpv6GroupInput) : CreateFirewallAddressIpv6GroupResult @configure + UpdateFirewallAddressIpv6GroupMembers(data: UpdateFirewallAddressIpv6GroupMembersInput) : UpdateFirewallAddressIpv6GroupMembersResult @configure + RemoveFirewallAddressIpv6GroupMembers(data: RemoveFirewallAddressIpv6GroupMembersInput) : RemoveFirewallAddressIpv6GroupMembersResult @configure SaveConfigFile(data: SaveConfigFileInput) : SaveConfigFileResult @configfile LoadConfigFile(data: LoadConfigFileInput) : LoadConfigFileResult @configfile + AddSystemImage(data: AddSystemImageInput) : AddSystemImageResult @image + DeleteSystemImage(data: DeleteSystemImageInput) : DeleteSystemImageResult @image } diff --git a/src/services/api/graphql/graphql/schema/show.graphql b/src/services/api/graphql/graphql/schema/show.graphql new file mode 100644 index 000000000..c7709e48b --- /dev/null +++ b/src/services/api/graphql/graphql/schema/show.graphql @@ -0,0 +1,14 @@ +input ShowInput { + path: [String!]! +} + +type Show { + path: [String] + result: String +} + +type ShowResult { + data: Show + success: Boolean! + errors: [String] +} diff --git a/src/services/api/graphql/graphql/schema/show_config.graphql b/src/services/api/graphql/graphql/schema/show_config.graphql new file mode 100644 index 000000000..34afd2aa9 --- /dev/null +++ b/src/services/api/graphql/graphql/schema/show_config.graphql @@ -0,0 +1,21 @@ +""" +Use 'scalar Generic' for show config output, to avoid attempts to +JSON-serialize in case of JSON output. +""" +scalar Generic + +input ShowConfigInput { + path: [String!]! + configFormat: String +} + +type ShowConfig { + path: [String] + result: Generic +} + +type ShowConfigResult { + data: ShowConfig + success: Boolean! + errors: [String] +} diff --git a/src/services/api/graphql/recipes/remove_firewall_address_group_members.py b/src/services/api/graphql/recipes/remove_firewall_address_group_members.py index cde30c27a..b91932e14 100644 --- a/src/services/api/graphql/recipes/remove_firewall_address_group_members.py +++ b/src/services/api/graphql/recipes/remove_firewall_address_group_members.py @@ -1,3 +1,17 @@ +# Copyright 2021 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# 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/>. from . session import Session diff --git a/src/services/api/graphql/recipes/session.py b/src/services/api/graphql/recipes/session.py index b96cc1753..1f844ff70 100644 --- a/src/services/api/graphql/recipes/session.py +++ b/src/services/api/graphql/recipes/session.py @@ -1,9 +1,33 @@ +# Copyright 2021 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# 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 json + from ariadne import convert_camel_case_to_snake + import vyos.defaults from vyos.config import Config +from vyos.configtree import ConfigTree from vyos.template import render -class Session(object): +class Session: + """ + Wrapper for calling configsession functions based on GraphQL requests. + Non-nullable fields in the respective schema allow avoiding a key check + in 'data'. + """ def __init__(self, session, data): self._session = session self._data = data @@ -43,6 +67,21 @@ class Session(object): session.delete(path) session.commit() + def show_config(self): + session = self._session + data = self._data + out = '' + + try: + out = session.show_config(data['path']) + if data.get('config_format', '') == 'json': + config_tree = vyos.configtree.ConfigTree(out) + out = json.loads(config_tree.to_json()) + except Exception as error: + raise error + + return out + def save(self): session = self._session data = self._data @@ -63,3 +102,37 @@ class Session(object): session.commit() except Exception as error: raise error + + def show(self): + session = self._session + data = self._data + out = '' + + try: + out = session.show(data['path']) + except Exception as error: + raise error + + return out + + def add(self): + session = self._session + data = self._data + + try: + res = session.install_image(data['location']) + except Exception as error: + raise error + + return res + + def delete(self): + session = self._session + data = self._data + + try: + res = session.remove_image(data['name']) + except Exception as error: + raise error + + return res diff --git a/src/services/api/graphql/recipes/templates/create_firewall_address_ipv_6_group.tmpl b/src/services/api/graphql/recipes/templates/create_firewall_address_ipv_6_group.tmpl new file mode 100644 index 000000000..e9b660722 --- /dev/null +++ b/src/services/api/graphql/recipes/templates/create_firewall_address_ipv_6_group.tmpl @@ -0,0 +1,4 @@ +set firewall group ipv6-address-group {{ name }} +{% for add in address %} +set firewall group ipv6-address-group {{ name }} address {{ add }} +{% endfor %} diff --git a/src/services/api/graphql/recipes/templates/remove_firewall_address_ipv_6_group_members.tmpl b/src/services/api/graphql/recipes/templates/remove_firewall_address_ipv_6_group_members.tmpl new file mode 100644 index 000000000..0efa0b226 --- /dev/null +++ b/src/services/api/graphql/recipes/templates/remove_firewall_address_ipv_6_group_members.tmpl @@ -0,0 +1,3 @@ +{% for add in address %} +delete firewall group ipv6-address-group {{ name }} address {{ add }} +{% endfor %} diff --git a/src/services/api/graphql/recipes/templates/update_firewall_address_ipv_6_group_members.tmpl b/src/services/api/graphql/recipes/templates/update_firewall_address_ipv_6_group_members.tmpl new file mode 100644 index 000000000..f98a5517c --- /dev/null +++ b/src/services/api/graphql/recipes/templates/update_firewall_address_ipv_6_group_members.tmpl @@ -0,0 +1,3 @@ +{% for add in address %} +set firewall group ipv6-address-group {{ name }} address {{ add }} +{% endfor %} diff --git a/src/services/vyos-configd b/src/services/vyos-configd index 670b6e66a..48c9135e2 100755 --- a/src/services/vyos-configd +++ b/src/services/vyos-configd @@ -28,6 +28,7 @@ import zmq from contextlib import contextmanager from vyos.defaults import directories +from vyos.util import boot_configuration_complete from vyos.configsource import ConfigSourceString, ConfigSourceError from vyos.config import Config from vyos import ConfigError @@ -186,7 +187,7 @@ def initialization(socket): session_out = None # if not a 'live' session, for example on boot, write to file - if not session_out or not os.path.isfile('/tmp/vyos-config-status'): + if not session_out or not boot_configuration_complete(): session_out = script_stdout_log session_mode = 'a' diff --git a/src/services/vyos-hostsd b/src/services/vyos-hostsd index f4b1d0fc2..9ae7b1ea9 100755 --- a/src/services/vyos-hostsd +++ b/src/services/vyos-hostsd @@ -139,6 +139,27 @@ # } # # +### authoritative_zones +## Additional zones hosted authoritatively by pdns-recursor. +## We add NTAs for these zones but do not do much else here. +# +# { 'type': 'authoritative_zones', +# 'op': 'add', +# 'data': ['<str zone>', ...] +# } +# +# { 'type': 'authoritative_zones', +# 'op': 'delete', +# 'data': ['<str zone>', ...] +# } +# +# { 'type': 'authoritative_zones', +# 'op': 'get', +# } +# response: +# { 'data': ['<str zone>', ...] } +# +# ### search_domains # # { 'type': 'search_domains', @@ -255,6 +276,7 @@ STATE = { "name_server_tags_recursor": [], "name_server_tags_system": [], "forward_zones": {}, + "authoritative_zones": [], "hosts": {}, "host_name": "vyos", "domain_name": "", @@ -267,7 +289,8 @@ base_schema = Schema({ Required('op'): Any('add', 'delete', 'set', 'get', 'apply'), 'type': Any('name_servers', 'name_server_tags_recursor', 'name_server_tags_system', - 'forward_zones', 'search_domains', 'hosts', 'host_name'), + 'forward_zones', 'authoritative_zones', 'search_domains', + 'hosts', 'host_name'), 'data': Any(list, dict), 'tag': str, 'tag_regex': str @@ -347,6 +370,11 @@ msg_schema_map = { 'delete': data_list_schema, 'get': op_type_schema }, + 'authoritative_zones': { + 'add': data_list_schema, + 'delete': data_list_schema, + 'get': op_type_schema + }, 'search_domains': { 'add': data_dict_list_schema, 'delete': data_list_schema, @@ -393,12 +421,12 @@ def pdns_rec_control(command): def make_resolv_conf(state): logger.info(f"Writing {RESOLV_CONF_FILE}") - render(RESOLV_CONF_FILE, 'vyos-hostsd/resolv.conf.tmpl', state, + render(RESOLV_CONF_FILE, 'vyos-hostsd/resolv.conf.j2', state, user='root', group='root') def make_hosts(state): logger.info(f"Writing {HOSTS_FILE}") - render(HOSTS_FILE, 'vyos-hostsd/hosts.tmpl', state, + render(HOSTS_FILE, 'vyos-hostsd/hosts.j2', state, user='root', group='root') def make_pdns_rec_conf(state): @@ -409,12 +437,12 @@ def make_pdns_rec_conf(state): chmod_755(PDNS_REC_RUN_DIR) render(PDNS_REC_LUA_CONF_FILE, - 'dns-forwarding/recursor.vyos-hostsd.conf.lua.tmpl', + 'dns-forwarding/recursor.vyos-hostsd.conf.lua.j2', state, user=PDNS_REC_USER, group=PDNS_REC_GROUP) logger.info(f"Writing {PDNS_REC_ZONES_FILE}") render(PDNS_REC_ZONES_FILE, - 'dns-forwarding/recursor.forward-zones.conf.tmpl', + 'dns-forwarding/recursor.forward-zones.conf.j2', state, user=PDNS_REC_USER, group=PDNS_REC_GROUP) def set_host_name(state, data): @@ -522,7 +550,7 @@ def handle_message(msg): data = get_option(msg, 'data') if _type in ['name_servers', 'forward_zones', 'search_domains', 'hosts']: delete_items_from_dict(STATE[_type], data) - elif _type in ['name_server_tags_recursor', 'name_server_tags_system']: + elif _type in ['name_server_tags_recursor', 'name_server_tags_system', 'authoritative_zones']: delete_items_from_list(STATE[_type], data) else: raise ValueError(f'Operation "{op}" unknown data type "{_type}"') @@ -534,7 +562,7 @@ def handle_message(msg): elif _type in ['forward_zones', 'hosts']: add_items_to_dict(STATE[_type], data) # maybe we need to rec_control clear-nta each domain that was removed here? - elif _type in ['name_server_tags_recursor', 'name_server_tags_system']: + elif _type in ['name_server_tags_recursor', 'name_server_tags_system', 'authoritative_zones']: add_items_to_list(STATE[_type], data) else: raise ValueError(f'Operation "{op}" unknown data type "{_type}"') @@ -550,7 +578,7 @@ def handle_message(msg): if _type in ['name_servers', 'search_domains', 'hosts']: tag_regex = get_option(msg, 'tag_regex') result = get_items_from_dict_regex(STATE[_type], tag_regex) - elif _type in ['name_server_tags_recursor', 'name_server_tags_system', 'forward_zones']: + elif _type in ['name_server_tags_recursor', 'name_server_tags_system', 'forward_zones', 'authoritative_zones']: result = STATE[_type] else: raise ValueError(f'Operation "{op}" unknown data type "{_type}"') diff --git a/src/services/vyos-http-api-server b/src/services/vyos-http-api-server index aa7ac6708..c1b595412 100755 --- a/src/services/vyos-http-api-server +++ b/src/services/vyos-http-api-server @@ -32,6 +32,7 @@ from fastapi.responses import HTMLResponse from fastapi.exceptions import RequestValidationError from fastapi.routing import APIRoute from pydantic import BaseModel, StrictStr, validator +from starlette.middleware.cors import CORSMiddleware from starlette.datastructures import FormData from starlette.formparsers import FormParser, MultiPartParser from multipart.multipart import parse_options_header @@ -351,7 +352,7 @@ class MultipartRoute(APIRoute): return error(e.status_code, e.detail) except Exception as e: if request.ERR_MISSING_KEY: - return error(422, "Valid API key is required") + return error(401, "Valid API key is required") if request.ERR_MISSING_DATA: return error(422, "Non-empty data field is required") if request.ERR_NOT_JSON: @@ -610,13 +611,19 @@ def show_op(data: ShowModel): # GraphQL integration ### -from api.graphql.bindings import generate_schema +def graphql_init(fast_api_app): + from api.graphql.bindings import generate_schema -api.graphql.state.init() + api.graphql.state.init() + api.graphql.state.settings['app'] = app -schema = generate_schema() + schema = generate_schema() -app.add_route('/graphql', GraphQL(schema, debug=True)) + if app.state.vyos_origins: + origins = app.state.vyos_origins + app.add_route('/graphql', CORSMiddleware(GraphQL(schema, debug=True), allow_origins=origins, allow_methods=("GET", "POST", "OPTIONS"))) + else: + app.add_route('/graphql', GraphQL(schema, debug=True)) ### @@ -640,15 +647,22 @@ if __name__ == '__main__': app.state.vyos_session = config_session app.state.vyos_keys = server_config['api_keys'] - app.state.vyos_debug = bool(server_config['debug'] == 'true') - app.state.vyos_strict = bool(server_config['strict'] == 'true') + app.state.vyos_debug = server_config['debug'] + app.state.vyos_gql = server_config['gql'] + app.state.vyos_strict = server_config['strict'] + app.state.vyos_origins = server_config.get('cors', {}).get('origins', []) - api.graphql.state.settings['app'] = app + if app.state.vyos_gql: + graphql_init(app) try: - uvicorn.run(app, host=server_config["listen_address"], - port=int(server_config["port"]), - proxy_headers=True) + if not server_config['socket']: + uvicorn.run(app, host=server_config["listen_address"], + port=int(server_config["port"]), + proxy_headers=True) + else: + uvicorn.run(app, uds="/run/api.sock", + proxy_headers=True) except OSError as err: logger.critical(f"OSError {err}") sys.exit(1) diff --git a/src/system/keepalived-fifo.py b/src/system/keepalived-fifo.py index 1fba0d75b..a8df232ae 100755 --- a/src/system/keepalived-fifo.py +++ b/src/system/keepalived-fifo.py @@ -29,6 +29,7 @@ from logging.handlers import SysLogHandler from vyos.ifconfig.vrrp import VRRP from vyos.configquery import ConfigTreeQuery from vyos.util import cmd +from vyos.util import dict_search # configure logging logger = logging.getLogger(__name__) @@ -69,22 +70,11 @@ class KeepalivedFifo: raise ValueError() # Read VRRP configuration directly from CLI - vrrp_config_dict = conf.get_config_dict(base, key_mangling=('-', '_'), - get_first_key=True) - self.vrrp_config = {'vrrp_groups': {}, 'sync_groups': {}} - for key in ['group', 'sync_group']: - if key not in vrrp_config_dict: - continue - for group, group_config in vrrp_config_dict[key].items(): - if 'transition_script' not in group_config: - continue - self.vrrp_config['vrrp_groups'][group] = { - 'STOP': group_config['transition_script'].get('stop'), - 'FAULT': group_config['transition_script'].get('fault'), - 'BACKUP': group_config['transition_script'].get('backup'), - 'MASTER': group_config['transition_script'].get('master'), - } - logger.info(f'Loaded configuration: {self.vrrp_config}') + self.vrrp_config_dict = conf.get_config_dict(base, + key_mangling=('-', '_'), get_first_key=True, + no_tag_node_value_mangle=True) + + logger.debug(f'Loaded configuration: {self.vrrp_config_dict}') except Exception as err: logger.error(f'Unable to load configuration: {err}') @@ -129,20 +119,17 @@ class KeepalivedFifo: if os.path.exists(mdns_running_file): cmd(mdns_update_command) - if n_name in self.vrrp_config['vrrp_groups'] and n_state in self.vrrp_config['vrrp_groups'][n_name]: - n_script = self.vrrp_config['vrrp_groups'][n_name].get(n_state) - if n_script: - self._run_command(n_script) + tmp = dict_search(f'group.{n_name}.transition_script.{n_state.lower()}', self.vrrp_config_dict) + if tmp != None: + self._run_command(tmp) # check and run commands for VRRP sync groups - # currently, this is not available in VyOS CLI - if n_type == 'GROUP': + elif n_type == 'GROUP': if os.path.exists(mdns_running_file): cmd(mdns_update_command) - if n_name in self.vrrp_config['sync_groups'] and n_state in self.vrrp_config['sync_groups'][n_name]: - n_script = self.vrrp_config['sync_groups'][n_name].get(n_state) - if n_script: - self._run_command(n_script) + tmp = dict_search(f'sync_group.{n_name}.transition_script.{n_state.lower()}', self.vrrp_config_dict) + if tmp != None: + self._run_command(tmp) # mark task in queue as done self.message_queue.task_done() except Exception as err: diff --git a/src/systemd/keepalived.service b/src/systemd/keepalived.service new file mode 100644 index 000000000..a462d8614 --- /dev/null +++ b/src/systemd/keepalived.service @@ -0,0 +1,13 @@ +[Unit] +Description=Keepalive Daemon (LVS and VRRP) +After=vyos-router.service +# Only start if there is a configuration file +ConditionFileNotEmpty=/run/keepalived/keepalived.conf + +[Service] +KillMode=process +Type=simple +# Read configuration variable file if it is present +ExecStart=/usr/sbin/keepalived --use-file /run/keepalived/keepalived.conf --pid /run/keepalived/keepalived.pid --dont-fork --snmp +ExecReload=/bin/kill -HUP $MAINPID +PIDFile=/run/keepalived/keepalived.pid diff --git a/src/systemd/miniupnpd.service b/src/systemd/miniupnpd.service new file mode 100644 index 000000000..51cb2eed8 --- /dev/null +++ b/src/systemd/miniupnpd.service @@ -0,0 +1,13 @@ +[Unit] +Description=UPnP service +ConditionPathExists=/run/upnp/miniupnp.conf +After=vyos-router.service +StartLimitIntervalSec=0 + +[Service] +WorkingDirectory=/run/upnp +Type=simple +ExecStart=/usr/sbin/miniupnpd -d -f /run/upnp/miniupnp.conf +PrivateTmp=yes +PIDFile=/run/miniupnpd.pid +Restart=on-failure diff --git a/src/systemd/tftpd@.service b/src/systemd/tftpd@.service index 266bc0962..a674bf598 100644 --- a/src/systemd/tftpd@.service +++ b/src/systemd/tftpd@.service @@ -7,7 +7,7 @@ RequiresMountsFor=/run Type=forking #NotifyAccess=main EnvironmentFile=-/etc/default/tftpd%I -ExecStart=/usr/sbin/in.tftpd "$DAEMON_ARGS" +ExecStart=/bin/sh -c "${VRF_ARGS} /usr/sbin/in.tftpd ${DAEMON_ARGS}" Restart=on-failure [Install] diff --git a/src/systemd/vyos-hostsd.service b/src/systemd/vyos-hostsd.service index b77335778..4da55f518 100644 --- a/src/systemd/vyos-hostsd.service +++ b/src/systemd/vyos-hostsd.service @@ -7,7 +7,7 @@ DefaultDependencies=no # Seemingly sensible way to say "as early as the system is ready" # All vyos-hostsd needs is read/write mounted root -After=systemd-remount-fs.service +After=systemd-remount-fs.service cloud-init.service [Service] WorkingDirectory=/run/vyos-hostsd diff --git a/src/systemd/vyos-http-api.service b/src/systemd/vyos-http-api.service deleted file mode 100644 index ba5df5984..000000000 --- a/src/systemd/vyos-http-api.service +++ /dev/null @@ -1,23 +0,0 @@ -[Unit] -Description=VyOS HTTP API service -After=auditd.service systemd-user-sessions.service time-sync.target vyos-router.service -Requires=vyos-router.service - -[Service] -ExecStartPre=/usr/libexec/vyos/init/vyos-config -ExecStart=/usr/libexec/vyos/services/vyos-http-api-server -Type=idle - -SyslogIdentifier=vyos-http-api -SyslogFacility=daemon - -Restart=on-failure - -# Does't work but leave it here -User=root -Group=vyattacfg - -[Install] -# Installing in a earlier target leaves ExecStartPre waiting -WantedBy=getty.target - diff --git a/src/tests/test_util.py b/src/tests/test_util.py index 9bd27adc0..8ac9a500a 100644 --- a/src/tests/test_util.py +++ b/src/tests/test_util.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright (C) 2020-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 @@ -23,3 +23,6 @@ class TestVyOSUtil(TestCase): expected_data = {"foo_bar": {"baz_quux": None}} new_data = mangle_dict_keys(data, '-', '_') self.assertEqual(new_data, expected_data) + + def test_sysctl_read(self): + self.assertEqual(sysctl_read('net.ipv4.conf.lo.forwarding'), '1') diff --git a/src/tests/test_validate.py b/src/tests/test_validate.py index b43dbd97e..68a257d25 100644 --- a/src/tests/test_validate.py +++ b/src/tests/test_validate.py @@ -30,8 +30,12 @@ class TestVyOSValidate(TestCase): self.assertFalse(vyos.validate.is_ipv6_link_local('169.254.0.1')) self.assertTrue(vyos.validate.is_ipv6_link_local('fe80::')) self.assertTrue(vyos.validate.is_ipv6_link_local('fe80::affe:1')) + self.assertTrue(vyos.validate.is_ipv6_link_local('fe80::affe:1%eth0')) self.assertFalse(vyos.validate.is_ipv6_link_local('2001:db8::')) + self.assertFalse(vyos.validate.is_ipv6_link_local('2001:db8::%eth0')) self.assertFalse(vyos.validate.is_ipv6_link_local('VyOS')) + self.assertFalse(vyos.validate.is_ipv6_link_local('::1')) + self.assertFalse(vyos.validate.is_ipv6_link_local('::1%lo')) def test_is_ipv6_link_local(self): self.assertTrue(vyos.validate.is_loopback_addr('127.0.0.1')) diff --git a/src/utils/vyos-hostsd-client b/src/utils/vyos-hostsd-client index d4d38315a..a0515951a 100755 --- a/src/utils/vyos-hostsd-client +++ b/src/utils/vyos-hostsd-client @@ -129,7 +129,8 @@ try: params = h.split(",") if len(params) < 2: raise ValueError("Malformed host entry") - entry['address'] = params[1] + # Address needs to be a list because of changes made in T2683 + entry['address'] = [params[1]] entry['aliases'] = params[2:] data[params[0]] = entry client.add_hosts({args.tag: data}) diff --git a/src/validators/as-number-list b/src/validators/as-number-list new file mode 100755 index 000000000..432d44180 --- /dev/null +++ b/src/validators/as-number-list @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Copyright (C) 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 +# 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/>. + +if [ $# -lt 1 ]; then + echo "Illegal number of parameters" + exit 1 +fi + +for var in "$@"; do + ${vyos_validators_dir}/numeric --range 1-4294967294 $var + if [ $? -ne 0 ]; then + exit 1 + fi +done + +exit 0 diff --git a/src/validators/bgp-route-target b/src/validators/bgp-rd-rt index e7e4d403f..b2b69c9be 100755 --- a/src/validators/bgp-route-target +++ b/src/validators/bgp-rd-rt @@ -19,29 +19,37 @@ from vyos.template import is_ipv4 parser = ArgumentParser() group = parser.add_mutually_exclusive_group() -group.add_argument('--single', action='store', help='Validate and allow only one route-target') -group.add_argument('--multi', action='store', help='Validate multiple, whitespace separated route-targets') +group.add_argument('--route-distinguisher', action='store', help='Validate BGP route distinguisher') +group.add_argument('--route-target', action='store', help='Validate one BGP route-target') +group.add_argument('--route-target-multi', action='store', help='Validate multiple, whitespace separated BGP route-targets') args = parser.parse_args() -def is_valid_rt(rt): - # every route target needs to have a colon and must consists of two parts +def is_valid(rt): + """ Verify BGP RD/RT - both can be verified using the same logic """ + # every RD/RT (route distinguisher/route target) needs to have a colon and + # must consists of two parts value = rt.split(':') if len(value) != 2: return False - # A route target must either be only numbers, or the first part must be an - # IPv4 address + + # An RD/RT must either be only numbers, or the first part must be an IPv4 + # address if (is_ipv4(value[0]) or value[0].isdigit()) and value[1].isdigit(): return True return False if __name__ == '__main__': - if args.single: - if not is_valid_rt(args.single): + if args.route_distinguisher: + if not is_valid(args.route_distinguisher): + exit(1) + + elif args.route_target: + if not is_valid(args.route_target): exit(1) - elif args.multi: - for rt in args.multi.split(' '): - if not is_valid_rt(rt): + elif args.route_target_multi: + for rt in args.route_target_multi.split(' '): + if not is_valid(rt): exit(1) else: diff --git a/src/validators/ip-address b/src/validators/ip-address index 51fb72c85..11d6df09e 100755 --- a/src/validators/ip-address +++ b/src/validators/ip-address @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-any-single $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IP address" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ip-cidr b/src/validators/ip-cidr index 987bf84ca..60d2ac295 100755 --- a/src/validators/ip-cidr +++ b/src/validators/ip-cidr @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-any-cidr $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IP CIDR" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ip-host b/src/validators/ip-host index f2906e8cf..77c578fa2 100755 --- a/src/validators/ip-host +++ b/src/validators/ip-host @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-any-host $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IP host" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ip-prefix b/src/validators/ip-prefix index e58aad395..e5a64fea8 100755 --- a/src/validators/ip-prefix +++ b/src/validators/ip-prefix @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-any-net $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IP prefix" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ip-protocol b/src/validators/ip-protocol index 078f8e319..c4c882502 100755 --- a/src/validators/ip-protocol +++ b/src/validators/ip-protocol @@ -31,11 +31,12 @@ if __name__ == '__main__': pattern = "!?\\b(all|ip|hopopt|icmp|igmp|ggp|ipencap|st|tcp|egp|igp|pup|udp|" \ "tcp_udp|hmp|xns-idp|rdp|iso-tp4|dccp|xtp|ddp|idpr-cmtp|ipv6|" \ - "ipv6-route|ipv6-frag|idrp|rsvp|gre|esp|ah|skip|ipv6-icmp|" \ + "ipv6-route|ipv6-frag|idrp|rsvp|gre|esp|ah|skip|ipv6-icmp|icmpv6|" \ "ipv6-nonxt|ipv6-opts|rspf|vmtp|eigrp|ospf|ax.25|ipip|etherip|" \ "encap|99|pim|ipcomp|vrrp|l2tp|isis|sctp|fc|mobility-header|" \ "udplite|mpls-in-ip|manet|hip|shim6|wesp|rohc)\\b" if re.match(pattern, input): exit(0) + print(f'Error: {input} is not a valid IP protocol') exit(1) diff --git a/src/validators/ipv4 b/src/validators/ipv4 index 53face090..8676d5800 100755 --- a/src/validators/ipv4 +++ b/src/validators/ipv4 @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv4 $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not IPv4" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv4-address b/src/validators/ipv4-address index 872a7645a..058db088b 100755 --- a/src/validators/ipv4-address +++ b/src/validators/ipv4-address @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv4-single $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv4 address" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv4-host b/src/validators/ipv4-host index f42feffa4..74b8c36a7 100755 --- a/src/validators/ipv4-host +++ b/src/validators/ipv4-host @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv4-host $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv4 host" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv4-multicast b/src/validators/ipv4-multicast index e5cbc9532..3f28c51db 100755 --- a/src/validators/ipv4-multicast +++ b/src/validators/ipv4-multicast @@ -1,3 +1,10 @@ #!/bin/sh -ipaddrcheck --is-ipv4-multicast $1 +ipaddrcheck --is-ipv4-multicast $1 && ipaddrcheck --is-ipv4-single $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv4 multicast address" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv4-prefix b/src/validators/ipv4-prefix index 8ec8a2c45..7e1e0e8dd 100755 --- a/src/validators/ipv4-prefix +++ b/src/validators/ipv4-prefix @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv4-net $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv4 prefix" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv4-range b/src/validators/ipv4-range index cc59039f1..6492bfc52 100755 --- a/src/validators/ipv4-range +++ b/src/validators/ipv4-range @@ -7,6 +7,11 @@ ip2dec () { printf '%d\n' "$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))" } +error_exit() { + echo "Error: $1 is not a valid IPv4 address range" + exit 1 +} + # Only run this if there is a hypen present in $1 if [[ "$1" =~ "-" ]]; then # This only works with real bash (<<<) - split IP addresses into array with @@ -15,21 +20,21 @@ if [[ "$1" =~ "-" ]]; then ipaddrcheck --is-ipv4-single ${strarr[0]} if [ $? -gt 0 ]; then - exit 1 + error_exit $1 fi ipaddrcheck --is-ipv4-single ${strarr[1]} if [ $? -gt 0 ]; then - exit 1 + error_exit $1 fi start=$(ip2dec ${strarr[0]}) stop=$(ip2dec ${strarr[1]}) if [ $start -ge $stop ]; then - exit 1 + error_exit $1 fi exit 0 fi -exit 1 +error_exit $1 diff --git a/src/validators/ipv6 b/src/validators/ipv6 index f18d4a63e..4ae130eb5 100755 --- a/src/validators/ipv6 +++ b/src/validators/ipv6 @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv6 $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not IPv6" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv6-address b/src/validators/ipv6-address index e5d68d756..1fca77668 100755 --- a/src/validators/ipv6-address +++ b/src/validators/ipv6-address @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv6-single $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv6 address" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv6-host b/src/validators/ipv6-host index f7a745077..7085809a9 100755 --- a/src/validators/ipv6-host +++ b/src/validators/ipv6-host @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv6-host $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv6 host" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv6-link-local b/src/validators/ipv6-link-local new file mode 100755 index 000000000..05e693b77 --- /dev/null +++ b/src/validators/ipv6-link-local @@ -0,0 +1,12 @@ +#!/usr/bin/python3 + +import sys +from vyos.validate import is_ipv6_link_local + +if __name__ == '__main__': + if len(sys.argv)>1: + addr = sys.argv[1] + if not is_ipv6_link_local(addr): + sys.exit(1) + + sys.exit(0) diff --git a/src/validators/ipv6-multicast b/src/validators/ipv6-multicast index 66cd90c9c..5aa7d734a 100755 --- a/src/validators/ipv6-multicast +++ b/src/validators/ipv6-multicast @@ -1,3 +1,10 @@ #!/bin/sh -ipaddrcheck --is-ipv6-multicast $1 +ipaddrcheck --is-ipv6-multicast $1 && ipaddrcheck --is-ipv6-single $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv6 multicast address" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv6-prefix b/src/validators/ipv6-prefix index e43616350..890dda723 100755 --- a/src/validators/ipv6-prefix +++ b/src/validators/ipv6-prefix @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv6-net $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv6 prefix" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv6-range b/src/validators/ipv6-range index 033b6461b..7080860c4 100755 --- a/src/validators/ipv6-range +++ b/src/validators/ipv6-range @@ -1,16 +1,20 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 -import sys -import re -from vyos.template import is_ipv6 +from ipaddress import IPv6Address +from sys import argv, exit if __name__ == '__main__': - if len(sys.argv)>1: - ipv6_range = sys.argv[1] - # Regex for ipv6-ipv6 https://regexr.com/ - if re.search('([a-f0-9:]+:+)+[a-f0-9]+-([a-f0-9:]+:+)+[a-f0-9]+', ipv6_range): - for tmp in ipv6_range.split('-'): - if not is_ipv6(tmp): - sys.exit(1) - - sys.exit(0) + if len(argv) > 1: + # try to pass validation and raise an error if failed + try: + ipv6_range = argv[1] + range_left = ipv6_range.split('-')[0] + range_right = ipv6_range.split('-')[1] + if not IPv6Address(range_left) < IPv6Address(range_right): + raise ValueError(f'left element {range_left} must be less than right element {range_right}') + except Exception as err: + print(f'Error: {ipv6_range} is not a valid IPv6 range: {err}') + exit(1) + else: + print('Error: an IPv6 range argument must be provided') + exit(1) diff --git a/src/validators/mac-address-firewall b/src/validators/mac-address-firewall new file mode 100755 index 000000000..70551f86d --- /dev/null +++ b/src/validators/mac-address-firewall @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2018-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 +# 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 re +import sys + +pattern = "^!?([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$" + +if __name__ == '__main__': + if len(sys.argv) != 2: + sys.exit(1) + if not re.match(pattern, sys.argv[1]): + sys.exit(1) + sys.exit(0) diff --git a/src/validators/port-multi b/src/validators/port-multi new file mode 100755 index 000000000..bd6f0ef60 --- /dev/null +++ b/src/validators/port-multi @@ -0,0 +1,52 @@ +#!/usr/bin/python3 + +from sys import argv +from sys import exit +import re + +from vyos.util import read_file + +services_file = '/etc/services' + +def get_services(): + names = [] + service_data = read_file(services_file, "") + for line in service_data.split("\n"): + if not line or line[0] == '#': + continue + tmp = line.split() + names.append(tmp[0]) + if len(tmp) > 2: + # Add port aliases to service list, too + names.extend(tmp[2:]) + # remove duplicate entries (e.g. echo) from list + names = list(dict.fromkeys(names)) + return names + +if __name__ == '__main__': + if len(argv)>1: + ports = argv[1].split(",") + services = get_services() + + for port in ports: + if port and port[0] == '!': + port = port[1:] + if re.match('^[0-9]{1,5}-[0-9]{1,5}$', port): + port_1, port_2 = port.split('-') + if int(port_1) not in range(1, 65536) or int(port_2) not in range(1, 65536): + print(f'Error: {port} is not a valid port range') + exit(1) + if int(port_1) > int(port_2): + print(f'Error: {port} is not a valid port range') + exit(1) + elif port.isnumeric(): + if int(port) not in range(1, 65536): + print(f'Error: {port} is not a valid port') + exit(1) + elif port not in services: + print(f'Error: {port} is not a valid service name') + exit(1) + else: + exit(2) + + exit(0) diff --git a/src/validators/port-range b/src/validators/port-range index abf0b09d5..5468000a7 100755 --- a/src/validators/port-range +++ b/src/validators/port-range @@ -3,16 +3,37 @@ import sys import re +from vyos.util import read_file + +services_file = '/etc/services' + +def get_services(): + names = [] + service_data = read_file(services_file, "") + for line in service_data.split("\n"): + if not line or line[0] == '#': + continue + names.append(line.split(None, 1)[0]) + return names + +def error(port_range): + print(f'Error: {port_range} is not a valid port or port range') + sys.exit(1) + if __name__ == '__main__': if len(sys.argv)>1: port_range = sys.argv[1] - if re.search('[0-9]{1,5}-[0-9]{1,5}', port_range): - for tmp in port_range.split('-'): - if int(tmp) not in range(1, 65535): - sys.exit(1) - else: - if int(port_range) not in range(1, 65535): - sys.exit(1) + if re.match('^[0-9]{1,5}-[0-9]{1,5}$', port_range): + port_1, port_2 = port_range.split('-') + if int(port_1) not in range(1, 65536) or int(port_2) not in range(1, 65536): + error(port_range) + if int(port_1) > int(port_2): + error(port_range) + elif port_range.isnumeric() and int(port_range) not in range(1, 65536): + error(port_range) + elif not port_range.isnumeric() and port_range not in get_services(): + print(f'Error: {port_range} is not a valid service name') + sys.exit(1) else: sys.exit(2) diff --git a/src/validators/range b/src/validators/range new file mode 100755 index 000000000..d4c25f3c4 --- /dev/null +++ b/src/validators/range @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 re +import sys +import argparse + +class MalformedRange(Exception): + pass + +def validate_range(value, min=None, max=None): + try: + lower, upper = re.match(r'^(\d+)-(\d+)$', value).groups() + + lower, upper = int(lower), int(upper) + + if int(lower) > int(upper): + raise MalformedRange("the lower bound exceeds the upper bound".format(value)) + + if min is not None: + if lower < min: + raise MalformedRange("the lower bound must not be less than {}".format(min)) + + if max is not None: + if upper > max: + raise MalformedRange("the upper bound must not be greater than {}".format(max)) + + except (AttributeError, ValueError): + raise MalformedRange("range syntax error") + +parser = argparse.ArgumentParser(description='Range validator.') +parser.add_argument('--min', type=int, action='store') +parser.add_argument('--max', type=int, action='store') +parser.add_argument('value', action='store') + +if __name__ == '__main__': + args = parser.parse_args() + + try: + validate_range(args.value, min=args.min, max=args.max) + except MalformedRange as e: + print("Incorrect range '{}': {}".format(args.value, e)) + sys.exit(1) diff --git a/src/validators/script b/src/validators/script index 1d8a27e5c..4ffdeb2a0 100755 --- a/src/validators/script +++ b/src/validators/script @@ -36,7 +36,7 @@ if __name__ == '__main__': # File outside the config dir is just a warning if not vyos.util.file_is_persistent(script): - sys.exit( - f'Warning: file {path} is outside the / config directory\n' + sys.exit(0)( + f'Warning: file {script} is outside the "/config" directory\n' 'It will not be automatically migrated to a new image on system update' ) diff --git a/src/validators/tcp-flag b/src/validators/tcp-flag new file mode 100755 index 000000000..1496b904a --- /dev/null +++ b/src/validators/tcp-flag @@ -0,0 +1,17 @@ +#!/usr/bin/python3 + +import sys +import re + +if __name__ == '__main__': + if len(sys.argv)>1: + flag = sys.argv[1] + if flag and flag[0] == '!': + flag = flag[1:] + if flag not in ['syn', 'ack', 'rst', 'fin', 'urg', 'psh', 'ecn', 'cwr']: + print(f'Error: {flag} is not a valid TCP flag') + sys.exit(1) + else: + sys.exit(2) + + sys.exit(0) diff --git a/test-requirements.txt b/test-requirements.txt index 9348520b5..a475e0a16 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -3,3 +3,4 @@ lxml pylint nose coverage +jinja2 |