diff options
| author | Matthew Kobayashi <matthew@kobayashi.au> | 2025-10-02 13:15:03 +1000 |
|---|---|---|
| committer | Kyrylo Yatsenko <hedrok@gmail.com> | 2025-10-21 19:57:40 +0300 |
| commit | 70b7818f75f55de14214b85a12b8ec13d98ff89b (patch) | |
| tree | 1da8eb1813602f444da9404dcedb00f2c2c3bffc /src | |
| parent | 2de4e9df6382edbb4b2af6148ef267854fa7ebbf (diff) | |
| download | vyos-1x-70b7818f75f55de14214b85a12b8ec13d98ff89b.tar.gz vyos-1x-70b7818f75f55de14214b85a12b8ec13d98ff89b.zip | |
T3680: protocols: add dhclient hooks for dhcp-interface static routes
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/protocols_static.py | 19 | ||||
| -rwxr-xr-x | src/etc/dhcp/dhclient-enter-hooks.d/98-vyos-static-routes-dhclient-hook | 42 | ||||
| -rwxr-xr-x | src/etc/dhcp/dhclient-exit-hooks.d/97-run-user-hooks (renamed from src/etc/dhcp/dhclient-exit-hooks.d/98-run-user-hooks) | 0 | ||||
| -rwxr-xr-x | src/etc/dhcp/dhclient-exit-hooks.d/98-vyos-static-routes-dhclient-hook | 48 |
4 files changed, 109 insertions, 0 deletions
diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py index 7c730ca81..1db8aa770 100755 --- a/src/conf_mode/protocols_static.py +++ b/src/conf_mode/protocols_static.py @@ -17,6 +17,7 @@ from ipaddress import IPv4Network from sys import exit from sys import argv +import os from vyos.config import Config from vyos.configverify import has_frr_protocol_in_dict @@ -25,12 +26,14 @@ from vyos.configverify import verify_vrf from vyos.frrender import FRRender from vyos.frrender import get_frrender_dict from vyos.utils.process import is_systemd_service_running +from vyos.utils.file import write_file from vyos.template import render from vyos import ConfigError from vyos import airbag airbag.enable() config_file = '/etc/iproute2/rt_tables.d/vyos-static.conf' +DHCP_HOOK_IFLIST = '/tmp/static_dhcp_interfaces' def get_config(config=None): if config: @@ -92,6 +95,22 @@ def generate(config_dict): # eqivalent of the C foo ? 'a' : 'b' statement static = vrf and config_dict['vrf']['name'][vrf]['protocols']['static'] or config_dict['static'] + # Collect interfaces that have DHCP configuration for DHCP hooks + dhcp_interfaces = set() + + # Check for DHCP interfaces in route configurations + if 'route' in static: + for prefix, prefix_options in static['route'].items(): + if 'dhcp_interface' in prefix_options: + for interface_name in prefix_options['dhcp_interface']: + dhcp_interfaces.add(interface_name) + + # Write the interface list for DHCP hooks or clean up if empty + if dhcp_interfaces: + write_file(DHCP_HOOK_IFLIST, " ".join(dhcp_interfaces)) + elif os.path.exists(DHCP_HOOK_IFLIST): + os.unlink(DHCP_HOOK_IFLIST) + # Put routing table names in /etc/iproute2/rt_tables render(config_file, 'iproute2/static.conf.j2', static) diff --git a/src/etc/dhcp/dhclient-enter-hooks.d/98-vyos-static-routes-dhclient-hook b/src/etc/dhcp/dhclient-enter-hooks.d/98-vyos-static-routes-dhclient-hook new file mode 100755 index 000000000..f735b4b29 --- /dev/null +++ b/src/etc/dhcp/dhclient-enter-hooks.d/98-vyos-static-routes-dhclient-hook @@ -0,0 +1,42 @@ +#!/bin/bash +# +# Copyright VyOS maintainers and contributors <maintainers@vyos.io> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# 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/>. + +DHCP_HOOK_IFLIST="/tmp/static_dhcp_interfaces" + +# Only run if there are static routes with dhcp-interface configured +if ! { [ -f $DHCP_HOOK_IFLIST ] && grep -qw $interface $DHCP_HOOK_IFLIST; }; then + return 0 +fi + +# Handle interface state changes that require static route regeneration +# - PREINIT: interface is about to be configured, cleanup old routes +# - EXPIRE: lease has expired, remove routes +# - FAIL: DHCP failed, remove routes +# - RELEASE: lease released, remove routes +# - STOP: dhclient stopped, remove routes +if [ "$reason" == "PREINIT" ] || [ "$reason" == "EXPIRE" ] || [ "$reason" == "FAIL" ] || [ "$reason" == "RELEASE" ] || [ "$reason" == "STOP" ]; then + # Best effort wait for any active commit to finish + sudo python3 - <<PYEND +from vyos.utils.commit import wait_for_commit_lock + +if __name__ == '__main__': + wait_for_commit_lock() + exit(0) +PYEND + + # Re-generate static routes config to remove routes that depend on this interface + sudo /usr/libexec/vyos/conf_mode/protocols_static.py +fi diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/98-run-user-hooks b/src/etc/dhcp/dhclient-exit-hooks.d/97-run-user-hooks index 910b586f0..910b586f0 100755 --- a/src/etc/dhcp/dhclient-exit-hooks.d/98-run-user-hooks +++ b/src/etc/dhcp/dhclient-exit-hooks.d/97-run-user-hooks diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/98-vyos-static-routes-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/98-vyos-static-routes-dhclient-hook new file mode 100755 index 000000000..f2eef67f3 --- /dev/null +++ b/src/etc/dhcp/dhclient-exit-hooks.d/98-vyos-static-routes-dhclient-hook @@ -0,0 +1,48 @@ +#!/bin/bash +# +# Copyright VyOS maintainers and contributors <maintainers@vyos.io> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# 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/>. + +DHCP_HOOK_IFLIST="/tmp/static_dhcp_interfaces" + +# Only run if there are static routes with dhcp-interface configured +if ! { [ -f $DHCP_HOOK_IFLIST ] && grep -qw $interface $DHCP_HOOK_IFLIST; }; then + return 0 +fi + +# Re-generate the config on the following events: +# - BOUND: always re-generate +# - RENEW: re-generate if the IP address changed +# - REBIND: re-generate if the IP address changed +# - EXPIRE: always re-generate (route should be removed) +# - RELEASE: always re-generate (route should be removed) +if [ "$reason" == "RENEW" ] || [ "$reason" == "REBIND" ]; then + if [ "$old_routers" == "$new_routers" ]; then + return 0 + fi +elif [ "$reason" != "BOUND" ] && [ "$reason" != "EXPIRE" ] && [ "$reason" != "RELEASE" ]; then + return 0 +fi + +# Best effort wait for any active commit to finish +sudo python3 - <<PYEND +from vyos.utils.commit import wait_for_commit_lock + +if __name__ == '__main__': + wait_for_commit_lock() + exit(0) +PYEND + +# Now re-generate the static routes config +sudo /usr/libexec/vyos/conf_mode/protocols_static.py |
