summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-02-24 21:51:10 +0100
committerChristian Poessinger <christian@poessinger.com>2021-02-24 21:53:54 +0100
commit9bcd5adf878dfa9f5c621f8b0043ef7f94cdb4b1 (patch)
treea6a496067d6d4906805cb76232921a513ce898e8
parentc85615ad50799fd0bedbff2e9b7b1831170290f9 (diff)
downloadvyos-1x-9bcd5adf878dfa9f5c621f8b0043ef7f94cdb4b1.tar.gz
vyos-1x-9bcd5adf878dfa9f5c621f8b0043ef7f94cdb4b1.zip
route: static: T2450: add missing "dhcp-interface" route option
As thought in the beginning the dhcp-interface route option can not be superseeded by the interface option. When a route is installed for a DHCP interface, that interface is usually a broadcast interface which can not be used for plain interface-based routes. The old Vyatta logic was migrated to Python where the current received next-hop address from the DHCP interface is installed as next-hop address.
-rw-r--r--data/templates/frr/static_routes_macro.j26
-rw-r--r--interface-definitions/include/static-route.xml.i15
-rw-r--r--python/vyos/template.py20
3 files changed, 40 insertions, 1 deletions
diff --git a/data/templates/frr/static_routes_macro.j2 b/data/templates/frr/static_routes_macro.j2
index b24232ef3..f10b58047 100644
--- a/data/templates/frr/static_routes_macro.j2
+++ b/data/templates/frr/static_routes_macro.j2
@@ -2,6 +2,12 @@
{% if prefix_config.blackhole is defined %}
{{ ip_ipv6 }} route {{ prefix }} blackhole {{ prefix_config.blackhole.distance if prefix_config.blackhole.distance is defined }} {{ 'tag ' + prefix_config.blackhole.tag if prefix_config.blackhole.tag is defined }} {{ 'table ' + table if table is defined and table is not none }}
{% endif %}
+{% if prefix_config.dhcp_interface is defined and prefix_config.dhcp_interface is not none %}
+{% set next_hop = prefix_config.dhcp_interface | get_dhcp_router %}
+{% if next_hop is defined and next_hop is not none %}
+{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }}
+{% endif %}
+{% endif %}
{% if prefix_config.interface is defined and prefix_config.interface is not none %}
{% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %}
{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is defined }} {{ 'nexthop-vrf ' + interface_config.vrf if interface_config.vrf is defined }} {{ 'table ' + table if table is defined and table is not none }}
diff --git a/interface-definitions/include/static-route.xml.i b/interface-definitions/include/static-route.xml.i
index 386582e09..21fcbcd3f 100644
--- a/interface-definitions/include/static-route.xml.i
+++ b/interface-definitions/include/static-route.xml.i
@@ -31,6 +31,21 @@
</leafNode>
</children>
</node>
+ <leafNode name="dhcp-interface">
+ <properties>
+ <help>DHCP interface supplying next-hop IP address</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>DHCP interface name</description>
+ </valueHelp>
+ <constraint>
+ <validator name="interface-name"/>
+ </constraint>
+ </properties>
+ </leafNode>
<tagNode name="interface">
<properties>
<help>Next-hop IPv4 router interface</help>
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 527384d0b..22883b103 100644
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -288,7 +288,6 @@ def compare_netmask(netmask1, netmask2):
except:
return False
-
@register_filter('isc_static_route')
def isc_static_route(subnet, router):
# https://ercpe.de/blog/pushing-static-routes-with-isc-dhcp-server
@@ -316,3 +315,22 @@ def is_file(filename):
if os.path.exists(filename):
return os.path.isfile(filename)
return False
+
+@register_filter('get_dhcp_router')
+def get_dhcp_router(interface):
+ """ Static routes can point to a router received by a DHCP reply. This
+ helper is used to get the current default router from the DHCP reply.
+
+ Returns False of no router is found, returns the IP address as string if
+ a router is found.
+ """
+ interface = interface.replace('.', '_')
+ lease_file = f'/var/lib/dhcp/dhclient_{interface}.leases'
+ if not os.path.exists(lease_file):
+ return None
+
+ from vyos.util import read_file
+ for line in read_file(lease_file).splitlines():
+ if 'option routers' in line:
+ (_, _, address) = line.split()
+ return address.rstrip(';')