summaryrefslogtreecommitdiff
path: root/data
diff options
context:
space:
mode:
Diffstat (limited to 'data')
-rw-r--r--data/configd-include.json3
-rw-r--r--data/templates/containers/registry.tmpl5
-rw-r--r--data/templates/containers/storage.tmpl5
-rw-r--r--data/templates/dhcp-client/ipv4.tmpl4
-rw-r--r--data/templates/dns-forwarding/recursor.conf.tmpl3
-rw-r--r--data/templates/dynamic-dns/ddclient.conf.tmpl2
-rw-r--r--data/templates/firewall/nftables-nat66.tmpl20
-rw-r--r--data/templates/frr/bgp.frr.tmpl102
-rw-r--r--data/templates/frr/isis.frr.tmpl11
-rw-r--r--data/templates/frr/ospf.frr.tmpl4
-rw-r--r--data/templates/frr/policy.frr.tmpl301
-rw-r--r--data/templates/frr/rip.frr.tmpl4
-rw-r--r--data/templates/frr/static.frr.tmpl17
-rw-r--r--data/templates/frr/static_mcast.frr.tmpl20
-rw-r--r--data/templates/frr/vrf.frr.tmpl24
-rw-r--r--data/templates/https/nginx.default.tmpl4
16 files changed, 465 insertions, 64 deletions
diff --git a/data/configd-include.json b/data/configd-include.json
index aabd7232e..f241d0cb6 100644
--- a/data/configd-include.json
+++ b/data/configd-include.json
@@ -21,7 +21,6 @@
"interfaces-pppoe.py",
"interfaces-pseudo-ethernet.py",
"interfaces-tunnel.py",
-"interfaces-erspan.py",
"interfaces-vxlan.py",
"interfaces-wireguard.py",
"interfaces-wireless.py",
@@ -31,6 +30,7 @@
"nat.py",
"nat66.py",
"ntp.py",
+"policy.py",
"policy-local-route.py",
"protocols_bfd.py",
"protocols_bgp.py",
@@ -44,7 +44,6 @@
"protocols_ripng.py",
"protocols_static.py",
"protocols_static_multicast.py",
-"protocols_vrf.py",
"salt-minion.py",
"service_console-server.py",
"service_ids_fastnetmon.py",
diff --git a/data/templates/containers/registry.tmpl b/data/templates/containers/registry.tmpl
new file mode 100644
index 000000000..0347de673
--- /dev/null
+++ b/data/templates/containers/registry.tmpl
@@ -0,0 +1,5 @@
+### 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
new file mode 100644
index 000000000..3a69b7252
--- /dev/null
+++ b/data/templates/containers/storage.tmpl
@@ -0,0 +1,5 @@
+### Autogenerated by /usr/libexec/vyos/conf_mode/containers.py ###
+
+[storage]
+ driver = "vfs"
+ graphroot = "/config/containers/storage"
diff --git a/data/templates/dhcp-client/ipv4.tmpl b/data/templates/dhcp-client/ipv4.tmpl
index 71b429db6..c934b7cdb 100644
--- a/data/templates/dhcp-client/ipv4.tmpl
+++ b/data/templates/dhcp-client/ipv4.tmpl
@@ -20,5 +20,9 @@ interface "{{ ifname }}" {
# 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 %}
+ # Block addresses coming from theses dhcp servers if configured.
+ reject {{ dhcp_options.reject | join(', ') }};
+{% endif %}
}
diff --git a/data/templates/dns-forwarding/recursor.conf.tmpl b/data/templates/dns-forwarding/recursor.conf.tmpl
index 8799718b0..9e0ad5d17 100644
--- a/data/templates/dns-forwarding/recursor.conf.tmpl
+++ b/data/templates/dns-forwarding/recursor.conf.tmpl
@@ -29,5 +29,8 @@ local-address={{ listen_address | join(',') }}
# dnssec
dnssec={{ dnssec }}
+# serve rfc1918 records
+serve-rfc1918={{ 'no' if no_serve_rfc1918 is defined else 'yes' }}
+
forward-zones-file=recursor.forward-zones.conf
diff --git a/data/templates/dynamic-dns/ddclient.conf.tmpl b/data/templates/dynamic-dns/ddclient.conf.tmpl
index 6fbbb50c3..9d379de00 100644
--- a/data/templates/dynamic-dns/ddclient.conf.tmpl
+++ b/data/templates/dynamic-dns/ddclient.conf.tmpl
@@ -18,7 +18,7 @@ use=if, if={{ iface }}
# RFC2136 dynamic DNS configuration for {{ rfc2136 }}, {{ config.zone }}, {{ dns_record }}
server={{ config.server }}
protocol=nsupdate
-password={{ config.keyfile }}
+password={{ config.key }}
ttl={{ config.ttl }}
zone={{ config.zone }}
{{ dns_record }}
diff --git a/data/templates/firewall/nftables-nat66.tmpl b/data/templates/firewall/nftables-nat66.tmpl
index cdaeaad6a..e5c1b1b8d 100644
--- a/data/templates/firewall/nftables-nat66.tmpl
+++ b/data/templates/firewall/nftables-nat66.tmpl
@@ -1,9 +1,13 @@
#!/usr/sbin/nft -f
{% macro nptv6_rule(rule,config, chain) %}
-{% 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 %}
+{% 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 #}
@@ -13,6 +17,8 @@
{% 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 %}
@@ -28,10 +34,12 @@
{% endif %}
{% set interface = " oifname \"" + config.outbound_interface + "\"" if config.outbound_interface is defined else '' %}
{% endif %}
-{% set comment = "NPT-NAT-" + rule %}
-{% if rule.log %}
-{% set base_log = "[NPT-DST-" + rule %}
-{% set log = base_log + "]" %}
+{% 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 #}
diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl
index f7aeaeb9d..0245c875e 100644
--- a/data/templates/frr/bgp.frr.tmpl
+++ b/data/templates/frr/bgp.frr.tmpl
@@ -35,6 +35,16 @@
{% 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_asn in config.local_as %}
neighbor {{ neighbor }} local-as {{ local_asn }} {{ 'no-prepend' if config.local_as[local_asn].no_prepend is defined }}
@@ -90,8 +100,24 @@
{% 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 %}
@@ -104,6 +130,9 @@
{% 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 %}
@@ -123,7 +152,7 @@
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 }}
+ 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 %}
@@ -185,12 +214,25 @@
{% endif %}
{% endmacro %}
!
-router bgp {{ asn }}
+{% if vrf is defined and vrf is not none and route_map is defined and route_map is not none %}
+vrf {{ vrf }}
+ ip protocol bgp route-map {{ route_map }}
+ exit-vrf
+!
+{% elif route_map is defined and route_map is not none %}
+ip protocol bgp route-map {{ route_map }}
+{% endif %}
+!
+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 %}
+{% if parameters is defined and parameters.default is defined and parameters.default.no_ipv4_unicast is defined %}
+{# Option must be set before any neighbor - see https://phabricator.vyos.net/T3463 #}
+ no bgp default ipv4-unicast
+{% endif %}
{# 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 %}
@@ -198,8 +240,24 @@ router bgp {{ asn }}
!
{% 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 %}
@@ -231,11 +289,33 @@ router bgp {{ asn }}
{% 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 %}
+ 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.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 %}
@@ -359,16 +439,11 @@ router bgp {{ asn }}
{% if parameters.default.local_pref is defined and parameters.default.local_pref is not none %}
bgp default local-preference {{ parameters.default.local_pref }}
{% endif %}
-{% if parameters.default.no_ipv4_unicast is defined %}
- no bgp default ipv4-unicast
-{% endif %}
{% endif %}
{% if parameters.deterministic_med is defined %}
bgp deterministic-med
{% endif %}
{% if parameters.distance is defined and parameters.distance is not none %}
- !
- address-family ipv4 unicast
{% 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 %}
@@ -377,11 +452,9 @@ router bgp {{ asn }}
distance {{ parameters.distance.prefix[prefix].distance }} {{ prefix }}
{% endfor %}
{% endif %}
- exit-address-family
- !
{% 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 }}
+ 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
@@ -405,8 +478,5 @@ router bgp {{ asn }}
{% if timers is defined and timers.keepalive is defined and timers.holdtime is defined %}
timers bgp {{ timers.keepalive }} {{ timers.holdtime }}
{% endif %}
-!
-{% if route_map is defined and route_map is not none %}
-ip protocol bgp route-map {{ route_map }}
-{% endif %}
-!
+ end
+! \ No newline at end of file
diff --git a/data/templates/frr/isis.frr.tmpl b/data/templates/frr/isis.frr.tmpl
index 4460ab3b5..c8e11399e 100644
--- a/data/templates/frr/isis.frr.tmpl
+++ b/data/templates/frr/isis.frr.tmpl
@@ -1,5 +1,5 @@
!
-router isis {{ process }}
+router isis VyOS {{ 'vrf ' + vrf if vrf is defined and vrf is not none }}
net {{ net }}
{% if dynamic_hostname is defined %}
hostname dynamic
@@ -133,8 +133,8 @@ router isis {{ process }}
!
{% if interface is defined and interface is not none %}
{% for iface, iface_config in interface.items() %}
-interface {{ iface }}
- ip router isis {{ process }}
+interface {{ iface }} {{ 'vrf ' + vrf if vrf is defined and vrf is not none }}
+ ip router isis VyOS
{% if iface_config.bfd is defined %}
isis bfd
{% endif %}
@@ -173,3 +173,8 @@ interface {{ iface }}
{% endif %}
{% endfor %}
{% endif %}
+!
+{% if route_map is defined and route_map is not none %}
+ip protocol isis route-map {{ route_map }}
+{% endif %}
+!
diff --git a/data/templates/frr/ospf.frr.tmpl b/data/templates/frr/ospf.frr.tmpl
index 140b6b406..a47c64c89 100644
--- a/data/templates/frr/ospf.frr.tmpl
+++ b/data/templates/frr/ospf.frr.tmpl
@@ -1,7 +1,7 @@
!
{% if interface is defined and interface is not none %}
{% for iface, iface_config in interface.items() %}
-interface {{ iface }}
+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 }}
@@ -50,7 +50,7 @@ interface {{ iface }}
{% endfor %}
{% endif %}
!
-router ospf
+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 %}
diff --git a/data/templates/frr/policy.frr.tmpl b/data/templates/frr/policy.frr.tmpl
new file mode 100644
index 000000000..881afa21f
--- /dev/null
+++ b/data/templates/frr/policy.frr.tmpl
@@ -0,0 +1,301 @@
+!
+{% 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.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_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_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.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.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.frr.tmpl b/data/templates/frr/rip.frr.tmpl
index bc92bddf9..cabc236f0 100644
--- a/data/templates/frr/rip.frr.tmpl
+++ b/data/templates/frr/rip.frr.tmpl
@@ -90,3 +90,7 @@ router rip
{% 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/static.frr.tmpl b/data/templates/frr/static.frr.tmpl
index bb0ec80a5..db59a44c2 100644
--- a/data/templates/frr/static.frr.tmpl
+++ b/data/templates/frr/static.frr.tmpl
@@ -1,18 +1,29 @@
{% 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_config) }}
+{{ static_routes(ip_prefix, prefix, prefix_config) }}
{%- 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_config) }}
+{{ 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 %}
diff --git a/data/templates/frr/static_mcast.frr.tmpl b/data/templates/frr/static_mcast.frr.tmpl
index 38635af32..4f114109a 100644
--- a/data/templates/frr/static_mcast.frr.tmpl
+++ b/data/templates/frr/static_mcast.frr.tmpl
@@ -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/vrf.frr.tmpl b/data/templates/frr/vrf.frr.tmpl
index 8d3d8e9dd..299c9719e 100644
--- a/data/templates/frr/vrf.frr.tmpl
+++ b/data/templates/frr/vrf.frr.tmpl
@@ -1,25 +1,9 @@
-{% from 'frr/static_routes_macro.j2' import static_routes %}
-!
-{% if vrf is defined and vrf is not none %}
-{% for vrf_name, vrf_config in vrf.items() %}
-vrf {{ vrf_name }}
+{% 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 %}
-{% if vrf_config.static is defined and vrf_config.static is not none %}
-{# IPv4 routes #}
-{% if vrf_config.static.route is defined and vrf_config.static.route is not none %}
-{% for prefix, prefix_config in vrf_config.static.route.items() %}
- {{ static_routes('ip', prefix, prefix_config) }}
-{%- endfor -%}
-{% endif %}
-{# IPv6 routes #}
-{% if vrf_config.static.route6 is defined and vrf_config.static.route6 is not none %}
-{% for prefix, prefix_config in vrf_config.static.route6.items() %}
- {{ static_routes('ipv6', prefix, prefix_config) }}
-{%- endfor -%}
-{% endif %}
-{% endif %}
+ exit-vrf
{% endfor %}
{% endif %}
-!
diff --git a/data/templates/https/nginx.default.tmpl b/data/templates/https/nginx.default.tmpl
index 81f8b3b8c..916764410 100644
--- a/data/templates/https/nginx.default.tmpl
+++ b/data/templates/https/nginx.default.tmpl
@@ -40,9 +40,11 @@ server {
{% endif %}
# proxy settings for HTTP API, if enabled; 503, if not
- location ~ /(retrieve|configure|config-file|image|generate|show) {
+ location ~ /(retrieve|configure|config-file|image|generate|show|docs|openapi.json|redoc) {
{% if server.api %}
proxy_pass http://localhost:{{ server.api.port }};
+ 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 %}