summaryrefslogtreecommitdiff
path: root/data
diff options
context:
space:
mode:
Diffstat (limited to 'data')
-rw-r--r--data/configd-include.json62
-rw-r--r--data/templates/accel-ppp/ipoe.config.tmpl2
-rw-r--r--data/templates/accel-ppp/l2tp.config.tmpl2
-rw-r--r--data/templates/accel-ppp/pppoe.config.tmpl2
-rw-r--r--data/templates/accel-ppp/pptp.config.tmpl2
-rw-r--r--data/templates/accel-ppp/sstp.config.tmpl2
-rw-r--r--data/templates/dhcp-client/daemon-options.tmpl5
-rw-r--r--data/templates/dhcp-client/ipv4.tmpl24
-rw-r--r--data/templates/dhcp-client/ipv6.tmpl77
-rw-r--r--data/templates/dhcp-client/ipv6_new.tmpl47
-rw-r--r--data/templates/frr/bgp.frr.tmpl968
-rw-r--r--data/templates/frr/ldpd.frr.tmpl12
-rw-r--r--data/templates/https/nginx.default.tmpl10
-rw-r--r--data/templates/lcd/LCDd.conf.tmpl132
-rw-r--r--data/templates/lcd/lcdproc.conf.tmpl60
-rw-r--r--data/templates/mdns-repeater/mdns-repeater.tmpl2
-rw-r--r--data/templates/ntp/ntp.conf.tmpl16
-rw-r--r--data/templates/ocserv/ocserv_config.tmpl82
-rw-r--r--data/templates/ocserv/ocserv_passwd.tmpl6
-rw-r--r--data/templates/ocserv/radius_conf.tmpl22
-rw-r--r--data/templates/ocserv/radius_servers.tmpl7
-rw-r--r--data/templates/pppoe/ip-down.script.tmpl2
-rw-r--r--data/templates/pppoe/ipv6-up.script.tmpl3
-rw-r--r--data/templates/router-advert/radvd.conf.tmpl72
-rw-r--r--data/templates/ssh/override.conf.tmpl3
-rw-r--r--data/templates/ssh/sshd_config.tmpl16
-rw-r--r--data/templates/system/curlrc.tmpl16
-rw-r--r--data/templates/system/ssh_config.tmpl3
-rw-r--r--data/templates/wifi/cfg80211.conf.tmpl4
-rw-r--r--data/templates/wifi/crda.tmpl4
-rw-r--r--data/templates/wifi/hostapd.conf.tmpl408
-rw-r--r--data/templates/wifi/wpa_supplicant.conf.tmpl4
-rw-r--r--data/vyos-configd-env-set2
-rw-r--r--data/vyos-configd-env-unset2
34 files changed, 1665 insertions, 416 deletions
diff --git a/data/configd-include.json b/data/configd-include.json
new file mode 100644
index 000000000..0c75657e0
--- /dev/null
+++ b/data/configd-include.json
@@ -0,0 +1,62 @@
+[
+"bcast_relay.py",
+"dhcp_relay.py",
+"dhcpv6_relay.py",
+"dynamic_dns.py",
+"firewall_options.py",
+"host_name.py",
+"http-api.py",
+"https.py",
+"igmp_proxy.py",
+"intel_qat.py",
+"interfaces-bonding.py",
+"interfaces-bridge.py",
+"interfaces-dummy.py",
+"interfaces-ethernet.py",
+"interfaces-geneve.py",
+"interfaces-l2tpv3.py",
+"interfaces-loopback.py",
+"interfaces-macsec.py",
+"interfaces-openvpn.py",
+"interfaces-pppoe.py",
+"interfaces-pseudo-ethernet.py",
+"interfaces-tunnel.py",
+"interfaces-vxlan.py",
+"interfaces-wireguard.py",
+"interfaces-wireless.py",
+"interfaces-wirelessmodem.py",
+"ipsec-settings.py",
+"lldp.py",
+"nat.py",
+"ntp.py",
+"protocols_igmp.py",
+"protocols_mpls.py",
+"protocols_pim.py",
+"protocols_rip.py",
+"protocols_static_multicast.py",
+"salt-minion.py",
+"service_console-server.py",
+"service_ids_fastnetmon.py",
+"service_ipoe-server.py",
+"service_mdns-repeater.py",
+"service_pppoe-server.py",
+"service_router-advert.py",
+"ssh.py",
+"system-ip.py",
+"system-ipv6.py",
+"system-login-banner.py",
+"system-options.py",
+"system-syslog.py",
+"system-timezone.py",
+"system-wifi-regdom.py",
+"system_console.py",
+"system_lcd.py",
+"task_scheduler.py",
+"tftp_server.py",
+"vpn_l2tp.py",
+"vpn_pptp.py",
+"vpn_sstp.py",
+"vrf.py",
+"vrrp.py",
+"vyos_cert.py"
+] \ No newline at end of file
diff --git a/data/templates/accel-ppp/ipoe.config.tmpl b/data/templates/accel-ppp/ipoe.config.tmpl
index 84de5bf51..fca520efa 100644
--- a/data/templates/accel-ppp/ipoe.config.tmpl
+++ b/data/templates/accel-ppp/ipoe.config.tmpl
@@ -77,7 +77,7 @@ chap-secrets={{ chap_secrets_file }}
[radius]
verbose=1
{% for r in radius_server %}
-server={{ r.server }},{{ r.key }},auth-port={{ r.port }},req-limit=0,fail-time={{ r.fail_time }}
+server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }}
{% endfor -%}
acct-timeout={{ radius_acct_tmo }}
diff --git a/data/templates/accel-ppp/l2tp.config.tmpl b/data/templates/accel-ppp/l2tp.config.tmpl
index b0ef17525..b9131684d 100644
--- a/data/templates/accel-ppp/l2tp.config.tmpl
+++ b/data/templates/accel-ppp/l2tp.config.tmpl
@@ -83,7 +83,7 @@ chap-secrets={{ chap_secrets_file }}
[radius]
verbose=1
{% for r in radius_server %}
-server={{ r.server }},{{ r.key }},auth-port={{ r.port }},req-limit=0,fail-time={{ r.fail_time }}
+server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }}
{% endfor -%}
acct-timeout={{ radius_acct_tmo }}
diff --git a/data/templates/accel-ppp/pppoe.config.tmpl b/data/templates/accel-ppp/pppoe.config.tmpl
index 370ca7946..5ad628fde 100644
--- a/data/templates/accel-ppp/pppoe.config.tmpl
+++ b/data/templates/accel-ppp/pppoe.config.tmpl
@@ -93,7 +93,7 @@ chap-secrets={{ chap_secrets_file }}
[radius]
verbose=1
{% for r in radius_server %}
-server={{ r.server }},{{ r.key }},auth-port={{ r.port }},req-limit=0,fail-time={{ r.fail_time }}
+server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }}
{% endfor -%}
acct-timeout={{ radius_acct_tmo }}
diff --git a/data/templates/accel-ppp/pptp.config.tmpl b/data/templates/accel-ppp/pptp.config.tmpl
index 0bbfc13c5..e0f2c6da9 100644
--- a/data/templates/accel-ppp/pptp.config.tmpl
+++ b/data/templates/accel-ppp/pptp.config.tmpl
@@ -66,7 +66,7 @@ chap-secrets={{ chap_secrets_file }}
[radius]
verbose=1
{% for r in radius_server %}
-server={{ r.server }},{{ r.key }},auth-port={{ r.port }},req-limit=0,fail-time={{ r.fail_time }}
+server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }}
{% endfor -%}
acct-timeout={{ radius_acct_tmo }}
diff --git a/data/templates/accel-ppp/sstp.config.tmpl b/data/templates/accel-ppp/sstp.config.tmpl
index 2c8c00023..c9e4a1d7d 100644
--- a/data/templates/accel-ppp/sstp.config.tmpl
+++ b/data/templates/accel-ppp/sstp.config.tmpl
@@ -69,7 +69,7 @@ chap-secrets={{ chap_secrets_file }}
[radius]
verbose=1
{% for r in radius_server %}
-server={{ r.server }},{{ r.key }},auth-port={{ r.port }},req-limit=0,fail-time={{ r.fail_time }}
+server={{ r.server }},{{ r.key }},auth-port={{ r.port }},acct-port={{ r.acct_port }},req-limit=0,fail-time={{ r.fail_time }}
{% endfor -%}
acct-timeout={{ radius_acct_tmo }}
diff --git a/data/templates/dhcp-client/daemon-options.tmpl b/data/templates/dhcp-client/daemon-options.tmpl
index 12786b777..290aefa49 100644
--- a/data/templates/dhcp-client/daemon-options.tmpl
+++ b/data/templates/dhcp-client/daemon-options.tmpl
@@ -1 +1,4 @@
-DHCLIENT_OPTS="-nw -cf {{ conf_file }} -pf {{ pid_file }} -lf {{ lease_file }} {{ '-S' if dhcpv6_prm_only }} {{ '-T' if dhcpv6_temporary }} {{ ifname }}"
+### 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 {{ifname}}"
+
diff --git a/data/templates/dhcp-client/ipv4.tmpl b/data/templates/dhcp-client/ipv4.tmpl
index ab772b5f6..8a44a9761 100644
--- a/data/templates/dhcp-client/ipv4.tmpl
+++ b/data/templates/dhcp-client/ipv4.tmpl
@@ -1,17 +1,19 @@
-# generated by dhcp.py
+### Autogenerated by interface.py ###
+
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
timeout 60;
retry 300;
interface "{{ ifname }}" {
- send host-name "{{ hostname }}";
- {% if client_id -%}
- send dhcp-client-identifier "{{ client_id }}";
- {% endif -%}
- {% if vendor_class_id -%}
- send vendor-class-identifier "{{ vendor_class_id }}";
- {% endif -%}
- request subnet-mask, broadcast-address, routers, domain-name-servers,
- rfc3442-classless-static-routes, domain-name, interface-mtu;
- require subnet-mask;
+ send host-name "{{ dhcp_options.host_name }}";
+{% if dhcp_options.client_id is defined and dhcp_options.client_id is not none %}
+ send dhcp-client-identifier "{{ dhcp_options.client_id }}";
+{% endif %}
+{% if dhcp_options.vendor_class_id is defined and dhcp_options.vendor_class_id is not none %}
+ send vendor-class-identifier "{{ dhcp_options.vendor_class_id }}";
+{% endif %}
+ request subnet-mask, broadcast-address, routers, domain-name-servers,
+ rfc3442-classless-static-routes, domain-name, interface-mtu;
+ require subnet-mask;
}
+
diff --git a/data/templates/dhcp-client/ipv6.tmpl b/data/templates/dhcp-client/ipv6.tmpl
index 490f14726..68f668117 100644
--- a/data/templates/dhcp-client/ipv6.tmpl
+++ b/data/templates/dhcp-client/ipv6.tmpl
@@ -1,44 +1,57 @@
-# generated by dhcp.py
-# man https://www.unix.com/man-page/debian/5/dhcp6c.conf/
+### Autogenerated by interface.py ###
+# man https://www.unix.com/man-page/debian/5/dhcp6c.conf/
interface {{ ifname }} {
+{% if address is defined and 'dhcpv6' in address %}
request domain-name-servers;
request domain-name;
-{% if dhcpv6_prm_only %}
+{% if dhcpv6_options is defined and dhcpv6_options.parameters_only is defined %}
information-only;
-{% endif %}
-{% if not dhcpv6_temporary %}
- send ia-na 1; # non-temporary address
-{% endif %}
-{% if dhcpv6_pd_interfaces %}
- send ia-pd 2; # prefix delegation
-{% endif %}
+{% 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 not dhcpv6_temporary %}
-id-assoc na 1 {
- # Identity association NA
+{% 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 %}
+{% endif %}
-{% if dhcpv6_pd_interfaces %}
-id-assoc pd 2 {
-{% if dhcpv6_pd_length %}
- prefix ::/{{ dhcpv6_pd_length }} infinity;
-{% endif %}
-{% for intf in dhcpv6_pd_interfaces %}
- prefix-interface {{ intf.ifname }} {
-{% if intf.sla_id %}
- sla-id {{ intf.sla_id }};
-{% endif %}
-{% if intf.sla_len %}
- sla-len {{ intf.sla_len }};
-{% endif %}
-{% if intf.if_id %}
- ifid {{ intf.if_id }};
-{% 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 %}
};
-{% endfor %}
+{% set count.value = count.value + 1 %}
+{% endfor %}
};
-{% endif %}
+{% endfor %}
+{% endif %}
diff --git a/data/templates/dhcp-client/ipv6_new.tmpl b/data/templates/dhcp-client/ipv6_new.tmpl
deleted file mode 100644
index 112431c5f..000000000
--- a/data/templates/dhcp-client/ipv6_new.tmpl
+++ /dev/null
@@ -1,47 +0,0 @@
-# generated by dhcp.py
-# man https://www.unix.com/man-page/debian/5/dhcp6c.conf/
-
-interface {{ ifname }} {
- request domain-name-servers;
- request domain-name;
-{% if dhcpv6_options is defined %}
-{% if dhcpv6_options.parameters_only is defined %}
- information-only;
-{% endif %}
-{% if dhcpv6_options.temporary is not defined %}
- send ia-na 1; # non-temporary address
-{% endif %}
-{% if dhcpv6_options.prefix_delegation is defined %}
- send ia-pd 2; # prefix delegation
-{% endif %}
-{% endif %}
-};
-
-{% if dhcpv6_options is defined %}
-{% if dhcpv6_options.temporary is not defined %}
-id-assoc na 1 {
- # Identity association NA
-};
-{% endif %}
-
-{% if dhcpv6_options.prefix_delegation is defined %}
-id-assoc pd 2 {
-{% if dhcpv6_options.prefix_delegation.length is defined %}
- prefix ::/{{ dhcpv6_options.prefix_delegation.length }} infinity;
-{% endif %}
-{% for interface in dhcpv6_options.prefix_delegation.interface %}
- prefix-interface {{ interface }} {
-{% if dhcpv6_options.prefix_delegation.interface[interface].sla_id is defined %}
- sla-id {{ dhcpv6_options.prefix_delegation.interface[interface].sla_id }};
-{% endif %}
-{% if dhcpv6_options.prefix_delegation.interface[interface].sla_len is defined %}
- sla-len {{ dhcpv6_options.prefix_delegation.interface[interface].sla_len }};
-{% endif %}
-{% if dhcpv6_options.prefix_delegation.interface[interface].address is defined %}
- ifid {{ dhcpv6_options.prefix_delegation.interface[interface].address }};
-{% endif %}
- };
-{% endfor %}
-};
-{% endif %}
-{% endif %}
diff --git a/data/templates/frr/bgp.frr.tmpl b/data/templates/frr/bgp.frr.tmpl
index cd6f31c93..d011a1e85 100644
--- a/data/templates/frr/bgp.frr.tmpl
+++ b/data/templates/frr/bgp.frr.tmpl
@@ -1 +1,967 @@
-!
+{% set conf_bgp = nbgp -%}
+{% for asn in nbgp -%}
+!
+router bgp {{ asn }}
+ no bgp default ipv4-unicast
+
+{#- set 'conf_bgp[asn].parameters' as bgp_params #}
+{%- set bgp_params = conf_bgp[asn].parameters %}
+{%- set bgp_afi = conf_bgp[asn].address_family %}
+
+{#- START Global ASN address-family section; set protocol bgp xxx address-family #}
+{%- if 'address_family' in conf_bgp[asn] %}
+{%- for type in bgp_afi %}
+{%- if type == "ipv4_unicast" %}
+ !
+ address-family ipv4 unicast
+{# need to check #}
+{%- if 'aggregate_address' in bgp_afi[type] %}
+{%- for ip in bgp_afi[type].aggregate_address %}
+{%- if ( ('as_set' and 'summary_only') in bgp_afi[type].aggregate_address[ip] ) %}
+ aggregate-address {{ ip }} as-set summary-only
+{%- elif 'as_set' in bgp_afi[type].aggregate_address[ip] %}
+ aggregate-address {{ ip }} as-set
+{%- elif 'summary_only' in bgp_afi[type].aggregate_address[ip] %}
+ aggregate-address {{ ip }} summary-only
+{%- else %}
+ aggregate-address {{ ip }}
+{%- endif %}
+{%- endfor %}
+{%- endif %}
+{# END aggregate address#}
+{#- redistribute #}
+{# need to check. dont work.
+ 'metric' and 'route_map' match also only 'route_map'
+ 'table' parameter also include in protocol, its not what I want #}
+{%- if 'redistribute' in bgp_afi[type] %}
+{%- if 'table' in bgp_afi[type].redistribute %}
+ redistribute table {{bgp_afi[type].redistribute.table}}
+{%- endif %}
+{%- for protocol in bgp_afi[type].redistribute %}
+{%- if ( ('metric' and 'route_map') in bgp_afi[type].redistribute[protocol] ) %}
+ redistribute {{protocol}} metric {{bgp_afi[type].redistribute[protocol].metric}} route-map {{bgp_afi[type].redistribute[protocol].route_map}}
+{%- elif 'metric' in bgp_afi[type].redistribute[protocol] %}
+ redistribute {{protocol}} metric {{bgp_afi[type].redistribute[protocol].metric}}
+{%- elif 'route_map' in bgp_afi[type].redistribute[protocol] %}
+ redistribute {{protocol}} route-map {{bgp_afi[type].redistribute[protocol].route_map}}
+{%- else %}
+ redistribute {{protocol}}
+{%- endif %}
+{%- endfor %}
+{%- endif %}
+{#- END redistribute #}
+
+{%- if 'network' in bgp_afi[type] %}
+{%- for net in bgp_afi[type].network %}
+ network {{ net }}
+{%- endfor %}
+{%- endif %}
+ exit-address-family
+ !
+{%- endif %}
+
+{%- if type == "ipv6_unicast" %}
+ !
+ address-family ipv6 unicast
+{%- if 'aggregate_address' in bgp_afi[type] %}
+{%- for ip in bgp_afi[type].aggregate_address %}
+{%- if ( ('as_set' and 'summary_only') in bgp_afi[type].aggregate_address[ip] ) %}
+ aggregate-address {{ ip }} as-set summary-only
+{%- elif 'as_set' in bgp_afi[type].aggregate_address[ip] %}
+ aggregate-address {{ ip }} as-set
+{%- elif 'summary_only' in bgp_afi[type].aggregate_address[ip] %}
+ aggregate-address {{ ip }} summary-only
+{%- else %}
+ aggregate-address {{ ip }}
+{%- endif %}
+{%- endfor %}
+{%- endif %}
+{# END aggregate address#}
+
+{#- redistribute #}
+{# need to check. doesn't work. 'metric' and 'route_map' match also only 'route_map' #}
+{%- if 'redistribute' in bgp_afi[type] %}
+{%- if 'table' in bgp_afi[type].redistribute %}
+ redistribute table {{bgp_afi[type].redistribute.table}}
+{%- endif %}
+{%- for protocol in bgp_afi[type].redistribute %}
+{%- if ( ('metric' and 'route_map') in bgp_afi[type].redistribute[protocol] ) %}
+ redistribute {{protocol}} metric {{bgp_afi[type].redistribute[protocol].metric}} route-map {{bgp_afi[type].redistribute[protocol].route_map}}
+{%- elif 'metric' in bgp_afi[type].redistribute[protocol] %}
+ redistribute {{protocol}} metric {{bgp_afi[type].redistribute[protocol].metric}}
+{%- elif 'route_map' in bgp_afi[type].redistribute[protocol] %}
+ redistribute {{protocol}} route-map {{bgp_afi[type].redistribute[protocol].route_map}}
+{%- else %}
+ redistribute {{protocol}}
+{%- endif %}
+{%- endfor %}
+{%- endif %}
+{#- END redistribute #}
+
+{%- if 'network' in bgp_afi[type] %}
+{%- for net in bgp_afi[type].network %}
+ network {{ net }}
+{%- endfor %}
+{%- endif %}
+ exit-address-family
+!
+{%- endif %}
+{%- endfor %}
+{%- endif %}
+{#- END Global ASN address-family section; set protocols bgp 65001 address-family #}
+
+{#- set protocols nbgp xxxx maximum-paths ibgp x, Generated by default for afi_4 #}
+{#- We don't have this parameter in afi_6. But this is supported in the FRR #}
+{%- if 'maximum_paths' in conf_bgp[asn] %}
+{%- if 'ebgp' in conf_bgp[asn].maximum_paths %}
+ !
+ address-family ipv4 unicast
+ maximum-paths {{ conf_bgp[asn].maximum_paths.ebgp }}
+ exit-address-family
+ !
+{%- endif %}
+{%- if 'ibgp' in conf_bgp[asn].maximum_paths %}
+ !
+ address-family ipv4 unicast
+ maximum-paths ibgp {{ conf_bgp[asn].maximum_paths.ibgp }}
+ exit-address-family
+ !
+{%- endif %}
+{%- endif %}
+
+{#- START peer-group; set protocol bgp xxx peer-group #}
+{%- if 'peer_group' in conf_bgp[asn] %}
+{%- for pr_group in conf_bgp[asn].peer_group %}
+{%- set conf_peer_group = conf_bgp[asn].peer_group[pr_group] %}
+ neighbor {{pr_group}} peer-group
+
+{#- First parameter for peer-group - remote-as #}
+{%- if 'remote_as' in conf_peer_group %}
+ neighbor {{ pr_group }} remote-as {{ conf_peer_group.remote_as }}
+{%- endif %}
+
+{%- if 'bfd' in conf_peer_group %}
+ neighbor {{ pr_group }} bfd
+{%- endif %}
+
+{%- if 'capability' in conf_peer_group %}
+{%- if 'dynamic' in conf_peer_group.capability %}
+ neighbor {{ pr_group }} capability dynamic
+{%- endif %}
+{%- if 'extended_nexthop' in conf_peer_group.capability %}
+ neighbor {{ pr_group }} capability extended-nexthop
+{%- endif %}
+{%- endif %}
+
+{%- if 'description' in conf_peer_group %}
+ neighbor {{ pr_group }} description {{ conf_peer_group.description }}
+{%- endif %}
+
+{%- if 'disable_capability_negotiation' in conf_peer_group %}
+ neighbor {{ pr_group }} disable-capability-negotiation
+{%- endif %}
+
+{#- https://phabricator.vyos.net/T2844. 'disable-send-community' only for afi #}
+{%- if 'disable_send_community' in conf_peer_group %}
+ !
+{%- endif %}
+
+{%- if 'ebgp_multihop' in conf_peer_group %}
+ neighbor {{ pr_group }} ebgp-multihop {{conf_peer_group.ebgp_multihop}}
+{%- endif %}
+
+{%- if 'local_as' in conf_peer_group %}
+{%- for loc_asn in conf_peer_group.local_as %}
+{%- if 'no_prepend' in conf_peer_group.local_as[loc_asn] %}
+ neighbor {{ pr_group }} local-as {{loc_asn}} no-prepend
+{%- else %}
+ neighbor {{ pr_group }} local-as {{loc_asn}}
+{%- endif %}
+{%- endfor %}
+{%- endif %}
+
+{%- if 'override_capability' in conf_peer_group %}
+ neighbor {{ pr_group }} override-capability
+{%- endif %}
+
+{%- if 'passive' in conf_peer_group %}
+ neighbor {{ pr_group }} passive
+{%- endif %}
+
+{%- if 'password' in conf_peer_group %}
+ neighbor {{ pr_group }} password {{ conf_peer_group.password }}
+{%- endif %}
+
+{%- if 'shutdown' in conf_peer_group %}
+ neighbor {{ pr_group }} shutdown
+{%- endif %}
+
+{%- if 'ttl_security' in conf_peer_group %}
+{%- if 'hops' in conf_peer_group.ttl_security %}
+ neighbor {{ pr_group }} ttl-security hops {{conf_peer_group.ttl_security.hops}}
+{%- endif %}
+{%- endif %}
+
+{%- if 'update_source' in conf_peer_group %}
+ neighbor {{ pr_group }} update-source {{ conf_peer_group.update_source }}
+{%- endif %}
+
+{# START peer-group afi; set protocols bgp xxx peer-group FOO address-family #}
+{%- if 'address_family' in conf_peer_group %}
+{%- for afi in conf_peer_group.address_family %}
+{%- if afi == "ipv4_unicast" %}
+ !
+ address-family ipv4 unicast
+
+{%- if 'allowas_in' in conf_peer_group.address_family.ipv4_unicast %}
+{%- if 'number' in conf_peer_group.address_family.ipv4_unicast.allowas_in %}
+ neighbor {{ pr_group }} allowas-in {{ conf_peer_group.address_family.ipv4_unicast.allowas_in.number }}
+{%- else %}
+ neighbor {{ pr_group }} allowas-in
+{%- endif %}
+{%- endif %}
+
+{#- START Single Params for peer-group; set protocols bgp xxx peer-group FOO address-family ipv4-unicast #}
+
+{%- if 'remove_private_as' in conf_peer_group.address_family.ipv4_unicast %}
+ neighbor {{ pr_group }} remove-private-AS
+{%- endif %}
+
+{%- if 'route_reflector_client' in conf_peer_group.address_family.ipv4_unicast %}
+ neighbor {{ pr_group }} route-reflector-client
+{%- endif %}
+
+{%- if 'weight' in conf_peer_group.address_family.ipv4_unicast %}
+ neighbor {{ pr_group }} weight {{ conf_peer_group.address_family.ipv4_unicast.weight }}
+{%- endif %}
+{#- END single params for peer-group #}
+
+{#- Checks need to be done as-path|med|next-hop #}
+{%- if 'attribute_unchanged' in conf_peer_group.address_family.ipv4_unicast %}
+{%- if 'as_path' in conf_peer_group.address_family.ipv4_unicast.attribute_unchanged %}
+ neighbor {{ pr_group }} attribute-unchanged as-path
+{%- else %}
+ neighbor {{ pr_group }} attribute-unchanged as-path next-hop med
+{%- endif %}
+{%- endif %}
+{#- END attribute-unchanged #}
+
+{%- if 'capability' in conf_peer_group.address_family.ipv4_unicast %}
+{%- if 'receive' in conf_peer_group.address_family.ipv4_unicast.capability.orf.prefix_list %}
+ neighbor {{ pr_group }} capability orf prefix-list receive
+{%- endif %}
+{%- if 'send' in conf_peer_group.address_family.ipv4_unicast.capability.orf.prefix_list %}
+ neighbor {{ pr_group }} capability orf prefix-list send
+{%- endif %}
+{%- endif %}
+
+{%- if 'default_originate' in conf_peer_group.address_family.ipv4_unicast %}
+{%- if 'route_map' in conf_peer_group.address_family.ipv4_unicast.default_originate %}
+ neighbor {{ pr_group }} default-originate route-map {{ conf_peer_group.address_family.ipv4_unicast.default_originate.route_map }}
+{%- else %}
+ neighbor {{ pr_group }} default-originate
+{%- endif %}
+{%- endif %}
+
+{%- if 'distribute_list' in conf_peer_group.address_family.ipv4_unicast %}
+{%- if 'export' in conf_peer_group.address_family.ipv4_unicast.distribute_list %}
+ neighbor {{ pr_group }} distribute-list {{conf_peer_group.address_family.ipv4_unicast.distribute_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer_group.address_family.ipv4_unicast.distribute_list %}
+ neighbor {{ pr_group }} distribute-list {{conf_peer_group.address_family.ipv4_unicast.distribute_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'filter_list' in conf_peer_group.address_family.ipv4_unicast %}
+{%- if 'export' in conf_peer_group.address_family.ipv4_unicast.filter_list %}
+ neighbor {{ pr_group }} filter-list {{conf_peer_group.address_family.ipv4_unicast.filter_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer_group.address_family.ipv4_unicast.filter_list %}
+ neighbor {{ pr_group }} filter-list {{conf_peer_group.address_family.ipv4_unicast.filter_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'maximum_prefix' in conf_peer_group.address_family.ipv4_unicast %}
+ neighbor {{ pr_group }} maximum-prefix {{ conf_peer_group.address_family.ipv4_unicast.maximum_prefix }}
+{%- endif %}
+
+{#- https://phabricator.vyos.net/T1817 #}
+{%- if 'nexthop_self' in conf_peer_group.address_family.ipv4_unicast %}
+{%- if 'force' in conf_peer_group.address_family.ipv4_unicast.nexthop_self %}
+ neighbor {{ pr_group }} next-hop-self force
+ neighbor {{ pr_group }} next-hop-self
+{%- else %}
+ neighbor {{ pr_group }} next-hop-self
+{%- endif %}
+{%- endif %}
+
+{%- if 'route_server_client' in conf_peer_group.address_family.ipv4_unicast %}
+ neighbor {{ pr_group }} route-server-client
+{%- endif %}
+
+{%- if 'route_map' in conf_peer_group.address_family.ipv4_unicast %}
+{%- if 'export' in conf_peer_group.address_family.ipv4_unicast.route_map %}
+ neighbor {{ pr_group }} route-map {{conf_peer_group.address_family.ipv4_unicast.route_map.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer_group.address_family.ipv4_unicast.route_map %}
+ neighbor {{ pr_group }} route-map {{conf_peer_group.address_family.ipv4_unicast.route_map.import}} in
+{%- endif %}
+{%- endif %}
+{%- if 'prefix_list' in conf_peer_group.address_family.ipv4_unicast %}
+{%- if 'export' in conf_peer_group.address_family.ipv4_unicast.prefix_list %}
+ neighbor {{ pr_group }} prefix-list {{conf_peer_group.address_family.ipv4_unicast.prefix_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer_group.address_family.ipv4_unicast.prefix_list %}
+ neighbor {{ pr_group }} prefix-list {{conf_peer_group.address_family.ipv4_unicast.prefix_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'soft_reconfiguration' in conf_peer_group.address_family.ipv4_unicast %}
+{%- if 'inbound' is defined %}
+ neighbor {{ pr_group }} soft-reconfiguration inbound
+{%- endif %}
+{%- endif %}
+
+{#- Need to check. https://phabricator.vyos.net/T2387#73900 #}
+{%- if 'unsuppress_map' in conf_peer_group.address_family.ipv4_unicast %}
+ neighbor {{ pr_group }} unsuppress-map {{conf_peer_group.address_family.ipv4_unicast.unsuppress_map}}
+{%- endif %}
+ neighbor {{ pr_group }} activate
+ exit-address-family
+ !
+{%- endif %}
+
+{%- if afi == "ipv6_unicast" %}
+ !
+ address-family ipv6 unicast
+
+{%- if 'allowas_in' in conf_peer_group.address_family.ipv6_unicast %}
+{%- if 'number' in conf_peer_group.address_family.ipv6_unicast.allowas_in %}
+ neighbor {{ pr_group }} allowas-in {{ conf_peer_group.address_family.ipv6_unicast.allowas_in.number }}
+{%- else %}
+ neighbor {{ pr_group }} allowas-in
+{%- endif %}
+{%- endif %}
+
+{#- START Single Params for peer-group afi6; set protocols bgp xxx peer-group FOO address-family ipv6-unicast #}
+{%- if 'remove_private_as' in conf_peer_group.address_family.ipv6_unicast %}
+ neighbor {{ pr_group }} remove-private-AS
+{%- endif %}
+
+{%- if 'route_reflector_client' in conf_peer_group.address_family.ipv6_unicast %}
+ neighbor {{ pr_group }} route-reflector-client
+{%- endif %}
+
+{%- if 'weight' in conf_peer_group.address_family.ipv6_unicast %}
+ neighbor {{ pr_group }} weight {{ conf_peer_group.address_family.ipv6_unicast.weight }}
+{%- endif %}
+{#- END single params for peer-group afi6 #}
+
+{#- Checks need to be done as-path|med|next-hop #}
+{%- if 'attribute_unchanged' in conf_peer_group.address_family.ipv6_unicast %}
+{%- if 'as_path' in conf_peer_group.address_family.ipv6_unicast.attribute_unchanged %}
+ neighbor {{ pr_group }} attribute-unchanged as-path
+{%- else %}
+ neighbor {{ pr_group }} attribute-unchanged as-path next-hop med
+{%- endif %}
+{%- endif %}
+
+{%- if 'capability' in conf_peer_group.address_family.ipv6_unicast %}
+{%- if 'receive' in conf_peer_group.address_family.ipv6_unicast.capability.orf.prefix_list %}
+ neighbor {{ pr_group }} capability orf prefix-list receive
+{%- endif %}
+{%- if 'send' in conf_peer_group.address_family.ipv6_unicast.capability.orf.prefix_list %}
+ neighbor {{ pr_group }} capability orf prefix-list send
+{%- endif %}
+{%- endif %}
+
+{%- if 'default_originate' in conf_peer_group.address_family.ipv6_unicast %}
+{%- if 'route_map' in conf_peer_group.address_family.ipv6_unicast.default_originate %}
+ neighbor {{ pr_group }} default-originate route-map {{ conf_peer_group.address_family.ipv6_unicast.default_originate.route_map }}
+{%- else %}
+ neighbor {{ pr_group }} default-originate
+{%- endif %}
+{%- endif %}
+
+{%- if 'distribute_list' in conf_peer_group.address_family.ipv6_unicast %}
+{%- if 'export' in conf_peer_group.address_family.ipv6_unicast.distribute_list %}
+ neighbor {{ pr_group }} distribute-list {{conf_peer_group.address_family.ipv6_unicast.distribute_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer_group.address_family.ipv6_unicast.distribute_list %}
+ neighbor {{ pr_group }} distribute-list {{conf_peer_group.address_family.ipv6_unicast.distribute_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'filter_list' in conf_peer_group.address_family.ipv6_unicast %}
+{%- if 'export' in conf_peer_group.address_family.ipv6_unicast.filter_list %}
+ neighbor {{ pr_group }} filter-list {{conf_peer_group.address_family.ipv6_unicast.filter_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer_group.address_family.ipv6_unicast.filter_list %}
+ neighbor {{ pr_group }} filter-list {{conf_peer_group.address_family.ipv6_unicast.filter_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'maximum_prefix' in conf_peer_group.address_family.ipv6_unicast %}
+ neighbor {{ pr_group }} maximum-prefix {{ conf_peer_group.address_family.ipv6_unicast.maximum_prefix }}
+{%- endif %}
+
+{#- https://phabricator.vyos.net/T1817 #}
+{%- if 'nexthop_self' in conf_peer_group.address_family.ipv6_unicast %}
+{%- if 'force' in conf_peer_group.address_family.ipv6_unicast.nexthop_self %}
+ neighbor {{ pr_group }} next-hop-self force
+ neighbor {{ pr_group }} next-hop-self
+{%- else %}
+ neighbor {{ pr_group }} next-hop-self
+{%- endif %}
+{%- endif %}
+
+{%- if 'route_server_client' in conf_peer_group.address_family.ipv6_unicast %}
+ neighbor {{ pr_group }} route-server-client
+{%- endif %}
+
+{%- if 'route_map' in conf_peer_group.address_family.ipv6_unicast %}
+{%- if 'export' in conf_peer_group.address_family.ipv6_unicast.route_map %}
+ neighbor {{ pr_group }} route-map {{conf_peer_group.address_family.ipv6_unicast.route_map.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer_group.address_family.ipv6_unicast.route_map %}
+ neighbor {{ pr_group }} route-map {{conf_peer_group.address_family.ipv6_unicast.route_map.import}} in
+{%- endif %}
+{%- endif %}
+{%- if 'prefix_list' in conf_peer_group.address_family.ipv6_unicast %}
+{%- if 'export' in conf_peer_group.address_family.ipv6_unicast.prefix_list %}
+ neighbor {{ pr_group }} prefix-list {{conf_peer_group.address_family.ipv6_unicast.prefix_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer_group.address_family.ipv6_unicast.prefix_list %}
+ neighbor {{ pr_group }} prefix-list {{conf_peer_group.address_family.ipv6_unicast.prefix_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'soft_reconfiguration' in conf_peer_group.address_family.ipv6_unicast %}
+{%- if 'inbound' is defined %}
+ neighbor {{ pr_group }} soft-reconfiguration inbound
+{%- endif %}
+{%- endif %}
+
+{#- Checks need to be done. https://phabricator.vyos.net/T2387#73900 #}
+{%- if 'unsuppress_map' in conf_peer_group.address_family.ipv6_unicast %}
+ neighbor {{ pr_group }} unsuppress-map {{conf_peer_group.address_family.ipv6_unicast.unsuppress_map}}
+{%- endif %}
+ neighbor {{ pr_group }} activate
+ exit-address-family
+ !
+{%- endif %}
+
+{%- endfor %}
+{%- endif %}
+{# END peer-group afi; set protocols bgp xxx peer-group FOO address-family #}
+
+{%- endfor %}
+{%- endif %}
+{#- END peer-group; set protocol bgp xxx peer-group #}
+
+{#- START peer section; set protocol bgp xxx neighbor #}
+{%- for peer in conf_bgp[asn].neighbor %}
+{#- set peer-group as conf_peer #}
+{%- set conf_peer = conf_bgp[asn].neighbor[peer] %}
+
+{#- First parameter for peer-group - remote-as #}
+{%- if 'remote_as' in conf_peer %}
+ neighbor {{ peer }} remote-as {{ conf_peer.remote_as }}
+{%- endif %}
+
+{%- if 'advertisement_interval' in conf_peer %}
+ neighbor {{ peer }} advertisement-interval {{ conf_peer.advertisement_interval }}
+{%- endif %}
+
+{%- if 'bfd' in conf_peer %}
+{%- if 'check_control_plane_failure' in conf_peer.bfd %}
+ neighbor {{ peer }} bfd
+ neighbor {{ peer }} bfd check-control-plane-failure
+{%- else %}
+ neighbor {{ peer }} bfd
+{%- endif %}
+{%- endif %}
+
+{%- if 'capability' in conf_peer %}
+{%- if 'dynamic' in conf_peer.capability %}
+ neighbor {{ peer }} capability dynamic
+{%- endif %}
+{%- if 'extended_nexthop' in conf_peer.capability %}
+ neighbor {{ peer }} capability extended-nexthop
+{%- endif %}
+{%- endif %}
+
+{%- if 'description' in conf_peer %}
+ neighbor {{ peer }} description {{ conf_peer.description }}
+{%- endif %}
+
+{%- if 'disable_capability_negotiation' in conf_peer %}
+ neighbor {{ peer }} disable-capability-negotiation
+{%- endif %}
+
+{#- https://phabricator.vyos.net/T2844. 'disable-send-community' only for afi #}
+{%- if 'disable_send_community' in conf_peer %}
+ !
+{%- endif %}
+
+{%- if 'ebgp_multihop' in conf_peer %}
+ neighbor {{ peer }} ebgp-multihop {{conf_peer.ebgp_multihop}}
+{%- endif %}
+
+{#- Need to check. 'Peer-group' needs to define before this section #}
+{%- if 'interface' in conf_peer %}
+{%- if 'peer_group' in conf_peer.interface %}
+ neighbor {{ peer }} interface peer-group {{conf_peer.interface.peer_group}}
+{%- endif %}
+{%- if 'remote_as' in conf_peer.interface %}
+ neighbor {{ peer }} interface remote-as {{conf_peer.interface.remote_as}}
+{%- endif %}
+{%- if 'v6only' in conf_peer.interface %}
+{%- if 'peer_group' in conf_peer.interface.v6only %}
+ neighbor {{ peer }} peer-group {{conf_peer.interface.peer_group}}
+{%- endif %}
+{%- if 'remote_as' in conf_peer.interface.v6only %}
+ neighbor {{ peer }} interface v6only remote-as {{conf_peer.interface.v6only.remote_as}}
+{%- endif %}
+{%- endif %}
+{%- endif %}
+
+{%- if 'local_as' in conf_peer %}
+{%- for loc_asn in conf_peer.local_as %}
+{%- if 'no_prepend' in conf_peer.local_as[loc_asn] %}
+ neighbor {{ peer }} local-as {{loc_asn}} no-prepend
+{%- else %}
+ neighbor {{ peer }} local-as {{loc_asn}}
+{%- endif %}
+{%- endfor %}
+{%- endif %}
+
+{%- if 'override_capability' in conf_peer %}
+ neighbor {{ peer }} override-capability
+{%- endif %}
+
+{%- if 'passive' in conf_peer %}
+ neighbor {{ peer }} passive
+{%- endif %}
+
+{%- if 'password' in conf_peer %}
+ neighbor {{ peer }} password {{ conf_peer.password }}
+{%- endif %}
+
+{%- if 'peer_group' in conf_peer %}
+ neighbor {{ peer }} peer-group {{ conf_peer.peer_group }}
+{%- endif %}
+
+{%- if 'port' in conf_peer %}
+ neighbor {{ peer }} port {{ conf_peer.port }}
+{%- endif %}
+
+{%- if 'shutdown' in conf_peer %}
+ neighbor {{ peer }} shutdown
+{%- endif %}
+
+{%- if 'strict_capability_match' in conf_peer %}
+ neighbor {{ peer }} strict-capability-match
+{%- endif %}
+
+{#- Need to check #}
+{%- if 'timers' in conf_peer %}
+{%- if ( ('connect' and 'holdtime' and 'keepalive') in conf_peer.timers ) %}
+ neighbor {{ peer }} timers {{conf_peer.timers.keepalive}} {{conf_peer.timers.holdtime}}
+ neighbor {{ peer }} timers connect {{conf_peer.timers.connect}}
+{%- endif %}
+{%- endif %}
+
+{%- if 'ttl_security' in conf_peer %}
+{%- if 'hops' in conf_peer.ttl_security %}
+ neighbor {{ peer }} ttl-security hops {{conf_peer.ttl_security.hops}}
+{%- endif %}
+{%- endif %}
+
+{%- if 'update_source' in conf_peer %}
+ neighbor {{ peer }} update-source {{ conf_peer.update_source }}
+{%- endif %}
+
+{#- START address family for peer; set protocols bgp xxx neighbor x.x.x.x address-family ipvX-unicast #}
+{%- if 'address_family' in conf_peer %}
+{%- for afi in conf_peer.address_family %}
+{%- if afi == "ipv4_unicast" %}
+ !
+ address-family ipv4 unicast
+
+{%- if 'allowas_in' in conf_peer.address_family.ipv4_unicast %}
+{%- if 'number' in conf_peer.address_family.ipv4_unicast.allowas_in %}
+ neighbor {{ peer }} allowas-in {{ conf_peer.address_family.ipv4_unicast.allowas_in.number }}
+{%- else %}
+ neighbor {{ peer }} allowas-in
+{%- endif %}
+{%- endif %}
+
+{#- START Single Params for neighbor; #}
+{%- if 'as_override' in conf_peer.address_family.ipv4_unicast %}
+ neighbor {{ peer }} as-override
+{%- endif %}
+
+{%- if 'remove_private_as' in conf_peer.address_family.ipv4_unicast %}
+ neighbor {{ peer }} remove-private-AS
+{%- endif %}
+
+{%- if 'route_reflector_client' in conf_peer.address_family.ipv4_unicast %}
+ neighbor {{ peer }} route-reflector-client
+{%- endif %}
+
+{%- if 'weight' in conf_peer.address_family.ipv4_unicast %}
+ neighbor {{ peer }} weight {{ conf_peer.address_family.ipv4_unicast.weight }}
+{%- endif %}
+{#- END single params for neighbor #}
+
+{#- Checks need to be done as-path|med|next-hop #}
+{%- if 'attribute_unchanged' in conf_peer.address_family.ipv4_unicast %}
+{%- if 'as_path' in conf_peer.address_family.ipv4_unicast.attribute_unchanged %}
+ neighbor {{ peer }} attribute-unchanged as-path
+{%- else %}
+ neighbor {{ peer }} attribute-unchanged as-path next-hop med
+{%- endif %}
+{%- endif %}
+{#- END attribute-unchanged #}
+
+{%- if 'capability' in conf_peer.address_family.ipv4_unicast %}
+{%- if 'receive' in conf_peer.address_family.ipv4_unicast.capability.orf.prefix_list %}
+ neighbor {{ peer }} capability orf prefix-list receive
+{%- endif %}
+{%- if 'send' in conf_peer.address_family.ipv4_unicast.capability.orf.prefix_list %}
+ neighbor {{ peer }} capability orf prefix-list send
+{%- endif %}
+{%- endif %}
+
+{%- if 'default_originate' in conf_peer.address_family.ipv4_unicast %}
+{%- if 'route_map' in conf_peer.address_family.ipv4_unicast.default_originate %}
+ neighbor {{ peer }} default-originate route-map {{ conf_peer.address_family.ipv4_unicast.default_originate.route_map }}
+{%- else %}
+ neighbor {{ peer }} default-originate
+{%- endif %}
+{%- endif %}
+
+{%- if 'distribute_list' in conf_peer.address_family.ipv4_unicast %}
+{%- if 'export' in conf_peer.address_family.ipv4_unicast.distribute_list %}
+ neighbor {{ peer }} distribute-list {{conf_peer.address_family.ipv4_unicast.distribute_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer.address_family.ipv4_unicast.distribute_list %}
+ neighbor {{ peer }} distribute-list {{conf_peer.address_family.ipv4_unicast.distribute_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'filter_list' in conf_peer.address_family.ipv4_unicast %}
+{%- if 'export' in conf_peer.address_family.ipv4_unicast.filter_list %}
+ neighbor {{ peer }} filter-list {{conf_peer.address_family.ipv4_unicast.filter_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer.address_family.ipv4_unicast.filter_list %}
+ neighbor {{ peer }} filter-list {{conf_peer.address_family.ipv4_unicast.filter_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'maximum_prefix' in conf_peer.address_family.ipv4_unicast %}
+ neighbor {{ peer }} maximum-prefix {{ conf_peer.address_family.ipv4_unicast.maximum_prefix }}
+{%- endif %}
+
+{#- https://phabricator.vyos.net/T1817 #}
+{%- if 'nexthop_self' in conf_peer.address_family.ipv4_unicast %}
+{%- if 'force' in conf_peer.address_family.ipv4_unicast.nexthop_self %}
+ neighbor {{ peer }} next-hop-self force
+ neighbor {{ peer }} next-hop-self
+{%- else %}
+ neighbor {{ peer }} next-hop-self
+{%- endif %}
+{%- endif %}
+
+{%- if 'route_server_client' in conf_peer.address_family.ipv4_unicast %}
+ neighbor {{ peer }} route-server-client
+{%- endif %}
+
+{%- if 'route_map' in conf_peer.address_family.ipv4_unicast %}
+{%- if 'export' in conf_peer.address_family.ipv4_unicast.route_map %}
+ neighbor {{ peer }} route-map {{conf_peer.address_family.ipv4_unicast.route_map.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer.address_family.ipv4_unicast.route_map %}
+ neighbor {{ peer }} route-map {{conf_peer.address_family.ipv4_unicast.route_map.import}} in
+{%- endif %}
+{%- endif %}
+{%- if 'prefix_list' in conf_peer.address_family.ipv4_unicast %}
+{%- if 'export' in conf_peer.address_family.ipv4_unicast.prefix_list %}
+ neighbor {{ peer }} prefix-list {{conf_peer.address_family.ipv4_unicast.prefix_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer.address_family.ipv4_unicast.prefix_list %}
+ neighbor {{ peer }} prefix-list {{conf_peer.address_family.ipv4_unicast.prefix_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'soft_reconfiguration' in conf_peer.address_family.ipv4_unicast %}
+{%- if 'inbound' is defined %}
+ neighbor {{ peer }} soft-reconfiguration inbound
+{%- endif %}
+{%- endif %}
+
+{#- Checks need to be done. https://phabricator.vyos.net/T2387#73900 #}
+{%- if 'unsuppress_map' in conf_peer.address_family.ipv4_unicast %}
+ neighbor {{ peer }} unsuppress-map {{conf_peer.address_family.ipv4_unicast.unsuppress_map}}
+{%- endif %}
+ neighbor {{ peer }} activate
+ exit-address-family
+ !
+{%- endif %}
+
+{%- if afi == "ipv6_unicast" %}
+ !
+ address-family ipv6 unicast
+
+{%- if 'allowas_in' in conf_peer.address_family.ipv6_unicast %}
+{%- if 'number' in conf_peer.address_family.ipv6_unicast.allowas_in %}
+ neighbor {{ peer }} allowas-in {{ conf_peer.address_family.ipv6_unicast.allowas_in.number }}
+{%- else %}
+ neighbor {{ peer }} allowas-in
+{%- endif %}
+{%- endif %}
+
+{#- START Single Params for neighbor #}
+{%- if 'as_override' in conf_peer.address_family.ipv6_unicast %}
+ neighbor {{ peer }} as-override
+{%- endif %}
+
+{%- if 'remove_private_as' in conf_peer.address_family.ipv6_unicast %}
+ neighbor {{ peer }} remove-private-AS
+{%- endif %}
+
+{%- if 'route_reflector_client' in conf_peer.address_family.ipv6_unicast %}
+ neighbor {{ peer }} route-reflector-client
+{%- endif %}
+
+{%- if 'weight' in conf_peer.address_family.ipv6_unicast %}
+ neighbor {{ peer }} weight {{ conf_peer.address_family.ipv6_unicast.weight }}
+{%- endif %}
+{#- END single params for neighbor #}
+
+{#- Checks need to be done as-path|med|next-hop #}
+{%- if 'attribute_unchanged' in conf_peer.address_family.ipv6_unicast %}
+{%- if 'as_path' in conf_peer.address_family.ipv6_unicast.attribute_unchanged %}
+ neighbor {{ peer }} attribute-unchanged as-path
+{%- else %}
+ neighbor {{ peer }} attribute-unchanged as-path next-hop med
+{%- endif %}
+{%- endif %}
+{#- END attribute-unchanged #}
+
+{%- if 'capability' in conf_peer.address_family.ipv6_unicast %}
+{%- if 'receive' in conf_peer.address_family.ipv6_unicast.capability.orf.prefix_list %}
+ neighbor {{ peer }} capability orf prefix-list receive
+{%- endif %}
+{%- if 'send' in conf_peer.address_family.ipv6_unicast.capability.orf.prefix_list %}
+ neighbor {{ peer }} capability orf prefix-list send
+{%- endif %}
+{%- endif %}
+
+{%- if 'default_originate' in conf_peer.address_family.ipv6_unicast %}
+{%- if 'route_map' in conf_peer.address_family.ipv6_unicast.default_originate %}
+ neighbor {{ peer }} default-originate route-map {{ conf_peer.address_family.ipv6_unicast.default_originate.route_map }}
+{%- else %}
+ neighbor {{ peer }} default-originate
+{%- endif %}
+{%- endif %}
+
+{%- if 'distribute_list' in conf_peer.address_family.ipv6_unicast %}
+{%- if 'export' in conf_peer.address_family.ipv6_unicast.distribute_list %}
+ neighbor {{ peer }} distribute-list {{conf_peer.address_family.ipv6_unicast.distribute_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer.address_family.ipv6_unicast.distribute_list %}
+ neighbor {{ peer }} distribute-list {{conf_peer.address_family.ipv6_unicast.distribute_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'filter_list' in conf_peer.address_family.ipv6_unicast %}
+{%- if 'export' in conf_peer.address_family.ipv6_unicast.filter_list %}
+ neighbor {{ peer }} filter-list {{conf_peer.address_family.ipv6_unicast.filter_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer.address_family.ipv6_unicast.filter_list %}
+ neighbor {{ peer }} filter-list {{conf_peer.address_family.ipv6_unicast.filter_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'maximum_prefix' in conf_peer.address_family.ipv6_unicast %}
+ neighbor {{ peer }} maximum-prefix {{ conf_peer.address_family.ipv6_unicast.maximum_prefix }}
+{%- endif %}
+
+{#- https://phabricator.vyos.net/T1817 #}
+{%- if 'nexthop_self' in conf_peer.address_family.ipv6_unicast %}
+{%- if 'force' in conf_peer.address_family.ipv6_unicast.nexthop_self %}
+ neighbor {{ peer }} next-hop-self force
+ neighbor {{ peer }} next-hop-self
+{%- else %}
+ neighbor {{ peer }} next-hop-self
+{%- endif %}
+{%- endif %}
+
+{%- if 'route_server_client' in conf_peer.address_family.ipv6_unicast %}
+ neighbor {{ peer }} route-server-client
+{%- endif %}
+
+{%- if 'route_map' in conf_peer.address_family.ipv6_unicast %}
+{%- if 'export' in conf_peer.address_family.ipv6_unicast.route_map %}
+ neighbor {{ peer }} route-map {{conf_peer.address_family.ipv6_unicast.route_map.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer.address_family.ipv6_unicast.route_map %}
+ neighbor {{ peer }} route-map {{conf_peer.address_family.ipv6_unicast.route_map.import}} in
+{%- endif %}
+{%- endif %}
+{%- if 'prefix_list' in conf_peer.address_family.ipv6_unicast %}
+{%- if 'export' in conf_peer.address_family.ipv6_unicast.prefix_list %}
+ neighbor {{ peer }} prefix-list {{conf_peer.address_family.ipv6_unicast.prefix_list.export}} out
+{%- endif %}
+{%- if 'import' in conf_peer.address_family.ipv6_unicast.prefix_list %}
+ neighbor {{ peer }} prefix-list {{conf_peer.address_family.ipv6_unicast.prefix_list.import}} in
+{%- endif %}
+{%- endif %}
+
+{%- if 'soft_reconfiguration' in conf_peer.address_family.ipv6_unicast %}
+{%- if 'inbound' is defined %}
+ neighbor {{ peer }} soft-reconfiguration inbound
+{%- endif %}
+{%- endif %}
+
+{#- Checks need to be done. https://phabricator.vyos.net/T2387#73900 #}
+{%- if 'unsuppress_map' in conf_peer.address_family.ipv6_unicast %}
+ neighbor {{ peer }} unsuppress-map {{conf_peer.address_family.ipv6_unicast.unsuppress_map}}
+{%- endif %}
+ neighbor {{ peer }} activate
+ exit-address-family
+ !
+{%- endif %}
+
+{%- endfor %}
+{%- endif %}
+{#- END address family for peer #}
+
+{%- endfor %}
+{#- END peer section; set protocols bgp xxx neighbor #}
+
+{#- START parameters section; set protocol bgp xxx parameters #}
+{%- if 'always_compare_med' in bgp_params %}
+ bgp always-compare-med
+{%- endif %}
+
+{%- if 'bestpath' in bgp_params %}
+{%- if 'compare_routerid' in bgp_params.bestpath %}
+ bgp bestpath compare-routerid
+{%- endif %}
+{%- if 'as_path' in bgp_params.bestpath %}
+{%- if 'confed' in bgp_params.bestpath.as_path %}
+ bgp bestpath as-path confed
+{%- endif %}
+{%- if 'ignore' in bgp_params.bestpath.as_path %}
+ bgp bestpath as-path ignore
+{%- endif %}
+{%- if 'multipath_relax' in bgp_params.bestpath.as_path %}
+ bgp bestpath as-path multipath-relax
+{%- endif %}
+{%- endif %}
+{%- if 'med' in bgp_params.bestpath %}
+{%- if ( ('confed' and 'missing_as_worst') in bgp_params.bestpath.med ) %}
+ bgp bestpath med confed missing-as-worst
+{%- elif 'confed' in bgp_params.bestpath.med %}
+ bgp bestpath med confed
+{%- elif 'missing_as_worst' in bgp_params.bestpath.med %}
+ bgp bestpath med missing-as-worst
+{%- endif%}
+{%- endif %}
+{%- endif %}
+
+{%- if 'cluster_id' in bgp_params %}
+ bgp cluster-id {{ bgp_params.cluster_id }}
+{%- endif %}
+
+{%- if 'confederation' in bgp_params %}
+{%- if 'identifier' in bgp_params.confederation %}
+ bgp confederation identifier {{ bgp_params.confederation.identifier }}
+{%- endif %}
+{%- if 'peers' in bgp_params.confederation %}
+ bgp confederation peers {{ bgp_params.confederation.peers }}
+{%- endif %}
+{%- endif %}
+
+{#- Doesn't work in current FRR configuration (bgp dampening 16 751 2001 61) #}
+{%- if 'dampening' in bgp_params %}
+{%- if ( ('half_life' and 'max_suppress_time' and 're_use' and 'start_suppress_time') in bgp_params.dampening ) %}
+ bgp dampening {{ bgp_params.dampening.half_life }} {{ bgp_params.dampening.re_use }} {{ bgp_params.dampening.start_suppress_time }} {{ bgp_params.dampening.max_suppress_time }}
+{%- endif %}
+{%- endif %}
+
+{%- if 'default' in bgp_params %}
+{%- if 'local_pref' in bgp_params.default %}
+ bgp default local-preference {{ bgp_params.default.local_pref }}
+{%- endif %}
+{#- We use this is parameter as default in template (5-th string) #}
+{%- if 'no_ipv4_unicast' in bgp_params.default %}
+ no bgp default ipv4-unicast
+{%- endif %}
+{%- endif %}
+
+{%- if 'deterministic_med' in bgp_params %}
+ bgp deterministic-med
+{%- endif %}
+
+{%- if 'distance' in bgp_params %}
+{%- if 'global' in bgp_params.distance %}
+{%- if ( ('external' and 'internal' and 'local') in bgp_params.distance.global ) %}
+ !
+ address-family ipv4 unicast
+ distance bgp {{ bgp_params.distance.global.external }} {{ bgp_params.distance.global.internal }} {{ bgp_params.distance.global.local }}
+ exit-address-family
+!
+{%- endif %}
+{%- endif %}
+{%- if 'prefix' in bgp_params.distance %}
+ !
+ address-family ipv4 unicast
+{%- for prfx in bgp_params.distance.prefix %}
+ distance {{ bgp_params.distance.prefix[prfx].distance }} {{ prfx }}
+{%- endfor %}
+ exit-address-family
+!
+{%- endif %}
+{%- endif %}
+
+{%- if 'graceful_restart' in bgp_params %}
+{%- if 'stalepath_time' in bgp_params.graceful_restart %}
+ bgp graceful-restart stalepath-time {{ bgp_params.graceful_restart.stalepath_time }}
+{%- endif %}
+{%- endif %}
+
+{%- if 'log_neighbor_changes' in bgp_params %}
+ bgp log-neighbor-changes
+{%- endif %}
+
+{%- if 'network_import_check' in bgp_params %}
+ bgp network import-check
+{%- endif %}
+
+{%- if 'no_client_to_client_reflection' in bgp_params %}
+ no bgp client-to-client reflection
+{%- endif %}
+
+{%- if 'no_fast_external_failover' in bgp_params %}
+ no bgp fast-external-failover
+{%- endif %}
+
+{#- END parameters; set protocols bgp xxx parameters #}
+
+{%- if 'timers' in conf_bgp[asn] %}
+{%- if ( ('holdtime' and 'keepalive') in conf_bgp[asn].timers ) %}
+ timers bgp {{conf_bgp[asn].timers.keepalive}} {{conf_bgp[asn].timers.holdtime}}
+{%- endif %}
+{%- endif %}
+
+{%- if 'route_map' in conf_bgp[asn] %}
+!
+ip protocol bgp route-map {{conf_bgp[asn].route_map}}
+{%- endif %}
+!
+{%- endfor -%}
+{#- END asn; router bgp xxx #}
diff --git a/data/templates/frr/ldpd.frr.tmpl b/data/templates/frr/ldpd.frr.tmpl
index bbff88ae5..dbaa917e8 100644
--- a/data/templates/frr/ldpd.frr.tmpl
+++ b/data/templates/frr/ldpd.frr.tmpl
@@ -21,6 +21,18 @@ no discovery transport-address {{ old_ldp.d_transp_ipv4 }}
{% if ldp.d_transp_ipv4 -%}
discovery transport-address {{ ldp.d_transp_ipv4 }}
{% endif -%}
+{% if old_ldp.hello_holdtime -%}
+no discovery hello holdtime {{ old_ldp.hello_holdtime }}
+{% endif -%}
+{% if ldp.hello_holdtime -%}
+discovery hello holdtime {{ ldp.hello_holdtime }}
+{% endif -%}
+{% if old_ldp.hello_interval -%}
+no discovery hello interval {{ old_ldp.hello_interval }}
+{% endif -%}
+{% if ldp.hello_interval -%}
+discovery hello interval {{ ldp.hello_interval }}
+{% endif -%}
{% for interface in old_ldp.interfaces -%}
no interface {{interface}}
{% endfor -%}
diff --git a/data/templates/https/nginx.default.tmpl b/data/templates/https/nginx.default.tmpl
index f4f2c1848..a20be45ae 100644
--- a/data/templates/https/nginx.default.tmpl
+++ b/data/templates/https/nginx.default.tmpl
@@ -25,10 +25,10 @@ server {
{% endfor %}
{% if server.certbot %}
- ssl_certificate /etc/letsencrypt/live/{{ server.certbot_dir }}/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/{{ server.certbot_dir }}/privkey.pem;
- include /etc/letsencrypt/options-ssl-nginx.conf;
- ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
+ 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 %}
include {{ server.vyos_cert.conf }};
{% else %}
@@ -52,7 +52,7 @@ server {
error_page 501 502 503 =200 @50*_json;
-{% if api_somewhere %}
+{% 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"}';
diff --git a/data/templates/lcd/LCDd.conf.tmpl b/data/templates/lcd/LCDd.conf.tmpl
new file mode 100644
index 000000000..6cf6a440f
--- /dev/null
+++ b/data/templates/lcd/LCDd.conf.tmpl
@@ -0,0 +1,132 @@
+### Autogenerted by system-display.py ##
+
+# LCDd.conf -- configuration file for the LCDproc server daemon LCDd
+#
+# This file contains the configuration for the LCDd server.
+#
+# The format is ini-file-like. It is divided into sections that start at
+# markers that look like [section]. Comments are all line-based comments,
+# and are lines that start with '#' or ';'.
+#
+# The server has a 'central' section named [server]. For the menu there is
+# a section called [menu]. Further each driver has a section which
+# defines how the driver acts.
+#
+# The drivers are activated by specifying them in a driver= line in the
+# server section, like:
+#
+# Driver=curses
+#
+# This tells LCDd to use the curses driver.
+# The first driver that is loaded and is capable of output defines the
+# size of the display. The default driver to use is curses.
+# If the driver is specified using the -d <driver> command line option,
+# the Driver= options in the config file are ignored.
+#
+# The drivers read their own options from the respective sections.
+
+## Server section with all kinds of settings for the LCDd server ##
+[server]
+
+# Where can we find the driver modules ?
+# NOTE: Always place a slash as last character !
+DriverPath=/usr/lib/x86_64-linux-gnu/lcdproc/
+
+# Tells the server to load the given drivers. Multiple lines can be given.
+# The name of the driver is case sensitive and determines the section
+# where to look for further configuration options of the specific driver
+# as well as the name of the dynamic driver module to load at runtime.
+# The latter one can be changed by giving a File= directive in the
+# driver specific section.
+#
+# The following drivers are supported:
+# bayrad, CFontz, CFontzPacket, curses, CwLnx, ea65, EyeboxOne, futaba,
+# g15, glcd, glcdlib, glk, hd44780, icp_a106, imon, imonlcd,, IOWarrior,
+# irman, joy, lb216, lcdm001, lcterm, linux_input, lirc, lis, MD8800,
+# mdm166a, ms6931, mtc_s16209x, MtxOrb, mx5000, NoritakeVFD,
+# Olimex_MOD_LCD1x9, picolcd, pyramid, rawserial, sdeclcd, sed1330,
+# sed1520, serialPOS, serialVFD, shuttleVFD, sli, stv5730, svga, t6963,
+# text, tyan, ula200, vlsys_m428, xosd, yard2LCD
+
+{% if model is defined %}
+{% if model.startswith('cfa-') %}
+Driver=CFontzPacket
+{% elif model == 'sdec' %}
+Driver=sdeclcd
+{% endif %}
+{% endif %}
+
+# Tells the driver to bind to the given interface. [default: 127.0.0.1]
+Bind=127.0.0.1
+
+# Listen on this specified port. [default: 13666]
+Port=13666
+
+# Sets the reporting level; defaults to warnings and errors only.
+# [default: 2; legal: 0-5]
+ReportLevel=3
+
+# Should we report to syslog instead of stderr? [default: no; legal: yes, no]
+ReportToSyslog=yes
+
+# User to run as. LCDd will drop its root privileges and run as this user
+# instead. [default: nobody]
+User=nobody
+
+# The server will stay in the foreground if set to yes.
+# [default: no, legal: yes, no]
+Foreground=yes
+
+# Hello message: each entry represents a display line; default: builtin
+Hello="Starting VyOS..."
+
+# GoodBye message: each entry represents a display line; default: builtin
+GoodBye="VyOS shutdown..."
+
+# Sets the interval in microseconds for updating the display.
+# [default: 125000 meaning 8Hz]
+FrameInterval=500000 # 2 updates per second
+
+# Sets the default time in seconds to displays a screen. [default: 4]
+WaitTime=1
+
+# If set to no, LCDd will start with screen rotation disabled. This has the
+# same effect as if the ToggleRotateKey had been pressed. Rotation will start
+# if the ToggleRotateKey is pressed. Note that this setting does not turn off
+# priority sorting of screens. [default: on; legal: on, off]
+AutoRotate=on
+
+# If yes, the the serverscreen will be rotated as a usual info screen. If no,
+# it will be a background screen, only visible when no other screens are
+# active. The special value 'blank' is similar to no, but only a blank screen
+# is displayed. [default: on; legal: on, off, blank]
+ServerScreen=blank
+
+# Set master backlight setting. If set to 'open' a client may control the
+# backlight for its own screens (only). [default: open; legal: off, open, on]
+Backlight=on
+
+# Set master heartbeat setting. If set to 'open' a client may control the
+# heartbeat for its own screens (only). [default: open; legal: off, open, on]
+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-') %}
+## CrystalFontz packet driver (for CFA533, CFA631, CFA633 & CFA635) ##
+[CFontzPacket]
+Model={{ model.split('-')[1] }}
+Device={{ device }}
+Contrast=350
+Brightness=500
+OffBrightness=50
+Reboot=yes
+USB=yes
+{% elif model == 'sdec' %}
+## SDEC driver for Lanner, Watchguard, Sophos sppliances ##
+[sdeclcd]
+# No options
+{% endif %}
+{% endif %}
diff --git a/data/templates/lcd/lcdproc.conf.tmpl b/data/templates/lcd/lcdproc.conf.tmpl
new file mode 100644
index 000000000..c79f3cd0d
--- /dev/null
+++ b/data/templates/lcd/lcdproc.conf.tmpl
@@ -0,0 +1,60 @@
+### autogenerated by system-lcd.py ###
+
+# LCDproc client configuration file
+
+[lcdproc]
+Server=127.0.0.1
+Port=13666
+
+# set reporting level
+ReportLevel=3
+
+# report to to syslog ?
+ReportToSyslog=true
+
+Foreground=yes
+
+[CPU]
+Active=true
+OnTime=1
+OffTime=2
+ShowInvisible=false
+
+[SMP-CPU]
+Active=false
+
+[Memory]
+Active=false
+
+[Load]
+Active=false
+
+[Uptime]
+Active=true
+
+[ProcSize]
+Active=false
+
+[Disk]
+Active=false
+
+[About]
+Active=false
+
+[TimeDate]
+Active=true
+TimeFormat="%H:%M:%S"
+
+[OldTime]
+Active=false
+
+[BigClock]
+Active=false
+
+[MiniClock]
+Active=false
+
+# Display the title bar in two-line mode. Note that with four lines or more
+# the title is always shown. [default: true; legal: true, false]
+ShowTitle=false
+
diff --git a/data/templates/mdns-repeater/mdns-repeater.tmpl b/data/templates/mdns-repeater/mdns-repeater.tmpl
index 3fc4db67e..80f4ab047 100644
--- a/data/templates/mdns-repeater/mdns-repeater.tmpl
+++ b/data/templates/mdns-repeater/mdns-repeater.tmpl
@@ -1,2 +1,2 @@
### Autogenerated by mdns_repeater.py ###
-DAEMON_ARGS="{{ interfaces | join(' ') }}"
+DAEMON_ARGS="{{ interface | join(' ') }}"
diff --git a/data/templates/ntp/ntp.conf.tmpl b/data/templates/ntp/ntp.conf.tmpl
index 6ef0c0f2c..df8157a41 100644
--- a/data/templates/ntp/ntp.conf.tmpl
+++ b/data/templates/ntp/ntp.conf.tmpl
@@ -25,23 +25,15 @@ server {{ srv | replace('_', '-') }} iburst {{ options }}
{% if allow_clients is defined and allow_clients.address is defined %}
# Allowed clients configuration
-{% if allow_clients.address is string %}
-restrict {{ allow_clients.address|address_from_cidr }} mask {{ allow_clients.address|netmask_from_cidr }} nomodify notrap nopeer
-{% else %}
-{% for address in allow_clients.address %}
+{% for address in allow_clients.address %}
restrict {{ address|address_from_cidr }} mask {{ address|netmask_from_cidr }} nomodify notrap nopeer
-{% endfor %}
-{% endif %}
+{% endfor %}
{% endif %}
{% if listen_address %}
# NTP should listen on configured addresses only
interface ignore wildcard
-{% if listen_address is string %}
-interface listen {{ listen_address }}
-{% else %}
-{% for address in listen_address %}
+{% for address in listen_address %}
interface listen {{ address }}
-{% endfor %}
-{% endif %}
+{% endfor %}
{% endif %}
diff --git a/data/templates/ocserv/ocserv_config.tmpl b/data/templates/ocserv/ocserv_config.tmpl
new file mode 100644
index 000000000..6aaeff693
--- /dev/null
+++ b/data/templates/ocserv/ocserv_config.tmpl
@@ -0,0 +1,82 @@
+### generated by vpn_anyconnect.py ###
+
+tcp-port = {{ listen_ports.tcp }}
+udp-port = {{ listen_ports.udp }}
+
+run-as-user = nobody
+run-as-group = daemon
+
+{% if "radius" in authentication.mode %}
+auth = "radius [config=/run/ocserv/radiusclient.conf]"
+{% else %}
+auth = "plain[/run/ocserv/ocpasswd]"
+{% endif %}
+
+{% if ssl.cert_file %}
+server-cert = {{ ssl.cert_file }}
+{% endif %}
+
+{% if ssl.key_file %}
+server-key = {{ ssl.key_file }}
+{% endif %}
+
+{% if ssl.ca_cert_file %}
+ca-cert = {{ ssl.ca_cert_file }}
+{% endif %}
+
+socket-file = /run/ocserv/ocserv.socket
+occtl-socket-file = /run/ocserv/occtl.socket
+use-occtl = true
+isolate-workers = true
+keepalive = 300
+dpd = 60
+mobile-dpd = 300
+switch-to-tcp-timeout = 30
+tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA:-VERS-SSL3.0:-ARCFOUR-128"
+auth-timeout = 240
+idle-timeout = 1200
+mobile-idle-timeout = 1800
+min-reauth-time = 3
+cookie-timeout = 300
+rekey-method = ssl
+try-mtu-discovery = true
+cisco-client-compat = true
+dtls-legacy = true
+
+
+# The name to use for the tun device
+device = sslvpn
+
+# An alternative way of specifying the network:
+{% if network_settings %}
+# DNS settings
+{% if network_settings.name_server is string %}
+dns = {{ network_settings.name_server }}
+{% else %}
+{% for dns in network_settings.name_server %}
+dns = {{ dns }}
+{% endfor %}
+{% endif %}
+# IPv4 network pool
+{% if network_settings.client_ip_settings %}
+{% if network_settings.client_ip_settings.subnet %}
+ipv4-network = {{ network_settings.client_ip_settings.subnet }}
+{% endif %}
+{% endif %}
+# IPv6 network pool
+{% 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 %}
+
+{% if network_settings.push_route is string %}
+route = {{ network_settings.push_route }}
+{% else %}
+{% for route in network_settings.push_route %}
+route = {{ route }}
+{% endfor %}
+{% endif %}
+
diff --git a/data/templates/ocserv/ocserv_passwd.tmpl b/data/templates/ocserv/ocserv_passwd.tmpl
new file mode 100644
index 000000000..ffadb4860
--- /dev/null
+++ b/data/templates/ocserv/ocserv_passwd.tmpl
@@ -0,0 +1,6 @@
+#<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.tmpl
new file mode 100644
index 000000000..2d19306a0
--- /dev/null
+++ b/data/templates/ocserv/radius_conf.tmpl
@@ -0,0 +1,22 @@
+### generated by cpn_anyconnect.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 %}
+authserver {{ srv }}
+{% endif %}
+{% endif %}
+{% endfor %}
+radius_timeout {{ timeout }}
+{% if source_address %}
+bindaddr {{ source_address }}
+{% else %}
+bindaddr *
+{% endif %}
+servers /run/ocserv/radius_servers
+dictionary /etc/radcli/dictionary
+default_realm
+radius_retries 3
+# \ No newline at end of file
diff --git a/data/templates/ocserv/radius_servers.tmpl b/data/templates/ocserv/radius_servers.tmpl
new file mode 100644
index 000000000..ba21fa074
--- /dev/null
+++ b/data/templates/ocserv/radius_servers.tmpl
@@ -0,0 +1,7 @@
+### generated by cpn_anyconnect.py ###
+# server key
+{% for srv in server %}
+{% if not "disable" in server[srv] %}
+{{ srv }} {{ server[srv].key }}
+{% endif %}
+{% endfor %}
diff --git a/data/templates/pppoe/ip-down.script.tmpl b/data/templates/pppoe/ip-down.script.tmpl
index 7b1952a80..c2d0cd09a 100644
--- a/data/templates/pppoe/ip-down.script.tmpl
+++ b/data/templates/pppoe/ip-down.script.tmpl
@@ -30,7 +30,7 @@ vtysh -c "conf t" ${VRF_NAME} -c "no ipv6 route ::/0 {{ ifname }} ${VRF_NAME}"
{% endif %}
{% endif %}
-{% if dhcpv6_options is defined and dhcpv6_options.prefix_delegation is defined %}
+{% 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/ipv6-up.script.tmpl b/data/templates/pppoe/ipv6-up.script.tmpl
index 3dee3d011..d0a62478c 100644
--- a/data/templates/pppoe/ipv6-up.script.tmpl
+++ b/data/templates/pppoe/ipv6-up.script.tmpl
@@ -40,12 +40,11 @@ echo 2 > /proc/sys/net/ipv6/conf/{{ ifname }}/accept_ra
echo 1 > /proc/sys/net/ipv6/conf/{{ ifname }}/autoconf
{% endif %}
-{% if dhcpv6_options is defined and dhcpv6_options.prefix_delegation is defined %}
+{% if dhcpv6_options is defined and dhcpv6_options.pd is defined %}
# Start wide dhcpv6 client
systemctl start dhcp6c@{{ ifname }}.service
{% endif %}
-
{% 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.
diff --git a/data/templates/router-advert/radvd.conf.tmpl b/data/templates/router-advert/radvd.conf.tmpl
index 073623eac..cebfc54b5 100644
--- a/data/templates/router-advert/radvd.conf.tmpl
+++ b/data/templates/router-advert/radvd.conf.tmpl
@@ -1,37 +1,47 @@
### Autogenerated by service_router-advert.py ###
-{% for i in interfaces -%}
-interface {{ i.name }} {
+{% if interface is defined and interface is not none %}
+{% for iface in interface %}
+interface {{ iface }} {
IgnoreIfMissing on;
- AdvDefaultPreference {{ i.default_preference }};
- AdvManagedFlag {{ i.managed_flag }};
- MaxRtrAdvInterval {{ i.interval_max }};
-{% if i.interval_min %}
- MinRtrAdvInterval {{ i.interval_min }};
-{% endif %}
- AdvReachableTime {{ i.reachable_time }};
- AdvIntervalOpt {{ i.send_advert }};
- AdvSendAdvert {{ i.send_advert }};
-{% if i.default_lifetime %}
- AdvDefaultLifetime {{ i.default_lifetime }};
-{% endif %}
-{% if i.link_mtu %}
- AdvLinkMTU {{ i.link_mtu }};
-{% endif %}
- AdvOtherConfigFlag {{ i.other_config_flag }};
- AdvRetransTimer {{ i.retrans_timer }};
- AdvCurHopLimit {{ i.hop_limit }};
-{% for p in i.prefixes %}
- prefix {{ p.prefix }} {
- AdvAutonomous {{ p.autonomous_flag }};
- AdvValidLifetime {{ p.valid_lifetime }};
- AdvOnLink {{ p.on_link }};
- AdvPreferredLifetime {{ p.preferred_lifetime }};
+{% if interface[iface].default_preference is defined and interface[iface].default_preference is not none %}
+ AdvDefaultPreference {{ interface[iface].default_preference }};
+{% endif %}
+{% if interface[iface].managed_flag is defined and interface[iface].managed_flag is not none %}
+ AdvManagedFlag {{ 'on' if interface[iface].managed_flag is defined else 'off' }};
+{% endif %}
+{% if interface[iface].interval.max is defined and interface[iface].interval.max is not none %}
+ MaxRtrAdvInterval {{ interface[iface].interval.max }};
+{% endif %}
+{% if interface[iface].interval.min is defined and interface[iface].interval.min is not none %}
+ MinRtrAdvInterval {{ interface[iface].interval.min }};
+{% endif %}
+{% if interface[iface].reachable_time is defined and interface[iface].reachable_time is not none %}
+ AdvReachableTime {{ interface[iface].reachable_time }};
+{% endif %}
+ AdvIntervalOpt {{ 'off' if interface[iface].no_send_advert is defined else 'on' }};
+ AdvSendAdvert {{ 'off' if interface[iface].no_send_advert is defined else 'on' }};
+{% if interface[iface].default_lifetime is defined %}
+ AdvDefaultLifetime {{ interface[iface].default_lifetime }};
+{% endif %}
+{% if interface[iface].link_mtu is defined %}
+ AdvLinkMTU {{ interface[iface].link_mtu }};
+{% endif %}
+ AdvOtherConfigFlag {{ 'on' if interface[iface].other_config_flag is defined else 'off' }};
+ AdvRetransTimer {{ interface[iface].retrans_timer }};
+ AdvCurHopLimit {{ interface[iface].hop_limit }};
+{% for prefix in interface[iface].prefix %}
+ prefix {{ prefix }} {
+ AdvAutonomous {{ 'off' if interface[iface].prefix[prefix].no_autonomous_flag is defined else 'on' }};
+ AdvValidLifetime {{ interface[iface].prefix[prefix].valid_lifetime }};
+ AdvOnLink {{ 'off' if interface[iface].prefix[prefix].no_on_link_flag is defined else 'on' }};
+ AdvPreferredLifetime {{ interface[iface].prefix[prefix].preferred_lifetime }};
};
-{% endfor %}
-{% if i.name_server %}
- RDNSS {{ i.name_server | join(" ") }} {
+{% endfor %}
+{% if interface[iface].name_server is defined %}
+ RDNSS {{ interface[iface].name_server | join(" ") }} {
};
-{% endif %}
+{% endif %}
};
-{% endfor -%}
+{% endfor -%}
+{% endif %}
diff --git a/data/templates/ssh/override.conf.tmpl b/data/templates/ssh/override.conf.tmpl
index 4276366ae..843aa927b 100644
--- a/data/templates/ssh/override.conf.tmpl
+++ b/data/templates/ssh/override.conf.tmpl
@@ -2,9 +2,10 @@
[Unit]
StartLimitIntervalSec=0
After=vyos-router.service
+ConditionPathExists={{config_file}}
[Service]
ExecStart=
-ExecStart={{vrf_command}}/usr/sbin/sshd -D $SSHD_OPTS
+ExecStart={{vrf_command}}/usr/sbin/sshd -f {{config_file}} -D $SSHD_OPTS
RestartSec=10
diff --git a/data/templates/ssh/sshd_config.tmpl b/data/templates/ssh/sshd_config.tmpl
index 4fde24255..52d537aca 100644
--- a/data/templates/ssh/sshd_config.tmpl
+++ b/data/templates/ssh/sshd_config.tmpl
@@ -37,13 +37,9 @@ PermitRootLogin no
UseDNS {{ "no" if disable_host_validation is defined else "yes" }}
# Specifies the port number that sshd(8) listens on
-{% if port is string %}
-Port {{ port }}
-{% else %}
-{% for value in port %}
+{% for value in port %}
Port {{ value }}
-{% endfor %}
-{% endif %}
+{% endfor %}
# Gives the verbosity level that is used when logging messages from sshd
LogLevel {{ loglevel | upper }}
@@ -53,13 +49,9 @@ PasswordAuthentication {{ "no" if disable_password_authentication is defined els
{% if listen_address %}
# Specifies the local addresses sshd should listen on
-{% if listen_address is string %}
-ListenAddress {{ listen_address }}
-{% else %}
-{% for address in listen_address %}
+{% for address in listen_address %}
ListenAddress {{ address }}
-{% endfor %}
-{% endif %}
+{% endfor %}
{% endif %}
{% if ciphers %}
diff --git a/data/templates/system/curlrc.tmpl b/data/templates/system/curlrc.tmpl
index 675e35a0c..3e5ce801c 100644
--- a/data/templates/system/curlrc.tmpl
+++ b/data/templates/system/curlrc.tmpl
@@ -1,8 +1,8 @@
-{% 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 %}
+{% 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/ssh_config.tmpl b/data/templates/system/ssh_config.tmpl
new file mode 100644
index 000000000..509bd5479
--- /dev/null
+++ b/data/templates/system/ssh_config.tmpl
@@ -0,0 +1,3 @@
+{% 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/wifi/cfg80211.conf.tmpl b/data/templates/wifi/cfg80211.conf.tmpl
index b21bacc1e..91df57aab 100644
--- a/data/templates/wifi/cfg80211.conf.tmpl
+++ b/data/templates/wifi/cfg80211.conf.tmpl
@@ -1,3 +1 @@
-{%- if regdom -%}
-options cfg80211 ieee80211_regdom={{ regdom }}
-{% endif %}
+{{ 'options cfg80211 ieee80211_regdom=' + regdom if regdom is defined }}
diff --git a/data/templates/wifi/crda.tmpl b/data/templates/wifi/crda.tmpl
index 750ad86ee..6cd125e37 100644
--- a/data/templates/wifi/crda.tmpl
+++ b/data/templates/wifi/crda.tmpl
@@ -1,3 +1 @@
-{%- if regdom -%}
-REGDOMAIN={{ regdom }}
-{% endif %}
+{{ 'REGDOMAIN=' + regdom if regdom is defined }}
diff --git a/data/templates/wifi/hostapd.conf.tmpl b/data/templates/wifi/hostapd.conf.tmpl
index d6068e4db..a7efee6d5 100644
--- a/data/templates/wifi/hostapd.conf.tmpl
+++ b/data/templates/wifi/hostapd.conf.tmpl
@@ -9,7 +9,7 @@ device_name={{ description | truncate(32, True) }}
# management frames with the Host AP driver); wlan0 with many nl80211 drivers
# Note: This attribute can be overridden by the values supplied with the '-i'
# command line parameter.
-interface={{ intf }}
+interface={{ ifname }}
# Driver interface type (hostap/wired/none/nl80211/bsd);
# default: hostap). nl80211 is used with all Linux mac80211 drivers.
@@ -28,8 +28,7 @@ logger_syslog_level=0
logger_stdout=-1
logger_stdout_level=0
-{%- if country_code %}
-
+{% if country_code %}
# Country code (ISO/IEC 3166-1). Used to set regulatory domain.
# Set as needed to indicate country in which device is operating.
# This can limit available channels and transmit power.
@@ -42,14 +41,12 @@ country_code={{ country_code }}
ieee80211d=1
{% endif %}
-{%- if ssid %}
-
+{% if ssid %}
# SSID to be used in IEEE 802.11 management frames
ssid={{ ssid }}
{% endif %}
-{%- if channel %}
-
+{% if channel %}
# Channel number (IEEE 802.11)
# (default: 0, i.e., not set)
# Please note that some drivers do not use this value from hostapd and the
@@ -61,8 +58,7 @@ ssid={{ ssid }}
channel={{ channel }}
{% endif %}
-{%- if mode %}
-
+{% if mode %}
# 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
@@ -71,29 +67,30 @@ 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 'n' in mode -%}
+{% if 'n' in mode %}
hw_mode=g
-{% elif 'ac' in mode -%}
+{% elif 'ac' in mode %}
hw_mode=a
ieee80211h=1
ieee80211ac=1
-{% else -%}
+{% else %}
hw_mode={{ mode }}
-{% endif %}
+{% endif %}
{% endif %}
# ieee80211w: Whether management frame protection (MFP) is enabled
# 0 = disabled (default)
# 1 = optional
# 2 = required
-{% if 'disabled' in mgmt_frame_protection -%}
+{% if 'disabled' in mgmt_frame_protection %}
ieee80211w=0
-{% elif 'optional' in mgmt_frame_protection -%}
+{% elif 'optional' in mgmt_frame_protection %}
ieee80211w=1
-{% elif 'required' in mgmt_frame_protection -%}
+{% elif 'required' in mgmt_frame_protection %}
ieee80211w=2
{% endif %}
+{% if capabilities is defined and capabilities.ht is 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
@@ -127,79 +124,50 @@ 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)
-{% if cap_ht %}
-ht_capab=
-{%- endif -%}
-
-{%- if cap_ht_40mhz_incapable -%}
-[40-INTOLERANT]
-{%- endif -%}
-
-{%- if cap_ht_delayed_block_ack -%}
-[DELAYED-BA]
-{%- endif -%}
-
-{%- if cap_ht_dsss_cck_40 -%}
-[DSSS_CCK-40]
-{%- endif -%}
-
-{%- if cap_ht_greenfield -%}
-[GF]
-{%- endif -%}
-
-{%- if cap_ht_ldpc -%}
-[LDPC]
-{%- endif -%}
-
-{%- if cap_ht_lsig_protection -%}
-[LSIG-TXOP-PROT]
-{%- endif -%}
-
-{%- if cap_ht_max_amsdu -%}
-[MAX-AMSDU-{{ cap_ht_max_amsdu }}]
-{%- endif -%}
-
-{%- if cap_ht_smps -%}
-[SMPS-{{ cap_ht_smps | upper }}]
-{%- endif -%}
-
-{%- if cap_ht_chan_set_width -%}
-{%- for csw in cap_ht_chan_set_width -%}
-[{{ csw | upper }}]
-{%- endfor -%}
-{%- endif -%}
-
-{%- if cap_ht_short_gi -%}
-{%- for gi in cap_ht_short_gi -%}
-[SHORT-GI-{{ gi }}]
-{%- endfor -%}
-{%- endif -%}
-
-{%- if cap_ht_stbc_tx -%}
-[TX-STBC]
-{%- endif -%}
-{%- if cap_ht_stbc_rx -%}
-[RX-STBC{{ cap_ht_stbc_rx }}]
-{%- endif %}
+{% set output = '' %}
+{% set output = output + '[40-INTOLERANT]' if capabilities.ht.fourtymhz_incapable is defined else '' %}
+{% set output = output + '[DELAYED-BA]' if capabilities.ht.delayed_block_ack is defined else '' %}
+{% set output = output + '[DSSS_CCK-40]' if capabilities.ht.dsss_cck_40 is defined else '' %}
+{% set output = output + '[GF]' if capabilities.ht.greenfield is defined else '' %}
+{% set output = output + '[LDPC]' if capabilities.ht.ldpc is defined else '' %}
+{% set output = output + '[LSIG-TXOP-PROT]' if capabilities.ht.lsig_protection is defined else '' %}
+{% set output = output + '[TX-STBC]' if capabilities.ht.stbc.tx is defined else '' %}
+{% set output = output + '[RX-STBC-' + capabilities.ht.stbc.rx | upper + ']' if capabilities.ht.stbc.tx is defined else '' %}
+{% set output = output + '[MAX-AMSDU-' + capabilities.ht.max_amsdu + ']' if capabilities.ht.max_amsdu is defined else '' %}
+{% set output = output + '[SMPS-' + capabilities.ht.smps | upper + ']' if capabilities.ht.smps is defined else '' %}
+
+{% if capabilities.ht.channel_set_width is defined %}
+{% for csw in capabilities.ht.channel_set_width %}
+{% set output = output + '[' + csw | upper + ']' %}
+{% endfor %}
+{% endif %}
-# Required for full HT and VHT functionality
-wme_enabled=1
+{% if capabilities.ht.short_gi is defined %}
+{% for short_gi in capabilities.ht.short_gi %}
+{% set output = output + '[SHORT-GI-' + short_gi | upper + ']' %}
+{% endfor %}
+{% endif %}
-{% if cap_ht_powersave -%}
+ht_capab={{ output }}
+
+{% if capabilities.ht.auto_powersave is 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 %}
-{% if cap_req_ht -%}
+{% endif %}
+
+# Required for full HT and VHT functionality
+wme_enabled=1
+
+
+{% if capabilities is defined and capabilities.require_ht is defined %}
# Require stations to support HT PHY (reject association if they do not)
require_ht=1
{% endif %}
-{%- if cap_vht_chan_set_width -%}
-vht_oper_chwidth={{ cap_vht_chan_set_width }}
-{%- endif %}
-
+{% if capabilities is defined and capabilities.vht is defined %}
# vht_capab: VHT capabilities (list of flags)
#
# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]
@@ -316,133 +284,95 @@ vht_oper_chwidth={{ cap_vht_chan_set_width }}
# Tx Antenna Pattern Consistency: [TX-ANTENNA-PATTERN]
# Indicates the possibility of Tx antenna pattern change
# 0 = Tx antenna pattern might change during the lifetime of an association
-# 1 = Tx antenna pattern does not change during the lifetime of an association
-{% if cap_vht %}
-vht_capab=
-{%- endif -%}
-
-{%- if cap_vht_max_mpdu -%}
-[MAX-MPDU-{{ cap_vht_max_mpdu }}]
-{%- endif -%}
-
-{%- if cap_vht_max_mpdu_exp -%}
-[MAX-A-MPDU-LEN-EXP{{ cap_vht_max_mpdu_exp }}]
-{%- endif -%}
-
-{%- if cap_vht_chan_set_width -%}
-{%- if '2' in cap_vht_chan_set_width -%}
-[VHT160]
-{%- elif '3' in cap_vht_chan_set_width -%}
-[VHT160-80PLUS80]
-{%- endif -%}
-{%- endif -%}
-
-{%- if cap_vht_stbc_tx -%}
-[TX-STBC-2BY1]
-{%- endif -%}
-
-{%- if cap_vht_stbc_rx -%}
-[RX-STBC-{{ cap_vht_stbc_rx }}]
-{%- endif -%}
-
-{%- if cap_vht_link_adaptation -%}
-{%- if 'unsolicited' in cap_vht_link_adaptation -%}
-[VHT-LINK-ADAPT2]
-{%- elif 'both' in cap_vht_link_adaptation -%}
-[VHT-LINK-ADAPT3]
-{%- endif -%}
-{%- endif -%}
-
-{%- if cap_vht_short_gi -%}
-{%- for gi in cap_vht_short_gi -%}
-[SHORT-GI-{{ gi }}]
-{%- endfor -%}
-{%- endif -%}
-
-{%- if cap_vht_ldpc -%}
-[RXLDPC]
-{%- endif -%}
-
-{%- if cap_vht_tx_powersave -%}
-[VHT-TXOP-PS]
-{%- endif -%}
-
-{%- if cap_vht_vht_cf -%}
-[HTC-VHT]
-{%- endif -%}
-
-{%- if cap_vht_beamform -%}
-{%- for beamform in cap_vht_beamform -%}
-{%- if 'single-user-beamformer' in beamform -%}
-[SU-BEAMFORMER]
-{%- elif 'single-user-beamformee' in beamform -%}
-[SU-BEAMFORMEE]
-{%- elif 'multi-user-beamformer' in beamform -%}
-[MU-BEAMFORMER]
-{%- elif 'multi-user-beamformee' in beamform -%}
-[MU-BEAMFORMEE]
-{%- endif -%}
-{%- endfor -%}
-{%- endif -%}
-
-{%- if cap_vht_antenna_fixed -%}
-[RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]
-{%- endif -%}
-
-{%- if cap_vht_antenna_cnt -%}
-{%- if cap_vht_antenna_cnt|int > 1 -%}
-{%- if cap_vht_beamform -%}
-{%- for beamform in cap_vht_beamform -%}
-{%- if 'single-user-beamformer' in beamform -%}
-{%- if cap_vht_antenna_cnt|int < 6 -%}
-[BF-ANTENNA-{{ cap_vht_antenna_cnt|int -1 }}][SOUNDING-DIMENSION-{{ cap_vht_antenna_cnt|int -1}}]
-{%- endif -%}
-{%- else -%}
-{%- if cap_vht_antenna_cnt|int < 5 -%}
-[BF-ANTENNA-{{ cap_vht_antenna_cnt }}][SOUNDING-DIMENSION-{{ cap_vht_antenna_cnt }}]
-{%- endif -%}
-{%- endif -%}
-{%- endfor -%}
-{%- else -%}
-{%- if cap_vht_antenna_cnt|int < 5 -%}
-[BF-ANTENNA-{{ cap_vht_antenna_cnt }}][SOUNDING-DIMENSION-{{ cap_vht_antenna_cnt }}]
-{%- endif -%}
-{%- endif -%}
-{%- endif -%}
-{%- endif %}
+# 1 = Tx antenna pattern does not change during the lifetime of an
+
+{% if capabilities.vht.center_channel_freq.freq_1 is 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 %}
+
+{% if capabilities.vht.center_channel_freq.freq_2 is 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 %}
+
+{% if capabilities.vht.channel_set_width is defined %}
+vht_oper_chwidth={{ capabilities.vht.channel_set_width }}
+{% endif %}
+
+{% set output = '' %}
+{% set output = output + '[TX-STBC-2BY1]' if capabilities.vht.stbc.tx is defined else '' %}
+{% set output = output + '[RXLDPC]' if capabilities.vht.ldpc is defined else '' %}
+{% set output = output + '[VHT-TXOP-PS]' if capabilities.vht.tx_powersave is defined else '' %}
+{% set output = output + '[HTC-VHT]' if capabilities.vht.vht_cf is defined else '' %}
+{% set output = output + '[RX-ANTENNA-PATTERN]' if capabilities.vht.antenna_pattern_fixed is defined else '' %}
+{% set output = output + '[TX-ANTENNA-PATTERN]' if capabilities.vht.antenna_pattern_fixed is defined else '' %}
+
+{% set output = output + '[RX-STBC-' + capabilities.vht.stbc.rx + ']' if capabilities.vht.stbc.rx is defined else '' %}
+{% set output = output + '[MAX-MPDU-' + capabilities.vht.max_mpdu + ']' if capabilities.vht.max_mpdu is defined else '' %}
+{% set output = output + '[MAX-A-MPDU-LEN-EXP-' + capabilities.vht.max_mpdu_exp + ']' if capabilities.vht.max_mpdu_exp is defined else '' %}
+{% set output = output + '[MAX-A-MPDU-LEN-EXP-' + capabilities.vht.max_mpdu_exp + ']' if capabilities.vht.max_mpdu_exp is defined else '' %}
+
+{% set output = output + '[VHT160]' if capabilities.vht.max_mpdu_exp is defined and capabilities.vht.max_mpdu_exp == '2' else '' %}
+{% set output = output + '[VHT160-80PLUS80]' if capabilities.vht.max_mpdu_exp is defined and capabilities.vht.max_mpdu_exp == '3' else '' %}
+{% set output = output + '[VHT-LINK-ADAPT2]' if capabilities.vht.link_adaptation is defined and capabilities.vht.link_adaptation == 'unsolicited' else '' %}
+{% set output = output + '[VHT-LINK-ADAPT3]' if capabilities.vht.link_adaptation is defined and capabilities.vht.link_adaptation == 'both' else '' %}
+
+{% if capabilities.vht.short_gi is defined %}
+{% for short_gi in capabilities.vht.short_gi %}
+{% set output = output + '[SHORT-GI-' + short_gi | upper + ']' %}
+{% endfor %}
+{% endif %}
+
+{% if capabilities.vht.beamform %}
+{% for beamform in capabilities.vht.beamform %}
+{% set output = output + '[SU-BEAMFORMER]' if beamform == 'single-user-beamformer' else '' %}
+{% set output = output + '[SU-BEAMFORMEE]' if beamform == 'single-user-beamformee' else '' %}
+{% set output = output + '[MU-BEAMFORMER]' if beamform == 'multi-user-beamformer' else '' %}
+{% set output = output + '[MU-BEAMFORMEE]' if beamform == 'multi-user-beamformee' else '' %}
+{% endfor %}
+{% endif %}
+
+{% 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 = output + '[BF-ANTENNA-' + capabilities.vht.antenna_count|int -1 + ']' %}
+{% set output = output + '[SOUNDING-DIMENSION-' + capabilities.vht.antenna_count|int -1 + ']' %}
+{% 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 = output + '[BF-ANTENNA-' + capabilities.vht.antenna_count + ']' %}
+{% set output = output + '[SOUNDING-DIMENSION-' + capabilities.vht.antenna_count+ ']' %}
+{% endif %}
+{% endif %}
+{% endif %}
+
+vht_capab={{ output }}
+{% endif %}
# ieee80211n: Whether IEEE 802.11n (HT) is enabled
# 0 = disabled (default)
# 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 cap_req_vht -%}
+{% if capabilities is defined and capabilities.require_vht is 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 -%}
+{% else %}
+{% if 'n' in mode or 'ac' in mode %}
ieee80211n=1
-{% else -%}
+{% else %}
ieee80211n=0
-{%- endif %}
-{% endif %}
-
-{% if cap_vht_center_freq_1 -%}
-# 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={{ cap_vht_center_freq_1 }}
-{% endif %}
-
-{% if cap_vht_center_freq_2 -%}
-# 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={{ cap_vht_center_freq_2 }}
+{% endif %}
{% endif %}
-{% if disable_broadcast_ssid -%}
+{% if disable_broadcast_ssid is 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)
@@ -463,7 +393,7 @@ ignore_broadcast_ssid=1
# 2 = use external RADIUS server (accept/deny lists are searched first)
macaddr_acl=0
-{% if max_stations -%}
+{% if max_stations is 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.
@@ -471,13 +401,13 @@ macaddr_acl=0
max_num_sta={{ max_stations }}
{% endif %}
-{% if isolate_stations -%}
+{% if isolate_stations is 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 -%}
+{% if reduce_transmit_power is 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
@@ -486,14 +416,15 @@ ap_isolate=1
local_pwr_constraint={{ reduce_transmit_power }}
{% endif %}
-{% if expunge_failing_stations -%}
+{% if expunge_failing_stations is 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.
disassoc_low_ack=1
{% endif %}
-{% if sec_wep -%}
+
+{% if security is defined and security.wep is 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.
@@ -522,13 +453,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 sec_wep_key -%}
-{% for key in sec_wep_key -%}
-wep_key{{ loop.index -1 }}={{ key}}
-{% endfor %}
-{%- endif %}
+{% if security.wep.key is defined %}
+{% for key in sec_wep_key %}
+wep_key{{ loop.index -1 }}={{ security.wep.key }}
+{% endfor %}
+{% endif %}
+
-{% elif sec_wpa -%}
+{% elif security is defined and security.wpa is defined %}
##### WPA/IEEE 802.11i configuration ##########################################
# Enable WPA. Setting this variable configures the AP to require WPA (either
@@ -542,15 +474,17 @@ wep_key{{ loop.index -1 }}={{ key}}
# and/or WPA2 (full IEEE 802.11i/RSN):
# bit0 = WPA
# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled)
-{% if 'both' in sec_wpa_mode -%}
+{% if security.wpa.mode is defined %}
+{% if security.wpa.mode == 'both' %}
wpa=3
-{%- elif 'wpa2' in sec_wpa_mode -%}
+{% elif security.wpa.mode == 'wpa2' %}
wpa=2
-{%- elif 'wpa' in sec_wpa_mode -%}
+{% elif security.wpa.mode == 'wpa' %}
wpa=1
-{%- endif %}
+{% endif %}
+{% endif %}
-{% if sec_wpa_cipher -%}
+{% if security.wpa.cipher is 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)
@@ -563,26 +497,27 @@ wpa=1
# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise,
# TKIP will be used as the group cipher. The optional group_cipher parameter can
# be used to override this automatic selection.
-{% if 'wpa2' in sec_wpa_mode -%}
+
+{% if security.wpa.mode is defined and security.wpa.mode == 'wpa2' %}
# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value)
-rsn_pairwise={{ sec_wpa_cipher | join(" ") }}
-{% else -%}
+rsn_pairwise={{ security.wpa.cipher | join(" ") }}
+{% else %}
# Pairwise cipher for WPA (v1) (default: TKIP)
-wpa_pairwise={{ sec_wpa_cipher | join(" ") }}
-{%- endif -%}
-{% endif %}
+wpa_pairwise={{ security.wpa.cipher | join(" ") }}
+{% endif %}
+{% endif %}
-{% if sec_wpa_group_cipher -%}
+{% if security.wpa.group_cipher is 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
# overriding the group cipher with an unexpected value can result in
# interoperability issues and in general, this parameter is mainly used for
# testing purposes.
-group_cipher={{ sec_wpa_group_cipher | join(" ") }}
-{% endif %}
+group_cipher={{ security.wpa.group_cipher | join(" ") }}
+{% endif %}
-{% if sec_wpa_passphrase -%}
+{% if security.wpa.passphrase is 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.
@@ -595,7 +530,7 @@ auth_algs=1
# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
# (8..63 characters) that will be converted to PSK. This conversion uses SSID
# so the PSK changes when ASCII passphrase is used and the SSID is changed.
-wpa_passphrase={{ sec_wpa_passphrase }}
+wpa_passphrase={{ security.wpa.passphrase }}
# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
@@ -604,7 +539,7 @@ wpa_passphrase={{ sec_wpa_passphrase }}
# WPA-PSK-SHA256 = WPA2-Personal using SHA256
wpa_key_mgmt=WPA-PSK
-{% elif sec_wpa_radius -%}
+{% elif security.wpa.radius is defined %}
##### IEEE 802.1X-2004 related configuration ##################################
# Require IEEE 802.1X authorization
ieee8021x=1
@@ -616,40 +551,37 @@ ieee8021x=1
# WPA-EAP-SHA256 = WPA2-Enterprise using SHA256
wpa_key_mgmt=WPA-EAP
-{% if sec_wpa_radius_source -%}
+{% if security.wpa.radius.server is 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.
-radius_client_addr={{ sec_wpa_radius_source }}
-
-# The own IP address of the access point (used as NAS-IP-Address)
-own_ip_addr={{ sec_wpa_radius_source }}
-{% else %}
# The own IP address of the access point (used as NAS-IP-Address)
+{% if security.wpa.radius.source_address is defined %}
+radius_client_addr={{ security.wpa.radius.source_address }}
+own_ip_addr={{ security.wpa.radius.source_address }}
+{% else %}
own_ip_addr=127.0.0.1
-{% endif %}
+{% endif %}
-{% for radius in sec_wpa_radius -%}
-{%- 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 %}
-{% endif %}
-{% endfor %}
-
-{% endif %}
-
-{% else %}
+{% endif %}
+{% endfor %}
+{% else %}
# Open system
auth_algs=1
+{% 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.tmpl
index 2784883f1..9ddad35fd 100644
--- a/data/templates/wifi/wpa_supplicant.conf.tmpl
+++ b/data/templates/wifi/wpa_supplicant.conf.tmpl
@@ -1,8 +1,8 @@
# WPA supplicant config
network={
ssid="{{ ssid }}"
-{%- if sec_wpa_passphrase %}
- psk="{{ sec_wpa_passphrase }}"
+{% if security is defined and security.wpa is defined and security.wpa.passphrase is defined %}
+ psk="{{ security.wpa.passphrase }}"
{% else %}
key_mgmt=NONE
{% endif %}
diff --git a/data/vyos-configd-env-set b/data/vyos-configd-env-set
new file mode 100644
index 000000000..d6d421eba
--- /dev/null
+++ b/data/vyos-configd-env-set
@@ -0,0 +1,2 @@
+#
+export vyshim=/usr/sbin/vyshim
diff --git a/data/vyos-configd-env-unset b/data/vyos-configd-env-unset
new file mode 100644
index 000000000..9616f9858
--- /dev/null
+++ b/data/vyos-configd-env-unset
@@ -0,0 +1,2 @@
+#
+unset vyshim