diff options
52 files changed, 637 insertions, 346 deletions
diff --git a/.gitignore b/.gitignore index e766a2c27..7707e94ca 100644 --- a/.gitignore +++ b/.gitignore @@ -144,3 +144,4 @@ debian/*.substvars data/component-versions.json # vyos-1x XML cache python/vyos/xml_ref/cache.py +python/vyos/xml_ref/pkg_cache/*_cache.py @@ -61,10 +61,7 @@ op_mode_definitions: $(op_xml_obj) rm -f $(OP_TMPL_DIR)/clear/node.def rm -f $(OP_TMPL_DIR)/delete/node.def rm -f $(OP_TMPL_DIR)/generate/node.def - rm -f $(OP_TMPL_DIR)/monitor/node.def rm -f $(OP_TMPL_DIR)/set/node.def - rm -f $(OP_TMPL_DIR)/show/node.def - rm -f $(OP_TMPL_DIR)/show/system/node.def rm -f $(OP_TMPL_DIR)/show/tech-support/node.def # XXX: ping and traceroute must be able to recursivly call itself as the diff --git a/data/templates/dhcp-client/dhcp6c_daemon-options.j2 b/data/templates/dhcp-client/dhcp6c_daemon-options.j2 new file mode 100644 index 000000000..d33d418fc --- /dev/null +++ b/data/templates/dhcp-client/dhcp6c_daemon-options.j2 @@ -0,0 +1,2 @@ +{% set no_release = '-n' if dhcpv6_options.no_release is vyos_defined else '' %} +DHCP6C_OPTS="-D -k /run/dhcp6c/dhcp6c.{{ ifname }}.sock -c /run/dhcp6c/dhcp6c.{{ ifname }}.conf -p /run/dhcp6c/dhcp6c.{{ ifname }}.pid {{ no_release }} {{ ifname }}" diff --git a/data/templates/ids/fastnetmon.j2 b/data/templates/ids/fastnetmon.j2 index 0340d3c92..f6f03d0db 100644 --- a/data/templates/ids/fastnetmon.j2 +++ b/data/templates/ids/fastnetmon.j2 @@ -29,10 +29,19 @@ unban_only_if_attack_finished = on # For each subnet, list track speed in bps and pps for both directions enable_subnet_counters = off -{% if mode.mirror is vyos_defined %} +{% if mode is vyos_defined('mirror') %} mirror_afpacket = on +{% elif mode is vyos_defined('sflow') %} +sflow = on +{% if sflow.port is vyos_defined %} +sflow_port = {{ sflow.port }} +{% endif %} +{% if sflow.listen_address is vyos_defined %} +sflow_host = {{ sflow.listen_address }} +{% endif %} {% endif %} + process_incoming_traffic = {{ 'on' if direction is vyos_defined and 'in' in direction else 'off' }} process_outgoing_traffic = {{ 'on' if direction is vyos_defined and 'out' in direction else 'off' }} diff --git a/data/templates/ids/fastnetmon_networks_list.j2 b/data/templates/ids/fastnetmon_networks_list.j2 index 5f1b3ba4d..0a0576d2a 100644 --- a/data/templates/ids/fastnetmon_networks_list.j2 +++ b/data/templates/ids/fastnetmon_networks_list.j2 @@ -1,4 +1,4 @@ -{% if network is vyos_defined() %} +{% if network is vyos_defined %} {% for net in network %} {{ net }} {% endfor %} diff --git a/data/templates/openvpn/server.conf.j2 b/data/templates/openvpn/server.conf.j2 index 525605240..d144529f3 100644 --- a/data/templates/openvpn/server.conf.j2 +++ b/data/templates/openvpn/server.conf.j2 @@ -48,11 +48,10 @@ push "redirect-gateway def1" {% if use_lzo_compression is vyos_defined %} compress lzo {% endif %} -{% if enable_dco is not vyos_defined %} +{% if offload.dco is not vyos_defined %} disable-dco {% endif %} - {% if mode is vyos_defined('client') %} # # OpenVPN Client mode diff --git a/debian/control b/debian/control index 8e9aaa702..772edb540 100644 --- a/debian/control +++ b/debian/control @@ -91,7 +91,7 @@ Depends: libqmi-utils, libstrongswan-extra-plugins (>=5.9), libstrongswan-standard-plugins (>=5.9), - libvppinfra, + libvppinfra [amd64], libvyosconfig0, linux-cpupower, lldpd, @@ -145,7 +145,7 @@ Depends: python3-tabulate, python3-vici (>= 5.7.2), python3-voluptuous, - python3-vpp-api, + python3-vpp-api [amd64], python3-xmltodict, python3-zmq, qrencode, @@ -180,9 +180,9 @@ Depends: uidmap, usb-modeswitch, usbutils, - vpp, - vpp-plugin-core, - vpp-plugin-dpdk, + vpp [amd64], + vpp-plugin-core [amd64], + vpp-plugin-dpdk [amd64], vyatta-bash, vyatta-cfg, vyos-http-api-tools, diff --git a/debian/vyos-1x.postinst b/debian/vyos-1x.postinst index 93e7ced9b..b1bd23ff2 100644 --- a/debian/vyos-1x.postinst +++ b/debian/vyos-1x.postinst @@ -180,6 +180,9 @@ systemctl enable vyos-config-cloud-init.service # Generate API GraphQL schema /usr/libexec/vyos/services/api/graphql/generate/generate_schema.py +# Update XML cache +python3 /usr/lib/python3/dist-packages/vyos/xml_ref/update_cache.py + # T1797: disable VPP support for rolling release, should be used by developers # only (in the initial phase). If you wan't to enable VPP use the below command # on your VyOS installation: diff --git a/interface-definitions/include/interface/dhcpv6-options.xml.i b/interface-definitions/include/interface/dhcpv6-options.xml.i index 609af1a2b..5ca1d525f 100644 --- a/interface-definitions/include/interface/dhcpv6-options.xml.i +++ b/interface-definitions/include/interface/dhcpv6-options.xml.i @@ -95,6 +95,12 @@ <valueless/> </properties> </leafNode> + <leafNode name="no-release"> + <properties> + <help>Do not send a release message on client exit</help> + <valueless/> + </properties> + </leafNode> </children> </node> <!-- include end --> diff --git a/interface-definitions/interfaces-openvpn.xml.in b/interface-definitions/interfaces-openvpn.xml.in index ca6d80f8b..127a8179b 100644 --- a/interface-definitions/interfaces-openvpn.xml.in +++ b/interface-definitions/interfaces-openvpn.xml.in @@ -285,6 +285,19 @@ </constraint> </properties> </leafNode> + <node name="offload"> + <properties> + <help>Configurable offload options</help> + </properties> + <children> + <leafNode name="dco"> + <properties> + <help>Enable data channel offload on this interface</help> + <valueless/> + </properties> + </leafNode> + </children> + </node> <leafNode name="openvpn-option"> <properties> <help>Additional OpenVPN options. You must use the syntax of openvpn.conf in this text-field. Using this without proper knowledge may result in a crashed OpenVPN server. Check system log to look for errors.</help> @@ -793,12 +806,6 @@ <valueless/> </properties> </leafNode> - <leafNode name="enable-dco"> - <properties> - <help>Use to enable OpenVPN data channel offload on this TUN interface</help> - <valueless/> - </properties> - </leafNode> #include <include/interface/redirect.xml.i> #include <include/interface/vrf.xml.i> </children> diff --git a/interface-definitions/service-ids-ddos-protection.xml.in b/interface-definitions/service-ids-ddos-protection.xml.in index bb06189bc..78463136b 100644 --- a/interface-definitions/service-ids-ddos-protection.xml.in +++ b/interface-definitions/service-ids-ddos-protection.xml.in @@ -70,17 +70,34 @@ <multi/> </properties> </leafNode> - <node name="mode"> + <leafNode name="mode"> <properties> - <help>Traffic capture modes</help> + <help>Traffic capture mode</help> + <completionHelp> + <list>mirror sflow</list> + </completionHelp> + <valueHelp> + <format>mirror</format> + <description>Listen to mirrored traffic</description> + </valueHelp> + <valueHelp> + <format>sflow</format> + <description>Capture sFlow flows</description> + </valueHelp> + <constraint> + <regex>(mirror|sflow)</regex> + </constraint> + </properties> + </leafNode> + <node name="sflow"> + <properties> + <help>Sflow settings</help> </properties> <children> - <!-- Future modes "mirror" "netflow" "combine (both)" --> - <leafNode name="mirror"> - <properties> - <help>Listen mirrored traffic mode</help> - <valueless/> - </properties> + #include <include/listen-address-ipv4-single.xml.i> + #include <include/port-number.xml.i> + <leafNode name="port"> + <defaultValue>6343</defaultValue> </leafNode> </children> </node> diff --git a/interface-definitions/system-option.xml.in b/interface-definitions/system-option.xml.in index efab50a66..b1b5f7fae 100644 --- a/interface-definitions/system-option.xml.in +++ b/interface-definitions/system-option.xml.in @@ -144,6 +144,26 @@ <valueless/> </properties> </leafNode> + <leafNode name="time-format"> + <properties> + <help>System time-format</help> + <completionHelp> + <list>12-hour 24-hour</list> + </completionHelp> + <valueHelp> + <format>12-hour</format> + <description>12 hour time format</description> + </valueHelp> + <valueHelp> + <format>24-hour</format> + <description>24 hour time format</description> + </valueHelp> + <constraint> + <regex>(12-hour|24-hour)</regex> + </constraint> + </properties> + <defaultValue>12-hour</defaultValue> + </leafNode> </children> </node> </children> diff --git a/op-mode-definitions/dhcp.xml.in b/op-mode-definitions/dhcp.xml.in index 66584efc3..6855fe447 100644 --- a/op-mode-definitions/dhcp.xml.in +++ b/op-mode-definitions/dhcp.xml.in @@ -7,6 +7,30 @@ <help>Show DHCP (Dynamic Host Configuration Protocol) information</help> </properties> <children> + <node name="client"> + <properties> + <help>Show DHCP client information</help> + </properties> + <children> + <node name="leases"> + <properties> + <help>Show DHCP client leases</help> + </properties> + <children> + <tagNode name="interface"> + <properties> + <help> Show DHCP client information for a given interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces --broadcast</script> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/dhcp.py show_client_leases --family inet --interface $6</command> + </tagNode> + </children> + <command>${vyos_op_scripts_dir}/dhcp.py show_client_leases --family inet</command> + </node> + </children> + </node> <node name="server"> <properties> <help>Show DHCP server information</help> diff --git a/op-mode-definitions/include/ospfv3/detail.xml.i b/op-mode-definitions/include/frr-detail.xml.i index 4e3c91268..4edf82eab 100644 --- a/op-mode-definitions/include/ospfv3/detail.xml.i +++ b/op-mode-definitions/include/frr-detail.xml.i @@ -1,8 +1,8 @@ -<!-- included start from ospfv3/detail.xml.i --> -<node name="detail"> +<!-- included start from frr-detail.xml.i --> +<leafNode name="detail"> <properties> <help>Show detailed information</help> </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> -</node> +</leafNode> <!-- included end --> diff --git a/op-mode-definitions/include/monitor-background.xml.i b/op-mode-definitions/include/monitor-background.xml.i deleted file mode 100644 index 9931127e3..000000000 --- a/op-mode-definitions/include/monitor-background.xml.i +++ /dev/null @@ -1,21 +0,0 @@ -<!-- included start from monitor-background.xml.i --> -<node name="background"> - <properties> - <help>Monitor in background</help> - </properties> - <children> - <node name="start"> - <properties> - <help>Start background monitoring</help> - </properties> - <command>${vyatta_bindir}/vyatta-monitor-background ${3^^} ${3}</command> - </node> - <node name="stop"> - <properties> - <help>Stop background monitoring</help> - </properties> - <command>${vyatta_bindir}/vyatta-monitor-background-stop ${3^^}</command> - </node> - </children> -</node> -<!-- included end --> diff --git a/op-mode-definitions/include/ospf/common.xml.i b/op-mode-definitions/include/ospf/common.xml.i index c8341bd3e..684073cc5 100644 --- a/op-mode-definitions/include/ospf/common.xml.i +++ b/op-mode-definitions/include/ospf/common.xml.i @@ -524,12 +524,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - <node name="detail"> - <properties> - <help>Show detailed IPv4 OSPF neighbor information</help> - </properties> - <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> - </node> + #include <include/frr-detail.xml.i> </children> </node> <tagNode name="neighbor"> diff --git a/op-mode-definitions/include/ospfv3/adv-router-id-node-tag.xml.i b/op-mode-definitions/include/ospfv3/adv-router-id-node-tag.xml.i index a1bd67a90..806366444 100644 --- a/op-mode-definitions/include/ospfv3/adv-router-id-node-tag.xml.i +++ b/op-mode-definitions/include/ospfv3/adv-router-id-node-tag.xml.i @@ -8,7 +8,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> </children> diff --git a/op-mode-definitions/include/ospfv3/adv-router.xml.i b/op-mode-definitions/include/ospfv3/adv-router.xml.i index a14fc39db..238242d11 100644 --- a/op-mode-definitions/include/ospfv3/adv-router.xml.i +++ b/op-mode-definitions/include/ospfv3/adv-router.xml.i @@ -7,7 +7,7 @@ </completionHelp> </properties> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> diff --git a/op-mode-definitions/include/ospfv3/border-routers.xml.i b/op-mode-definitions/include/ospfv3/border-routers.xml.i index b6fac6785..e8827a2c4 100644 --- a/op-mode-definitions/include/ospfv3/border-routers.xml.i +++ b/op-mode-definitions/include/ospfv3/border-routers.xml.i @@ -5,7 +5,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <tagNode name="border-routers"> diff --git a/op-mode-definitions/include/ospfv3/database.xml.i b/op-mode-definitions/include/ospfv3/database.xml.i index e98f9e35b..fdc45f184 100644 --- a/op-mode-definitions/include/ospfv3/database.xml.i +++ b/op-mode-definitions/include/ospfv3/database.xml.i @@ -29,7 +29,7 @@ </completionHelp> </properties> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> </children> @@ -45,7 +45,7 @@ </properties> <command>vtysh -c "show ipv6 ospf6 database * $6"</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/adv-router-id-node-tag.xml.i> @@ -67,12 +67,12 @@ </properties> <command>vtysh -c "show ipv6 ospf6 database as-external * $7"</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> </children> </tagNode> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -87,14 +87,14 @@ </completionHelp> </properties> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/self-originated.xml.i> #include <include/ospfv3/adv-router-id-node-tag.xml.i> </children> </tagNode> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> #include <include/ospfv3/self-originated.xml.i> @@ -105,7 +105,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -120,7 +120,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -135,7 +135,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -150,7 +150,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -165,7 +165,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -180,7 +180,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -195,7 +195,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -210,7 +210,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> @@ -225,7 +225,7 @@ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> #include <include/ospfv3/adv-router.xml.i> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/linkstate-id.xml.i> diff --git a/op-mode-definitions/include/ospfv3/interface.xml.i b/op-mode-definitions/include/ospfv3/interface.xml.i index 7a0b8ea48..45d5dbd45 100644 --- a/op-mode-definitions/include/ospfv3/interface.xml.i +++ b/op-mode-definitions/include/ospfv3/interface.xml.i @@ -11,7 +11,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <tagNode name="prefix"> @@ -23,7 +23,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> <node name="match"> <properties> <help>Matched interface prefix information</help> @@ -49,7 +49,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <tagNode name="prefix"> @@ -61,7 +61,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> <node name="match"> <properties> <help>Matched interface prefix information</help> diff --git a/op-mode-definitions/include/ospfv3/linkstate-id-node-tag.xml.i b/op-mode-definitions/include/ospfv3/linkstate-id-node-tag.xml.i index ee3863b35..66674e754 100644 --- a/op-mode-definitions/include/ospfv3/linkstate-id-node-tag.xml.i +++ b/op-mode-definitions/include/ospfv3/linkstate-id-node-tag.xml.i @@ -8,7 +8,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> #include <include/ospfv3/self-originated.xml.i> diff --git a/op-mode-definitions/include/ospfv3/linkstate-id.xml.i b/op-mode-definitions/include/ospfv3/linkstate-id.xml.i index 9ead17c20..aa226c988 100644 --- a/op-mode-definitions/include/ospfv3/linkstate-id.xml.i +++ b/op-mode-definitions/include/ospfv3/linkstate-id.xml.i @@ -7,7 +7,7 @@ </completionHelp> </properties> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> </children> diff --git a/op-mode-definitions/include/ospfv3/linkstate.xml.i b/op-mode-definitions/include/ospfv3/linkstate.xml.i index 78ef3efa1..030dc7923 100644 --- a/op-mode-definitions/include/ospfv3/linkstate.xml.i +++ b/op-mode-definitions/include/ospfv3/linkstate.xml.i @@ -4,7 +4,7 @@ <help>Show OSPFv3 linkstate routing information</help> </properties> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> <tagNode name="network"> <properties> <help>Show linkstate Network information</help> diff --git a/op-mode-definitions/include/ospfv3/neighbor.xml.i b/op-mode-definitions/include/ospfv3/neighbor.xml.i index 37859f815..b736270be 100644 --- a/op-mode-definitions/include/ospfv3/neighbor.xml.i +++ b/op-mode-definitions/include/ospfv3/neighbor.xml.i @@ -5,7 +5,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> <node name="drchoice"> <properties> <help>Show neighbor DR choice information</help> diff --git a/op-mode-definitions/include/ospfv3/route.xml.i b/op-mode-definitions/include/ospfv3/route.xml.i index 9271c9c3a..a5b97cd05 100644 --- a/op-mode-definitions/include/ospfv3/route.xml.i +++ b/op-mode-definitions/include/ospfv3/route.xml.i @@ -11,7 +11,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <node name="external-2"> @@ -20,7 +20,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <node name="inter-area"> @@ -29,7 +29,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> <node name="intra-area"> @@ -38,10 +38,10 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> <node name="summary"> <properties> <help>Show route table summary</help> @@ -71,7 +71,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> </children> </node> </children> diff --git a/op-mode-definitions/include/ospfv3/self-originated.xml.i b/op-mode-definitions/include/ospfv3/self-originated.xml.i index 734f3f8ad..7549ccb2c 100644 --- a/op-mode-definitions/include/ospfv3/self-originated.xml.i +++ b/op-mode-definitions/include/ospfv3/self-originated.xml.i @@ -5,7 +5,7 @@ </properties> <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> <children> - #include <include/ospfv3/detail.xml.i> + #include <include/frr-detail.xml.i> #include <include/ospfv3/dump.xml.i> #include <include/ospfv3/internal.xml.i> </children> diff --git a/op-mode-definitions/monitor-bridge.xml.in b/op-mode-definitions/monitor-bridge.xml.in index 712a924f1..a43fa6dd9 100644 --- a/op-mode-definitions/monitor-bridge.xml.in +++ b/op-mode-definitions/monitor-bridge.xml.in @@ -4,14 +4,14 @@ <children> <node name="bridge"> <properties> - <help>Monitoring bridge database generated objects and address changes</help> + <help>Monitor bridge database changes</help> </properties> <command>sudo bridge monitor all</command> <children> <node name="link"> <command>sudo bridge monitor link</command> <properties> - <help>Monitoring bridge database generated connection interface changes</help> + <help>Monitor bridge database generated connection interface changes</help> </properties> </node> <node name="fdb"> diff --git a/op-mode-definitions/monitor-log.xml.in b/op-mode-definitions/monitor-log.xml.in index 8f3f73478..ee52a7eb8 100644 --- a/op-mode-definitions/monitor-log.xml.in +++ b/op-mode-definitions/monitor-log.xml.in @@ -1,6 +1,9 @@ <?xml version="1.0"?> <interfaceDefinition> <node name="monitor"> + <properties> + <help>Monitor system information</help> + </properties> <children> <node name="log"> <properties> @@ -27,6 +30,12 @@ </leafNode> </children> </node> + <leafNode name="conntrack-sync"> + <properties> + <help>Monitor last lines of conntrack-sync log</help> + </properties> + <command>journalctl --no-hostname --follow --boot --unit conntrackd.service</command> + </leafNode> <node name="dhcp"> <properties> <help>Monitor last lines of Dynamic Host Control Protocol log</help> @@ -117,6 +126,23 @@ </properties> <command>journalctl --no-hostname --boot --follow --unit chrony.service</command> </leafNode> + <node name="openvpn"> + <properties> + <help>Monitor last lines of OpenVPN log</help> + </properties> + <command>journalctl --no-hostname --boot --follow --unit openvpn@*.service</command> + <children> + <tagNode name="interface"> + <properties> + <help>Monitor last lines of specific OpenVPN interface log</help> + <completionHelp> + <path>interfaces openvpn</path> + </completionHelp> + </properties> + <command>journalctl --no-hostname --boot --unit openvpn@$5.service</command> + </tagNode> + </children> + </node> <node name="pppoe"> <properties> <help>Monitor last lines of PPPoE interface log</help> @@ -248,9 +274,45 @@ </properties> <command>journalctl --no-hostname --boot --follow --unit ssh.service</command> </leafNode> + <leafNode name="vpn"> + <properties> + <help>Monitor last lines of ALL Virtual Private Network services</help> + </properties> + <command>journalctl --no-hostname --boot --follow --unit strongswan.service --unit accel-ppp@*.service --unit ocserv.service</command> + </leafNode> + <leafNode name="ipsec"> + <properties> + <help>Monitor last lines of IPsec log</help> + </properties> + <command>journalctl --no-hostname --boot --follow --unit strongswan.service</command> + </leafNode> + <leafNode name="l2tp"> + <properties> + <help>Monitor last lines of L2TP log</help> + </properties> + <command>journalctl --no-hostname --boot --follow --unit accel-ppp@l2tp.service</command> + </leafNode> + <leafNode name="openconnect"> + <properties> + <help>Monitor last lines of OpenConnect log</help> + </properties> + <command>journalctl --no-hostname --boot --follow --unit ocserv.service</command> + </leafNode> + <leafNode name="pptp"> + <properties> + <help>Monitor last lines of PPTP log</help> + </properties> + <command>journalctl --no-hostname --boot --follow --unit accel-ppp@pptp.service</command> + </leafNode> + <leafNode name="sstp"> + <properties> + <help>Monitor last lines of Secure Socket Tunneling Protocol server</help> + </properties> + <command>journalctl --no-hostname --boot --follow --unit accel-ppp@sstp.service</command> + </leafNode> <node name="sstpc"> <properties> - <help>Monitor last lines of Secure Socket Tunneling Protocol log</help> + <help>Monitor last lines of Secure Socket Tunneling Protocol client</help> </properties> <command>journalctl --no-hostname --boot --follow --unit "ppp@sstpc*.service"</command> <children> @@ -265,49 +327,6 @@ </tagNode> </children> </node> - <node name="vpn"> - <properties> - <help>Monitor Virtual Private Network services</help> - </properties> - <children> - <leafNode name="all"> - <properties> - <help>Monitor last lines of ALL VPNs</help> - </properties> - <command>journalctl --no-hostname --boot --follow --unit strongswan.service --unit accel-ppp@*.service --unit ocserv.service</command> - </leafNode> - <leafNode name="ipsec"> - <properties> - <help>Monitor last lines of IPsec log</help> - </properties> - <command>journalctl --no-hostname --boot --follow --unit strongswan.service</command> - </leafNode> - <leafNode name="l2tp"> - <properties> - <help>Monitor last lines of L2TP log</help> - </properties> - <command>journalctl --no-hostname --boot --follow --unit accel-ppp@l2tp.service</command> - </leafNode> - <leafNode name="openconnect"> - <properties> - <help>Monitor last lines of OpenConnect log</help> - </properties> - <command>journalctl --no-hostname --boot --follow --unit ocserv.service</command> - </leafNode> - <leafNode name="pptp"> - <properties> - <help>Monitor last lines of PPTP log</help> - </properties> - <command>journalctl --no-hostname --boot --follow --unit accel-ppp@pptp.service</command> - </leafNode> - <leafNode name="sstp"> - <properties> - <help>Monitor last lines of SSTP log</help> - </properties> - <command>journalctl --no-hostname --boot --follow --unit accel-ppp@sstp.service</command> - </leafNode> - </children> - </node> <leafNode name="vpp"> <properties> <help>Monitor last lines of Vector Packet Processor log</help> @@ -320,12 +339,6 @@ </properties> <command>journalctl --no-hostname --boot --follow --unit keepalived.service</command> </leafNode> - <leafNode name="webproxy"> - <properties> - <help>Monitor last lines of Webproxy log</help> - </properties> - <command>journalctl --no-hostname --boot --follow --unit squid.service</command> - </leafNode> </children> </node> </children> diff --git a/op-mode-definitions/monitor-ndp.xml.in b/op-mode-definitions/monitor-ndp.xml.in index 26d881f1a..3b08f3d73 100644 --- a/op-mode-definitions/monitor-ndp.xml.in +++ b/op-mode-definitions/monitor-ndp.xml.in @@ -4,14 +4,14 @@ <children> <node name="ndp"> <properties> - <help>Monitor the NDP information received by the router through the device</help> + <help>Monitor Neighbor Discovery Protocol (NDP) information</help> </properties> <command>sudo ndptool monitor</command> <children> <tagNode name="interface"> <command>sudo ndptool monitor --ifname=$4</command> <properties> - <help>Monitor ndp protocol on specified interface</help> + <help>Monitor Neighbor Discovery Protocol on specified interface</help> <completionHelp> <script>${vyos_completion_dir}/list_interfaces</script> </completionHelp> @@ -20,7 +20,7 @@ <tagNode name="type"> <command>sudo ndptool monitor --ifname=$4 --msg-type=$6</command> <properties> - <help>Monitor specific types of NDP protocols</help> + <help>Monitor specific Neighbor Discovery Protocol type</help> <completionHelp> <list>rs ra ns na</list> </completionHelp> @@ -31,7 +31,7 @@ <tagNode name="type"> <command>sudo ndptool monitor --msg-type=$4</command> <properties> - <help>Monitor specific types of NDP protocols</help> + <help>Monitor specific Neighbor Discovery Protocol type</help> <completionHelp> <list>rs ra ns na</list> </completionHelp> diff --git a/op-mode-definitions/monitor-protocol.xml.in b/op-mode-definitions/monitor-protocol.xml.in index f3af3575c..f05a1945f 100644 --- a/op-mode-definitions/monitor-protocol.xml.in +++ b/op-mode-definitions/monitor-protocol.xml.in @@ -12,7 +12,6 @@ <help>Monitor the Border Gateway Protocol (BGP)</help> </properties> <children> - #include <include/monitor-background.xml.i> <node name="disable"> <properties> <help>Disable Border Gateway Protocol (BGP) debugging</help> @@ -266,7 +265,6 @@ <help>Monitor Open Shortest Path First (OSPF) protocol</help> </properties> <children> - #include <include/monitor-background.xml.i> <node name="disable"> <properties> <help>Disable Open Shortest Path First (OSPF) debugging</help> @@ -650,25 +648,6 @@ <help>Monitor the IPv6 Open Shortest Path First (OSPFv3) protocol</help> </properties> <children> - <node name="background"> - <properties> - <help>Monitor in background</help> - </properties> - <children> - <node name="start"> - <properties> - <help>Start background monitoring</help> - </properties> - <command>${vyatta_bindir}/vyatta-monitor-background OSPFv3 ospf6</command> - </node> - <node name="stop"> - <properties> - <help>Stop background monitoring</help> - </properties> - <command>${vyatta_bindir}/vyatta-monitor-background-stop OSPFv3</command> - </node> - </children> - </node> <node name="disable"> <properties> <help>Disable IPv6 Open Shortest Path First (OSPFv3) protocol debugging</help> @@ -1192,25 +1171,6 @@ <help>Monitor the Routing Information Base (RIB)</help> </properties> <children> - <node name="background"> - <properties> - <help>Monitor in background</help> - </properties> - <children> - <node name="start"> - <properties> - <help>Start background monitoring</help> - </properties> - <command>${vyatta_bindir}/vyatta-monitor-background RIB zebra</command> - </node> - <node name="stop"> - <properties> - <help>Stop background monitoring</help> - </properties> - <command>${vyatta_bindir}/vyatta-monitor-background-stop RIB</command> - </node> - </children> - </node> <node name="disable"> <properties> <help>Disable Route Information Base (RIB) debugging</help> @@ -1360,7 +1320,6 @@ <help>Monitor the Routing Information Protocol (RIP)</help> </properties> <children> - #include <include/monitor-background.xml.i> <node name="disable"> <properties> <help>Disable Routing Information Protocol (RIP) debugging</help> @@ -1452,7 +1411,6 @@ <help>Monitor the Routing Information Protocol Next Generation (RIPng) protocol</help> </properties> <children> - #include <include/monitor-background.xml.i> <node name="disable"> <properties> <help>Disable Routing Information Protocol Next Generation (RIPNG) debugging</help> diff --git a/op-mode-definitions/show-bridge.xml.in b/op-mode-definitions/show-bridge.xml.in index a272ea204..fad3f3418 100644 --- a/op-mode-definitions/show-bridge.xml.in +++ b/op-mode-definitions/show-bridge.xml.in @@ -7,12 +7,20 @@ <help>Show bridging information</help> </properties> <children> - <leafNode name="vlan"> + <node name="vlan"> <properties> <help>View the VLAN filter settings of the bridge</help> </properties> <command>${vyos_op_scripts_dir}/bridge.py show_vlan</command> - </leafNode> + <children> + <leafNode name="tunnel"> + <properties> + <help>Show bridge VLAN tunnel mapping</help> + </properties> + <command>${vyos_op_scripts_dir}/bridge.py show_vlan --tunnel</command> + </leafNode> + </children> + </node> </children> </node> <leafNode name="bridge"> diff --git a/op-mode-definitions/show-evpn.xml.in b/op-mode-definitions/show-evpn.xml.in index 0bdb41e7a..a005cbc30 100644 --- a/op-mode-definitions/show-evpn.xml.in +++ b/op-mode-definitions/show-evpn.xml.in @@ -7,6 +7,34 @@ <help>Show Ethernet VPN (EVPN) information</help> </properties> <children> + <node name="access-vlan"> + <properties> + <help>Access VLANs</help> + </properties> + <children> + #include <include/frr-detail.xml.i> + </children> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </node> + <tagNode name="access-vlan"> + <properties> + <help>Access VLANs interface name</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces --bridgeable --no-vlan-subinterfaces</script> + </completionHelp> + </properties> + <children> + <node name="node.tag"> + <properties> + <help>VLAN ID</help> + <completionHelp> + <list><1-4094></list> + </completionHelp> + </properties> + <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command> + </node> + </children> + </tagNode> <node name="arp-cache"> <properties> <help>ARP and ND cache</help> diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in index 579e348f7..925a780ac 100644 --- a/op-mode-definitions/show-log.xml.in +++ b/op-mode-definitions/show-log.xml.in @@ -1,6 +1,9 @@ <?xml version="1.0"?> <interfaceDefinition> <node name="show"> + <properties> + <help>Show system information</help> + </properties> <children> <tagNode name="log"> <properties> @@ -395,23 +398,6 @@ </properties> <command>journalctl --no-hostname --boot --unit ssh.service</command> </leafNode> - <node name="sstpc"> - <properties> - <help>Show log for SSTP client</help> - </properties> - <command>journalctl --no-hostname --boot --unit "ppp@sstpc*.service"</command> - <children> - <tagNode name="interface"> - <properties> - <help>Show SSTP client log on specific interface</help> - <completionHelp> - <path>interfaces sstpc</path> - </completionHelp> - </properties> - <command>journalctl --no-hostname --boot --unit "ppp@$5.service"</command> - </tagNode> - </children> - </node> <tagNode name="tail"> <properties> <help>Show last n changes to messages</help> @@ -427,47 +413,57 @@ </properties> <command>tail -n 10 /var/log/messages</command> </node> - <node name="vpn"> + <leafNode name="vpn"> + <properties> + <help>Monitor last lines of ALL Virtual Private Network services</help> + </properties> + <command>journalctl --no-hostname --boot --unit strongswan.service --unit accel-ppp@*.service --unit ocserv.service</command> + </leafNode> + <leafNode name="ipsec"> + <properties> + <help>Show log for IPsec</help> + </properties> + <command>journalctl --no-hostname --boot --unit strongswan.service</command> + </leafNode> + <leafNode name="l2tp"> + <properties> + <help>Show log for L2TP</help> + </properties> + <command>journalctl --no-hostname --boot --unit accel-ppp@l2tp.service</command> + </leafNode> + <leafNode name="openconnect"> + <properties> + <help>Show log for OpenConnect</help> + </properties> + <command>journalctl --no-hostname --boot --unit ocserv.service</command> + </leafNode> + <leafNode name="pptp"> + <properties> + <help>Show log for PPTP</help> + </properties> + <command>journalctl --no-hostname --boot --unit accel-ppp@pptp.service</command> + </leafNode> + <leafNode name="sstp"> + <properties> + <help>Show log for Secure Socket Tunneling Protocol (SSTP) server</help> + </properties> + <command>journalctl --no-hostname --boot --unit accel-ppp@sstp.service</command> + </leafNode> + <node name="sstpc"> <properties> - <help>Show log for Virtual Private Network (VPN)</help> + <help>Show log for Secure Socket Tunneling Protocol (SSTP) client</help> </properties> + <command>journalctl --no-hostname --boot --unit "ppp@sstpc*.service"</command> <children> - <leafNode name="all"> - <properties> - <help>Show log for ALL</help> - </properties> - <command>journalctl --no-hostname --boot --unit strongswan.service --unit accel-ppp@*.service --unit ocserv.service</command> - </leafNode> - <leafNode name="ipsec"> - <properties> - <help>Show log for IPsec</help> - </properties> - <command>journalctl --no-hostname --boot --unit strongswan.service</command> - </leafNode> - <leafNode name="l2tp"> - <properties> - <help>Show log for L2TP</help> - </properties> - <command>journalctl --no-hostname --boot --unit accel-ppp@l2tp.service</command> - </leafNode> - <leafNode name="openconnect"> - <properties> - <help>Show log for OpenConnect</help> - </properties> - <command>journalctl --no-hostname --boot --unit ocserv.service</command> - </leafNode> - <leafNode name="pptp"> - <properties> - <help>Show log for PPTP</help> - </properties> - <command>journalctl --no-hostname --boot --unit accel-ppp@pptp.service</command> - </leafNode> - <leafNode name="sstp"> + <tagNode name="interface"> <properties> - <help>Show log for SSTP</help> + <help>Show SSTP client log on specific interface</help> + <completionHelp> + <path>interfaces sstpc</path> + </completionHelp> </properties> - <command>journalctl --no-hostname --boot --unit accel-ppp@sstp.service</command> - </leafNode> + <command>journalctl --no-hostname --boot --unit "ppp@$5.service"</command> + </tagNode> </children> </node> <leafNode name="vpp"> diff --git a/op-mode-definitions/webproxy.xml.in b/op-mode-definitions/webproxy.xml.in index 5ae1577d8..57df44ff8 100644 --- a/op-mode-definitions/webproxy.xml.in +++ b/op-mode-definitions/webproxy.xml.in @@ -2,43 +2,28 @@ <interfaceDefinition> <node name="monitor"> <children> - <node name="webproxy"> - <properties> - <help>Monitor WebProxy service</help> - </properties> - <command>${vyatta_bindir}/vyatta-monitor Webproxy squid</command> + <node name="log"> <children> - <node name="access-log"> - <properties> - <help>Monitor the last lines of the squid access log</help> - </properties> - <command>if [ -f /var/log/squid/access.log ]; then sudo tail --follow=name /var/log/squid/access.log; else echo "WebProxy access-log does not exist"; fi</command> - </node> - <node name="background"> + <node name="webproxy"> <properties> - <help>Monitor Webproxy in the background</help> + <help>Monitor last lines of Webproxy log</help> </properties> + <command>journalctl --no-hostname --boot --follow --unit squid.service</command> <children> - <node name="start"> + <leafNode name="access-log"> <properties> - <help>Start background monitoring of Webproxy</help> + <help>Monitor the last lines of the Webproxy access log</help> </properties> - <command>${vyatta_bindir}/vyatta-monitor-background Webproxy squid</command> - </node> - <node name="stop"> + <command>if [ -f /var/log/squid/access.log ]; then sudo tail --follow=name /var/log/squid/access.log; else echo "WebProxy access-log does not exist"; fi</command> + </leafNode> + <leafNode name="cache-log"> <properties> - <help>Stop background monitoring of Webproxy</help> + <help>Monitor the last lines of the Webproxy cache log</help> </properties> - <command>${vyatta_bindir}/vyatta-monitor-background-stop Webproxy </command> - </node> + <command>if [ -f /var/log/squid/cache.log ]; then sudo tail --follow=name /var/log/squid/cache.log; else echo "WebProxy cache-log does not exist"; fi</command> + </leafNode> </children> </node> - <node name="cache-log"> - <properties> - <help>Monitor the last lines of the squid cache log</help> - </properties> - <command>if [ -f /var/log/squid/cache.log ]; then sudo tail --follow=name /var/log/squid/cache.log; else echo "WebProxy cache-log does not exist"; fi</command> - </node> </children> </node> </children> @@ -102,6 +87,17 @@ <help>Update the webproxy blacklist database</help> </properties> <command>sudo ${vyos_op_scripts_dir}/webproxy_update_blacklist.sh --update-blacklist</command> + <children> + <tagNode name="vrf"> + <properties> + <help>Update webproxy blacklist database via specified VRF</help> + <completionHelp> + <path>vrf name</path> + </completionHelp> + </properties> + <command>sudo ${vyos_op_scripts_dir}/webproxy_update_blacklist.sh --update-blacklist --vrf "${5}" </command> + </tagNode> + </children> </node> </children> </node> diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py index d0cd87464..e18d9817d 100644 --- a/python/vyos/configtree.py +++ b/python/vyos/configtree.py @@ -418,10 +418,6 @@ class DiffTree: self.__diff_tree.argtypes = [c_char_p, c_void_p, c_void_p] self.__diff_tree.restype = c_void_p - self.__trim_tree = self.__lib.trim_tree - self.__trim_tree.argtypes = [c_void_p, c_void_p] - self.__trim_tree.restype = c_void_p - check_path(path) path_str = " ".join(map(str, path)).encode() @@ -435,11 +431,7 @@ class DiffTree: self.add = self.full.get_subtree(['add']) self.sub = self.full.get_subtree(['sub']) self.inter = self.full.get_subtree(['inter']) - - # trim sub(-tract) tree to get delete tree for commands - ref = self.right.get_subtree(path, with_node=True) if path else self.right - res = self.__trim_tree(self.sub._get_config(), ref._get_config()) - self.delete = ConfigTree(address=res) + self.delete = self.full.get_subtree(['del']) def to_commands(self): add = self.add.to_commands() diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index 2793b201c..903cc8535 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -304,7 +304,7 @@ def parse_rule(rule_conf, fw_name, rule_id, ip_name): if 'ipsec' in rule_conf: if 'match_ipsec' in rule_conf['ipsec']: output.append('meta ipsec == 1') - if 'match_non_ipsec' in rule_conf['ipsec']: + if 'match_none' in rule_conf['ipsec']: output.append('meta ipsec == 0') if 'fragment' in rule_conf: diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 120f2131b..99ddb2021 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -1288,9 +1288,11 @@ class Interface(Control): ifname = self.ifname config_file = f'/run/dhcp6c/dhcp6c.{ifname}.conf' + options_file = f'/run/dhcp6c/dhcp6c.{ifname}.options' systemd_service = f'dhcp6c@{ifname}.service' if enable and 'disable' not in self._config: + render(options_file, 'dhcp-client/dhcp6c_daemon-options.j2', self._config) render(config_file, 'dhcp-client/ipv6.j2', self._config) # We must ignore any return codes. This is required to enable diff --git a/python/vyos/xml_ref/generate_cache.py b/python/vyos/xml_ref/generate_cache.py index 792c6eea7..6a05d4608 100755 --- a/python/vyos/xml_ref/generate_cache.py +++ b/python/vyos/xml_ref/generate_cache.py @@ -18,10 +18,14 @@ import sys import json -import argparse +from argparse import ArgumentParser +from argparse import ArgumentTypeError +from os import getcwd +from os import makedirs from os.path import join from os.path import abspath from os.path import dirname +from os.path import basename from xmltodict import parse _here = dirname(__file__) @@ -29,9 +33,10 @@ _here = dirname(__file__) sys.path.append(join(_here, '..')) from configtree import reference_tree_to_json, ConfigTreeError -xml_cache = abspath(join(_here, 'cache.py')) xml_cache_json = 'xml_cache.json' xml_tmp = join('/tmp', xml_cache_json) +pkg_cache = abspath(join(_here, 'pkg_cache')) +ref_cache = abspath(join(_here, 'cache.py')) node_data_fields = ("node_type", "multi", "valueless", "default_value") @@ -45,16 +50,26 @@ def trim_node_data(cache: dict): if isinstance(cache[k], dict): trim_node_data(cache[k]) +def non_trivial(s): + if not s: + raise ArgumentTypeError("Argument must be non empty string") + return s + def main(): - parser = argparse.ArgumentParser(description='generate and save dict from xml defintions') + parser = ArgumentParser(description='generate and save dict from xml defintions') parser.add_argument('--xml-dir', type=str, required=True, help='transcluded xml interface-definition directory') - parser.add_argument('--save-json-dir', type=str, - help='directory to save json cache if needed') - args = parser.parse_args() - - xml_dir = abspath(args.xml_dir) - save_dir = abspath(args.save_json_dir) if args.save_json_dir else None + parser.add_argument('--package-name', type=non_trivial, default='vyos-1x', + help='name of current package') + parser.add_argument('--output-path', help='path to generated cache') + args = vars(parser.parse_args()) + + xml_dir = abspath(args['xml_dir']) + pkg_name = args['package_name'].replace('-','_') + cache_name = pkg_name + '_cache.py' + out_path = args['output_path'] + path = out_path if out_path is not None else pkg_cache + xml_cache = abspath(join(path, cache_name)) try: reference_tree_to_json(xml_dir, xml_tmp) @@ -67,21 +82,30 @@ def main(): trim_node_data(d) - if save_dir is not None: - save_file = join(save_dir, xml_cache_json) - with open(save_file, 'w') as f: - f.write(json.dumps(d)) - syntax_version = join(xml_dir, 'xml-component-version.xml') - with open(syntax_version) as f: - content = f.read() + try: + with open(syntax_version) as f: + component = f.read() + except FileNotFoundError: + if pkg_name != 'vyos_1x': + component = '' + else: + print("\nWARNING: missing xml-component-version.xml\n") + sys.exit(1) - parsed = parse(content) - converted = parsed['interfaceDefinition']['syntaxVersion'] + if component: + parsed = parse(component) + else: + parsed = None version = {} - for i in converted: - tmp = {i['@component']: i['@version']} - version |= tmp + # addon package definitions may have empty (== 0) version info + if parsed is not None and parsed['interfaceDefinition'] is not None: + converted = parsed['interfaceDefinition']['syntaxVersion'] + if not isinstance(converted, list): + converted = [converted] + for i in converted: + tmp = {i['@component']: i['@version']} + version |= tmp version = {"component_version": version} @@ -90,5 +114,7 @@ def main(): with open(xml_cache, 'w') as f: f.write(f'reference = {str(d)}') + print(cache_name) + if __name__ == '__main__': main() diff --git a/python/vyos/xml_ref/pkg_cache/__init__.py b/python/vyos/xml_ref/pkg_cache/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/python/vyos/xml_ref/pkg_cache/__init__.py diff --git a/python/vyos/xml_ref/update_cache.py b/python/vyos/xml_ref/update_cache.py new file mode 100755 index 000000000..0842bcbe9 --- /dev/null +++ b/python/vyos/xml_ref/update_cache.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +import os +from copy import deepcopy +from generate_cache import pkg_cache +from generate_cache import ref_cache + +def dict_merge(source, destination): + dest = deepcopy(destination) + + for key, value in source.items(): + if key not in dest: + dest[key] = value + elif isinstance(source[key], dict): + dest[key] = dict_merge(source[key], dest[key]) + + return dest + +def main(): + res = {} + cache_dir = os.path.basename(pkg_cache) + for mod in os.listdir(pkg_cache): + mod = os.path.splitext(mod)[0] + if not mod.endswith('_cache'): + continue + d = getattr(__import__(f'{cache_dir}.{mod}', fromlist=[mod]), 'reference') + if mod == 'vyos_1x_cache': + res = dict_merge(res, d) + else: + res = dict_merge(d, res) + + with open(ref_cache, 'w') as f: + f.write(f'reference = {str(res)}') + +if __name__ == '__main__': + main() diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py index b4afac0e2..a3868fa70 100644 --- a/smoketest/scripts/cli/base_interfaces_test.py +++ b/smoketest/scripts/cli/base_interfaces_test.py @@ -791,6 +791,7 @@ class BasicInterfaceTest: # Enable DHCPv6 client self.cli_set(path + ['address', 'dhcpv6']) + self.cli_set(path + ['dhcpv6-options', 'no-release']) self.cli_set(path + ['dhcpv6-options', 'rapid-commit']) self.cli_set(path + ['dhcpv6-options', 'parameters-only']) self.cli_set(path + ['dhcpv6-options', 'duid', duid]) @@ -798,6 +799,9 @@ class BasicInterfaceTest: self.cli_commit() + dhcp6c_options = read_file(f'/run/dhcp6c/dhcp6c.{interface}.options') + self.assertIn(f'-n', dhcp6c_options) + duid_base = 10 for interface in self._interfaces: duid = '00:01:00:01:27:71:db:f0:00:50:00:00:00:{}'.format(duid_base) diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index 2e4bea377..3bef9b8f6 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -88,32 +88,45 @@ def get_config(config=None): conf = Config() base = ['interfaces', 'openvpn'] - tmp_pki = conf.get_config_dict(['pki'], key_mangling=('-', '_'), - get_first_key=True, no_tag_node_value_mangle=True) - ifname, openvpn = get_interface_dict(conf, base) - - if 'deleted' not in openvpn: - openvpn['pki'] = tmp_pki - if is_node_changed(conf, base + [ifname, 'openvpn-option']): - openvpn.update({'restart_required': {}}) - if is_node_changed(conf, base + [ifname, 'enable-dco']): - openvpn.update({'restart_required': {}}) - - # We have to get the dict using 'get_config_dict' instead of 'get_interface_dict' - # as 'get_interface_dict' merges the defaults in, so we can not check for defaults in there. - tmp = conf.get_config_dict(base + [openvpn['ifname']], get_first_key=True) - - # We have to cleanup the config dict, as default values could enable features - # which are not explicitly enabled on the CLI. Example: server mfa totp - # originate comes with defaults, which will enable the - # totp plugin, even when not set via CLI so we - # need to check this first and drop those keys - if dict_search('server.mfa.totp', tmp) == None: - del openvpn['server']['mfa'] - openvpn['auth_user_pass_file'] = '/run/openvpn/{ifname}.pw'.format(**openvpn) + if 'deleted' in openvpn: + return openvpn + + openvpn['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True) + + if is_node_changed(conf, base + [ifname, 'openvpn-option']): + openvpn.update({'restart_required': {}}) + if is_node_changed(conf, base + [ifname, 'enable-dco']): + openvpn.update({'restart_required': {}}) + + # We have to get the dict using 'get_config_dict' instead of 'get_interface_dict' + # as 'get_interface_dict' merges the defaults in, so we can not check for defaults in there. + tmp = conf.get_config_dict(base + [openvpn['ifname']], get_first_key=True) + + # We have to cleanup the config dict, as default values could enable features + # which are not explicitly enabled on the CLI. Example: server mfa totp + # originate comes with defaults, which will enable the + # totp plugin, even when not set via CLI so we + # need to check this first and drop those keys + if dict_search('server.mfa.totp', tmp) == None: + del openvpn['server']['mfa'] + + # OpenVPN Data-Channel-Offload (DCO) is a Kernel module. If loaded it applies to all + # OpenVPN interfaces. Check if DCO is used by any other interface instance. + tmp = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + for interface, interface_config in tmp.items(): + # If one interface has DCO configured, enable it. No need to further check + # all other OpenVPN interfaces. We must use a dedicated key to indicate + # the Kernel module must be loaded or not. The per interface "offload.dco" + # key is required per OpenVPN interface instance. + if dict_search('offload.dco', interface_config) != None: + openvpn['module_load_dco'] = {} + break + return openvpn def is_ec_private_key(pki, cert_name): @@ -674,6 +687,15 @@ def apply(openvpn): if interface in interfaces(): VTunIf(interface).remove() + # dynamically load/unload DCO Kernel extension if requested + dco_module = 'ovpn_dco_v2' + if 'module_load_dco' in openvpn: + check_kmod(dco_module) + else: + unload_kmod(dco_module) + + # Now bail out early if interface is disabled or got deleted + if 'deleted' in openvpn or 'disable' in openvpn: return None # verify specified IP address is present on any interface on this system @@ -683,13 +705,6 @@ def apply(openvpn): if not is_addr_assigned(openvpn['local_host']): cmd('sysctl -w net.ipv4.ip_nonlocal_bind=1') - # dynamically load/unload DCO Kernel extension if requested - dco_module = 'ovpn_dco_v2' - if 'enable_dco' in openvpn: - check_kmod(dco_module) - else: - unload_kmod(dco_module) - # No matching OpenVPN process running - maybe it got killed or none # existed - nevertheless, spawn new OpenVPN process action = 'reload-or-restart' diff --git a/src/conf_mode/interfaces-wwan.py b/src/conf_mode/interfaces-wwan.py index 6658ca86a..2515dc838 100755 --- a/src/conf_mode/interfaces-wwan.py +++ b/src/conf_mode/interfaces-wwan.py @@ -75,7 +75,6 @@ def get_config(config=None): # We need to know the amount of other WWAN interfaces as ModemManager needs # to be started or stopped. - conf.set_level(base) wwan['other_interfaces'] = conf.get_config_dict([], key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index cec025fea..7b9f15505 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -475,6 +475,8 @@ def verify(bgp): if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']): raise ConfigError( 'Command "import vrf" conflicts with "rd vpn export" command!') + if not dict_search('parameters.router_id', bgp): + Warning(f'BGP "router-id" is required when using "rd" and "route-target"!') if dict_search('route_target.vpn.both', afi_config): if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']): diff --git a/src/conf_mode/service_ids_fastnetmon.py b/src/conf_mode/service_ids_fastnetmon.py index 2e678cf0b..f6b80552b 100755 --- a/src/conf_mode/service_ids_fastnetmon.py +++ b/src/conf_mode/service_ids_fastnetmon.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2022 VyOS maintainers and contributors +# Copyright (C) 2018-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -30,6 +30,7 @@ airbag.enable() config_file = r'/run/fastnetmon/fastnetmon.conf' networks_list = r'/run/fastnetmon/networks_list' excluded_networks_list = r'/run/fastnetmon/excluded_networks_list' +attack_dir = '/var/log/fastnetmon_attacks' def get_config(config=None): if config: @@ -55,8 +56,11 @@ def verify(fastnetmon): if 'mode' not in fastnetmon: raise ConfigError('Specify operating mode!') - if 'listen_interface' not in fastnetmon: - raise ConfigError('Specify interface(s) for traffic capture') + if fastnetmon.get('mode') == 'mirror' and 'listen_interface' not in fastnetmon: + raise ConfigError("Incorrect settings for 'mode mirror': must specify interface(s) for traffic mirroring") + + if fastnetmon.get('mode') == 'sflow' and 'listen_address' not in fastnetmon.get('sflow', {}): + raise ConfigError("Incorrect settings for 'mode sflow': must specify sFlow 'listen-address'") if 'alert_script' in fastnetmon: if os.path.isfile(fastnetmon['alert_script']): @@ -74,6 +78,10 @@ def generate(fastnetmon): return None + # Create dir for log attack details + if not os.path.exists(attack_dir): + os.mkdir(attack_dir) + render(config_file, 'ids/fastnetmon.j2', fastnetmon) render(networks_list, 'ids/fastnetmon_networks_list.j2', fastnetmon) render(excluded_networks_list, 'ids/fastnetmon_excluded_networks_list.j2', fastnetmon) diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login.py index afd75913e..82941e0c0 100755 --- a/src/conf_mode/system-login.py +++ b/src/conf_mode/system-login.py @@ -54,7 +54,7 @@ MAX_USER_UID: int = 59999 # LOGIN_TIMEOUT from /etc/loign.defs minus 10 sec MAX_RADIUS_TIMEOUT: int = 50 # MAX_RADIUS_TIMEOUT divided by 2 sec (minimum recomended timeout) -MAX_RADIUS_COUNT: int = 25 +MAX_RADIUS_COUNT: int = 8 # Maximum number of supported TACACS servers MAX_TACACS_COUNT: int = 8 diff --git a/src/conf_mode/system-option.py b/src/conf_mode/system-option.py index 5172b492e..1495e9223 100755 --- a/src/conf_mode/system-option.py +++ b/src/conf_mode/system-option.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright (C) 2019-2023 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -36,6 +36,11 @@ airbag.enable() curlrc_config = r'/etc/curlrc' ssh_config = r'/etc/ssh/ssh_config.d/91-vyos-ssh-client-options.conf' systemd_action_file = '/lib/systemd/system/ctrl-alt-del.target' +time_format_to_locale = { + '12-hour': 'en_US.UTF-8', + '24-hour': 'en_GB.UTF-8' +} + def get_config(config=None): if config: @@ -143,6 +148,11 @@ def apply(options): else: cmd('systemctl disable root-partition-auto-resize.service') + # Time format 12|24-hour + if 'time_format' in options: + time_format = time_format_to_locale.get(options['time_format']) + cmd(f'localectl set-locale LC_TIME={time_format}') + if __name__ == '__main__': try: c = get_config() diff --git a/src/op_mode/bridge.py b/src/op_mode/bridge.py index 1834b9cc9..185db4f20 100755 --- a/src/op_mode/bridge.py +++ b/src/op_mode/bridge.py @@ -29,7 +29,6 @@ from vyos.utils.dict import dict_search import vyos.opmode - def _get_json_data(): """ Get bridge data format JSON @@ -46,11 +45,14 @@ def _get_raw_data_summary(): return data_dict -def _get_raw_data_vlan(): +def _get_raw_data_vlan(tunnel:bool=False): """ :returns dict """ - json_data = cmd('bridge --json --compressvlans vlan show') + show = 'show' + if tunnel: + show = 'tunnel' + json_data = cmd(f'bridge --json --compressvlans vlan {show}') data_dict = json.loads(json_data) return data_dict @@ -134,10 +136,34 @@ def _get_formatted_output_vlan(data): flags = ', '.join(flags_raw if isinstance(flags_raw,list) else "").lower() data_entries.append([interface, vlan, flags]) - headers = ["Interface", "Vlan", "Flags"] + headers = ["Interface", "VLAN", "Flags"] output = tabulate(data_entries, headers) return output +def _get_formatted_output_vlan_tunnel(data): + data_entries = [] + for entry in data: + interface = entry.get('ifname') + first = True + for tunnel_entry in entry.get('tunnels'): + vlan = tunnel_entry.get('vlan') + vni = tunnel_entry.get('tunid') + if first: + data_entries.append([interface, vlan, vni]) + first = False + else: + # Group by VXLAN interface only - no need to repeat + # VXLAN interface name for every VLAN <-> VNI mapping + # + # Interface VLAN VNI + # ----------- ------ ----- + # vxlan0 100 100 + # 200 200 + data_entries.append(['', vlan, vni]) + + headers = ["Interface", "VLAN", "VNI"] + output = tabulate(data_entries, headers) + return output def _get_formatted_output_fdb(data): data_entries = [] @@ -192,12 +218,15 @@ def show(raw: bool): return _get_formatted_output_summary(bridge_data) -def show_vlan(raw: bool): - bridge_vlan = _get_raw_data_vlan() +def show_vlan(raw: bool, tunnel: typing.Optional[bool]): + bridge_vlan = _get_raw_data_vlan(tunnel) if raw: return bridge_vlan else: - return _get_formatted_output_vlan(bridge_vlan) + if tunnel: + return _get_formatted_output_vlan_tunnel(bridge_vlan) + else: + return _get_formatted_output_vlan(bridge_vlan) def show_fdb(raw: bool, interface: str): diff --git a/src/op_mode/dhcp.py b/src/op_mode/dhcp.py index 3e51e990b..20ef698bd 100755 --- a/src/op_mode/dhcp.py +++ b/src/op_mode/dhcp.py @@ -14,10 +14,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import os import sys import typing from datetime import datetime +from glob import glob from ipaddress import ip_address from isc_dhcp_leases import IscDhcpLeases from tabulate import tabulate @@ -27,10 +29,13 @@ import vyos.opmode from vyos.base import Warning from vyos.configquery import ConfigTreeQuery -from vyos.utils.process import cmd from vyos.utils.dict import dict_search +from vyos.utils.file import read_file +from vyos.utils.process import cmd from vyos.utils.process import is_systemd_service_running +time_string = "%a %b %d %H:%M:%S %Z %Y" + config = ConfigTreeQuery() lease_valid_states = ['all', 'active', 'free', 'expired', 'released', 'abandoned', 'reset', 'backup'] sort_valid_inet = ['end', 'mac', 'hostname', 'ip', 'pool', 'remaining', 'start', 'state'] @@ -287,6 +292,87 @@ def show_server_leases(raw: bool, family: ArgFamily, pool: typing.Optional[str], return _get_formatted_server_leases(lease_data, family=family) +def _get_raw_client_leases(family='inet', interface=None): + from time import mktime + from datetime import datetime + + lease_dir = '/var/lib/dhcp' + lease_files = [] + lease_data = [] + + if interface: + tmp = f'{lease_dir}/dhclient_{interface}.lease' + if os.path.exists(tmp): + lease_files.append(tmp) + else: + # All DHCP leases + lease_files = glob(f'{lease_dir}/dhclient_*.lease') + + for lease in lease_files: + tmp = {} + with open(lease, 'r') as f: + for line in f.readlines(): + line = line.rstrip() + if 'last_update' not in tmp: + # ISC dhcp client contains least_update timestamp in human readable + # format this makes less sense for an API and also the expiry + # timestamp is provided in UNIX time. Convert string (e.g. Sun Jul + # 30 18:13:44 CEST 2023) to UNIX time (1690733624) + tmp.update({'last_update' : int(mktime(datetime.strptime(line, time_string).timetuple()))}) + continue + + k, v = line.split('=') + tmp.update({k : v.replace("'", "")}) + + lease_data.append(tmp) + + return lease_data + +def _get_formatted_client_leases(lease_data, family): + from time import localtime + from time import strftime + + from vyos.validate import is_intf_addr_assigned + + data_entries = [] + for lease in lease_data: + data_entries.append(["Interface", lease['interface']]) + if 'new_ip_address' in lease: + tmp = '[Active]' if is_intf_addr_assigned(lease['interface'], lease['new_ip_address']) else '[Inactive]' + data_entries.append(["IP address", lease['new_ip_address'], tmp]) + if 'new_subnet_mask' in lease: + data_entries.append(["Subnet Mask", lease['new_subnet_mask']]) + if 'new_domain_name' in lease: + data_entries.append(["Domain Name", lease['new_domain_name']]) + if 'new_routers' in lease: + data_entries.append(["Router", lease['new_routers']]) + if 'new_domain_name_servers' in lease: + data_entries.append(["Name Server", lease['new_domain_name_servers']]) + if 'new_dhcp_server_identifier' in lease: + data_entries.append(["DHCP Server", lease['new_dhcp_server_identifier']]) + if 'new_dhcp_lease_time' in lease: + data_entries.append(["DHCP Server", lease['new_dhcp_lease_time']]) + if 'last_update' in lease: + tmp = strftime(time_string, localtime(int(lease['last_update']))) + data_entries.append(["Last Update", tmp]) + if 'new_expiry' in lease: + tmp = strftime(time_string, localtime(int(lease['new_expiry']))) + data_entries.append(["Expiry", tmp]) + + # Add empty marker + data_entries.append(['']) + + output = tabulate(data_entries, tablefmt='plain') + + return output + +def show_client_leases(raw: bool, family: ArgFamily, interface: typing.Optional[str]): + lease_data = _get_raw_client_leases(family=family, interface=interface) + if raw: + return lease_data + else: + return _get_formatted_client_leases(lease_data, family=family) + if __name__ == '__main__': try: res = vyos.opmode.run(sys.modules[__name__]) diff --git a/src/op_mode/webproxy_update_blacklist.sh b/src/op_mode/webproxy_update_blacklist.sh index 4fb9a54c6..05ea86f9e 100755 --- a/src/op_mode/webproxy_update_blacklist.sh +++ b/src/op_mode/webproxy_update_blacklist.sh @@ -45,6 +45,9 @@ do --auto-update-blacklist) auto="yes" ;; + --vrf) + vrf="yes" + ;; (-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;; (*) break;; esac @@ -76,7 +79,11 @@ fi if [[ -n $update ]] && [[ $update -eq "yes" ]]; then tmp_blacklists='/tmp/blacklists.gz' - curl -o $tmp_blacklists $blacklist_url + if [[ -n $vrf ]] && [[ $vrf -eq "yes" ]]; then + sudo ip vrf exec $1 curl -o $tmp_blacklists $blacklist_url + else + curl -o $tmp_blacklists $blacklist_url + fi if [ $? -ne 0 ]; then echo "Unable to download [$blacklist_url]!" exit 1 diff --git a/src/systemd/dhcp6c@.service b/src/systemd/dhcp6c@.service index 9a97ee261..495cb7e26 100644 --- a/src/systemd/dhcp6c@.service +++ b/src/systemd/dhcp6c@.service @@ -2,14 +2,16 @@ Description=WIDE DHCPv6 client on %i Documentation=man:dhcp6c(8) man:dhcp6c.conf(5) ConditionPathExists=/run/dhcp6c/dhcp6c.%i.conf +ConditionPathExists=/run/dhcp6c/dhcp6c.%i.options After=vyos-router.service StartLimitIntervalSec=0 [Service] WorkingDirectory=/run/dhcp6c +EnvironmentFile=-/run/dhcp6c/dhcp6c.%i.options Type=forking PIDFile=/run/dhcp6c/dhcp6c.%i.pid -ExecStart=/usr/sbin/dhcp6c -D -k /run/dhcp6c/dhcp6c.%i.sock -c /run/dhcp6c/dhcp6c.%i.conf -p /run/dhcp6c/dhcp6c.%i.pid %i +ExecStart=/usr/sbin/dhcp6c $DHCP6C_OPTS Restart=on-failure RestartSec=20 |