summaryrefslogtreecommitdiff
path: root/data
diff options
context:
space:
mode:
Diffstat (limited to 'data')
-rw-r--r--data/configd-include.json19
-rw-r--r--data/templates/accel-ppp/chap-secrets.config_dict.j2 (renamed from data/templates/accel-ppp/chap-secrets.config_dict.tmpl)14
-rw-r--r--data/templates/accel-ppp/chap-secrets.ipoe.j2 (renamed from data/templates/accel-ppp/chap-secrets.ipoe.tmpl)22
-rw-r--r--data/templates/accel-ppp/chap-secrets.j2 (renamed from data/templates/accel-ppp/chap-secrets.tmpl)10
-rw-r--r--data/templates/accel-ppp/config_chap_secrets_radius.j230
-rw-r--r--data/templates/accel-ppp/config_ip_pool.j218
-rw-r--r--data/templates/accel-ppp/config_ipv6_pool.j220
-rw-r--r--data/templates/accel-ppp/config_modules_auth_mode.j24
-rw-r--r--data/templates/accel-ppp/config_modules_auth_protocols.j28
-rw-r--r--data/templates/accel-ppp/config_modules_ipv6.j22
-rw-r--r--data/templates/accel-ppp/config_name_server.j212
-rw-r--r--data/templates/accel-ppp/config_shaper_radius.j211
-rw-r--r--data/templates/accel-ppp/ipoe.config.j2142
-rw-r--r--data/templates/accel-ppp/ipoe.config.tmpl116
-rw-r--r--data/templates/accel-ppp/l2tp.config.j2 (renamed from data/templates/accel-ppp/l2tp.config.tmpl)69
-rw-r--r--data/templates/accel-ppp/pppoe.config.j2172
-rw-r--r--data/templates/accel-ppp/pppoe.config.tmpl174
-rw-r--r--data/templates/accel-ppp/pptp.config.j2 (renamed from data/templates/accel-ppp/pptp.config.tmpl)32
-rw-r--r--data/templates/accel-ppp/sstp.config.j2 (renamed from data/templates/accel-ppp/sstp.config.tmpl)2
-rw-r--r--data/templates/bcast-relay/udp-broadcast-relay.j25
-rw-r--r--data/templates/bcast-relay/udp-broadcast-relay.tmpl7
-rw-r--r--data/templates/conntrack/nftables-ct.j248
-rw-r--r--data/templates/conntrack/sysctl.conf.j2 (renamed from data/templates/conntrack/sysctl.conf.tmpl)2
-rw-r--r--data/templates/conntrack/vyos_nf_conntrack.conf.j2 (renamed from data/templates/conntrack/vyos_nf_conntrack.conf.tmpl)0
-rw-r--r--data/templates/conntrackd/conntrackd.conf.j2 (renamed from data/templates/conntrackd/conntrackd.conf.tmpl)58
-rw-r--r--data/templates/conntrackd/conntrackd.op-mode.j213
-rw-r--r--data/templates/conntrackd/conntrackd.op-mode.tmpl13
-rw-r--r--data/templates/conserver/conserver.conf.j2 (renamed from data/templates/conserver/conserver.conf.tmpl)2
-rw-r--r--data/templates/conserver/dropbear@.service.j2 (renamed from data/templates/conserver/dropbear@.service.tmpl)0
-rw-r--r--data/templates/container/registries.conf.j227
-rw-r--r--data/templates/container/storage.conf.j24
-rw-r--r--data/templates/containers/registry.tmpl5
-rw-r--r--data/templates/containers/storage.tmpl5
-rw-r--r--data/templates/dhcp-client/daemon-options.j24
-rw-r--r--data/templates/dhcp-client/daemon-options.tmpl4
-rw-r--r--data/templates/dhcp-client/ipv4.j2 (renamed from data/templates/dhcp-client/ipv4.tmpl)18
-rw-r--r--data/templates/dhcp-client/ipv6.j260
-rw-r--r--data/templates/dhcp-client/ipv6.tmpl60
-rw-r--r--data/templates/dhcp-relay/dhcrelay.conf.j2 (renamed from data/templates/dhcp-relay/dhcrelay.conf.tmpl)2
-rw-r--r--data/templates/dhcp-relay/dhcrelay6.conf.j221
-rw-r--r--data/templates/dhcp-relay/dhcrelay6.conf.tmpl21
-rw-r--r--data/templates/dhcp-server/dhcpd.conf.j2246
-rw-r--r--data/templates/dhcp-server/dhcpd.conf.tmpl231
-rw-r--r--data/templates/dhcp-server/dhcpdv6.conf.j2132
-rw-r--r--data/templates/dhcp-server/dhcpdv6.conf.tmpl124
-rw-r--r--data/templates/dns-forwarding/recursor.conf.j2 (renamed from data/templates/dns-forwarding/recursor.conf.tmpl)11
-rw-r--r--data/templates/dns-forwarding/recursor.conf.lua.j2 (renamed from data/templates/dns-forwarding/recursor.conf.lua.tmpl)0
-rw-r--r--data/templates/dns-forwarding/recursor.forward-zones.conf.j2 (renamed from data/templates/dns-forwarding/recursor.forward-zones.conf.tmpl)19
-rw-r--r--data/templates/dns-forwarding/recursor.vyos-hostsd.conf.lua.j230
-rw-r--r--data/templates/dns-forwarding/recursor.vyos-hostsd.conf.lua.tmpl24
-rw-r--r--data/templates/dns-forwarding/recursor.zone.conf.j26
-rw-r--r--data/templates/dynamic-dns/ddclient.conf.j251
-rw-r--r--data/templates/dynamic-dns/ddclient.conf.tmpl49
-rw-r--r--data/templates/ethernet/wpa_supplicant.conf.j2 (renamed from data/templates/ethernet/wpa_supplicant.conf.tmpl)10
-rw-r--r--data/templates/firewall/nftables-defines.j232
-rw-r--r--data/templates/firewall/nftables-nat.j2182
-rw-r--r--data/templates/firewall/nftables-nat.tmpl181
-rw-r--r--data/templates/firewall/nftables-nat66.j2102
-rw-r--r--data/templates/firewall/nftables-nat66.tmpl102
-rw-r--r--data/templates/firewall/nftables-policy.j255
-rw-r--r--data/templates/firewall/nftables-vrf-zones.j2 (renamed from data/templates/firewall/nftables-vrf-zones.tmpl)0
-rw-r--r--data/templates/firewall/nftables.j2274
-rw-r--r--data/templates/firewall/upnpd.conf.j2172
-rw-r--r--data/templates/frr/bfdd.frr.j258
-rw-r--r--data/templates/frr/bfdd.frr.tmpl44
-rw-r--r--data/templates/frr/bgpd.frr.j2533
-rw-r--r--data/templates/frr/bgpd.frr.tmpl528
-rw-r--r--data/templates/frr/igmp.frr.j241
-rw-r--r--data/templates/frr/igmp.frr.tmpl41
-rw-r--r--data/templates/frr/isisd.frr.j2197
-rw-r--r--data/templates/frr/isisd.frr.tmpl198
-rw-r--r--data/templates/frr/ldpd.frr.j2149
-rw-r--r--data/templates/frr/ldpd.frr.tmpl187
-rw-r--r--data/templates/frr/ospf6d.frr.j295
-rw-r--r--data/templates/frr/ospf6d.frr.tmpl92
-rw-r--r--data/templates/frr/ospfd.frr.j2189
-rw-r--r--data/templates/frr/ospfd.frr.tmpl192
-rw-r--r--data/templates/frr/pimd.frr.j2 (renamed from data/templates/frr/pimd.frr.tmpl)16
-rw-r--r--data/templates/frr/policy.frr.j2331
-rw-r--r--data/templates/frr/policy.frr.tmpl322
-rw-r--r--data/templates/frr/rip_ripng.frr.j242
-rw-r--r--data/templates/frr/ripd.frr.j292
-rw-r--r--data/templates/frr/ripd.frr.tmpl96
-rw-r--r--data/templates/frr/ripngd.frr.j257
-rw-r--r--data/templates/frr/ripngd.frr.tmpl60
-rw-r--r--data/templates/frr/rpki.frr.j2 (renamed from data/templates/frr/rpki.frr.tmpl)17
-rw-r--r--data/templates/frr/static_mcast.frr.j2 (renamed from data/templates/frr/static_mcast.frr.tmpl)20
-rw-r--r--data/templates/frr/static_routes_macro.j229
-rw-r--r--data/templates/frr/staticd.frr.j264
-rw-r--r--data/templates/frr/staticd.frr.tmpl58
-rw-r--r--data/templates/frr/vrf-vni.frr.j29
-rw-r--r--data/templates/frr/vrf-vni.frr.tmpl9
-rw-r--r--data/templates/frr/vrf.route-map.frr.j210
-rw-r--r--data/templates/frr/vrf.route-map.frr.tmpl10
-rw-r--r--data/templates/getty/serial-getty.service.j2 (renamed from data/templates/getty/serial-getty.service.tmpl)0
-rw-r--r--data/templates/high-availability/keepalived.conf.j2169
-rw-r--r--data/templates/https/nginx.default.j2 (renamed from data/templates/https/nginx.default.tmpl)50
-rw-r--r--data/templates/https/override.conf.j215
-rw-r--r--data/templates/https/vyos-http-api.service.j222
-rw-r--r--data/templates/ids/fastnetmon.j2 (renamed from data/templates/ids/fastnetmon.tmpl)38
-rw-r--r--data/templates/ids/fastnetmon_networks_list.j27
-rw-r--r--data/templates/ids/fastnetmon_networks_list.tmpl7
-rw-r--r--data/templates/igmp-proxy/igmpproxy.conf.j2 (renamed from data/templates/igmp-proxy/igmpproxy.conf.tmpl)30
-rw-r--r--data/templates/ipsec/charon.j2 (renamed from data/templates/ipsec/charon.tmpl)12
-rw-r--r--data/templates/ipsec/charon/dhcp.conf.j2 (renamed from data/templates/ipsec/charon/dhcp.conf.tmpl)8
-rw-r--r--data/templates/ipsec/charon/eap-radius.conf.j2 (renamed from data/templates/ipsec/charon/eap-radius.conf.tmpl)16
-rw-r--r--data/templates/ipsec/interfaces_use.conf.j2 (renamed from data/templates/ipsec/interfaces_use.conf.tmpl)4
-rw-r--r--data/templates/ipsec/ios_profile.j2 (renamed from data/templates/ipsec/ios_profile.tmpl)2
-rw-r--r--data/templates/ipsec/ipsec.conf.j219
-rw-r--r--data/templates/ipsec/ipsec.conf.tmpl18
-rw-r--r--data/templates/ipsec/ipsec.secrets.j2 (renamed from data/templates/ipsec/ipsec.secrets.tmpl)4
-rw-r--r--data/templates/ipsec/swanctl.conf.j2131
-rw-r--r--data/templates/ipsec/swanctl.conf.tmpl131
-rw-r--r--data/templates/ipsec/swanctl/l2tp.j2 (renamed from data/templates/ipsec/swanctl/l2tp.tmpl)8
-rw-r--r--data/templates/ipsec/swanctl/peer.j2166
-rw-r--r--data/templates/ipsec/swanctl/peer.tmpl142
-rw-r--r--data/templates/ipsec/swanctl/profile.j2 (renamed from data/templates/ipsec/swanctl/profile.tmpl)26
-rw-r--r--data/templates/ipsec/swanctl/remote_access.j2 (renamed from data/templates/ipsec/swanctl/remote_access.tmpl)39
-rw-r--r--data/templates/ipsec/windows_profile.j2 (renamed from data/templates/ipsec/windows_profile.tmpl)0
-rw-r--r--data/templates/lcd/LCDd.conf.j2 (renamed from data/templates/lcd/LCDd.conf.tmpl)20
-rw-r--r--data/templates/lcd/lcdproc.conf.j2 (renamed from data/templates/lcd/lcdproc.conf.tmpl)0
-rw-r--r--data/templates/lldp/lldpd.j22
-rw-r--r--data/templates/lldp/lldpd.tmpl3
-rw-r--r--data/templates/lldp/vyos.conf.j225
-rw-r--r--data/templates/lldp/vyos.conf.tmpl20
-rw-r--r--data/templates/login/authorized_keys.j29
-rw-r--r--data/templates/login/authorized_keys.tmpl9
-rw-r--r--data/templates/login/pam_radius_auth.conf.j236
-rw-r--r--data/templates/login/pam_radius_auth.conf.tmpl36
-rw-r--r--data/templates/logs/logrotate/vyos-atop.j220
-rw-r--r--data/templates/logs/logrotate/vyos-rsyslog.j213
-rw-r--r--data/templates/macsec/wpa_supplicant.conf.j2 (renamed from data/templates/macsec/wpa_supplicant.conf.tmpl)10
-rw-r--r--data/templates/mdns-repeater/avahi-daemon.j2 (renamed from data/templates/mdns-repeater/avahi-daemon.tmpl)0
-rw-r--r--data/templates/monitoring/override.conf.j27
-rw-r--r--data/templates/monitoring/syslog_telegraf.j25
-rw-r--r--data/templates/monitoring/systemd_vyos_telegraf_service.j216
-rw-r--r--data/templates/monitoring/telegraf.j2122
-rw-r--r--data/templates/ndppd/ndppd.conf.j244
-rw-r--r--data/templates/ndppd/ndppd.conf.tmpl44
-rw-r--r--data/templates/netflow/uacctd.conf.tmpl72
-rw-r--r--data/templates/nhrp/opennhrp.conf.j242
-rw-r--r--data/templates/nhrp/opennhrp.conf.tmpl41
-rw-r--r--data/templates/ntp/ntpd.conf.j2 (renamed from data/templates/ntp/ntpd.conf.tmpl)29
-rw-r--r--data/templates/ntp/override.conf.j214
-rw-r--r--data/templates/ntp/override.conf.tmpl14
-rw-r--r--data/templates/ocserv/ocserv_config.j2 (renamed from data/templates/ocserv/ocserv_config.tmpl)45
-rw-r--r--data/templates/ocserv/ocserv_otp_usr.j28
-rw-r--r--data/templates/ocserv/ocserv_passwd.j28
-rw-r--r--data/templates/ocserv/ocserv_passwd.tmpl6
-rw-r--r--data/templates/ocserv/radius_conf.j2 (renamed from data/templates/ocserv/radius_conf.tmpl)12
-rw-r--r--data/templates/ocserv/radius_servers.j27
-rw-r--r--data/templates/ocserv/radius_servers.tmpl7
-rw-r--r--data/templates/openvpn/auth.pw.j2 (renamed from data/templates/openvpn/auth.pw.tmpl)2
-rw-r--r--data/templates/openvpn/client.conf.j2 (renamed from data/templates/openvpn/client.conf.tmpl)30
-rw-r--r--data/templates/openvpn/server.conf.j2224
-rw-r--r--data/templates/openvpn/server.conf.tmpl226
-rw-r--r--data/templates/openvpn/service-override.conf.j221
-rw-r--r--data/templates/openvpn/service-override.conf.tmpl20
-rw-r--r--data/templates/pmacct/override.conf.j217
-rw-r--r--data/templates/pmacct/uacctd.conf.j280
-rw-r--r--data/templates/pppoe/ip-down.script.tmpl38
-rw-r--r--data/templates/pppoe/ip-pre-up.script.tmpl18
-rw-r--r--data/templates/pppoe/ip-up.script.tmpl49
-rw-r--r--data/templates/pppoe/ipv6-up.script.tmpl46
-rw-r--r--data/templates/pppoe/peer.j2 (renamed from data/templates/pppoe/peer.tmpl)32
-rw-r--r--data/templates/router-advert/radvd.conf.j266
-rw-r--r--data/templates/router-advert/radvd.conf.tmpl66
-rw-r--r--data/templates/salt-minion/minion.j2 (renamed from data/templates/salt-minion/minion.tmpl)18
-rw-r--r--data/templates/snmp/etc.snmp.conf.j2 (renamed from data/templates/snmp/etc.snmp.conf.tmpl)2
-rw-r--r--data/templates/snmp/etc.snmpd.conf.j2182
-rw-r--r--data/templates/snmp/etc.snmpd.conf.tmpl119
-rw-r--r--data/templates/snmp/override.conf.j214
-rw-r--r--data/templates/snmp/override.conf.tmpl14
-rw-r--r--data/templates/snmp/usr.snmpd.conf.j28
-rw-r--r--data/templates/snmp/usr.snmpd.conf.tmpl6
-rw-r--r--data/templates/snmp/var.snmpd.conf.j216
-rw-r--r--data/templates/snmp/var.snmpd.conf.tmpl14
-rw-r--r--data/templates/squid/sg_acl.conf.j2 (renamed from data/templates/squid/sg_acl.conf.tmpl)0
-rw-r--r--data/templates/squid/squid.conf.j2111
-rw-r--r--data/templates/squid/squid.conf.tmpl113
-rw-r--r--data/templates/squid/squidGuard.conf.j2124
-rw-r--r--data/templates/squid/squidGuard.conf.tmpl124
-rw-r--r--data/templates/ssh/override.conf.j213
-rw-r--r--data/templates/ssh/override.conf.tmpl13
-rw-r--r--data/templates/ssh/sshd_config.j2 (renamed from data/templates/ssh/sshd_config.tmpl)54
-rw-r--r--data/templates/ssh/sshguard_config.j227
-rw-r--r--data/templates/ssh/sshguard_whitelist.j27
-rw-r--r--data/templates/syslog/logrotate.j211
-rw-r--r--data/templates/syslog/logrotate.tmpl12
-rw-r--r--data/templates/syslog/rsyslog.conf.j254
-rw-r--r--data/templates/syslog/rsyslog.conf.tmpl48
-rw-r--r--data/templates/system/curlrc.j26
-rw-r--r--data/templates/system/curlrc.tmpl8
-rw-r--r--data/templates/system/proxy.j27
-rw-r--r--data/templates/system/ssh_config.j23
-rw-r--r--data/templates/system/ssh_config.tmpl3
-rw-r--r--data/templates/system/sysctl.conf.j27
-rw-r--r--data/templates/system/sysctl.conf.tmpl7
-rw-r--r--data/templates/tftp-server/default.j28
-rw-r--r--data/templates/tftp-server/default.tmpl2
-rw-r--r--data/templates/vrf/vrf.conf.j29
-rw-r--r--data/templates/vrf/vrf.conf.tmpl9
-rw-r--r--data/templates/vrrp/keepalived.conf.tmpl106
-rw-r--r--data/templates/vyos-hostsd/hosts.j2 (renamed from data/templates/vyos-hostsd/hosts.tmpl)15
-rw-r--r--data/templates/vyos-hostsd/resolv.conf.j2 (renamed from data/templates/vyos-hostsd/resolv.conf.tmpl)14
-rw-r--r--data/templates/wifi/cfg80211.conf.tmpl1
-rw-r--r--data/templates/wifi/crda.tmpl1
-rw-r--r--data/templates/wifi/hostapd.conf.j2 (renamed from data/templates/wifi/hostapd.conf.tmpl)342
-rw-r--r--data/templates/wifi/wpa_supplicant.conf.j2 (renamed from data/templates/wifi/wpa_supplicant.conf.tmpl)8
-rw-r--r--data/templates/zone_policy/nftables.j2113
210 files changed, 6338 insertions, 5255 deletions
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 %}