summaryrefslogtreecommitdiff
path: root/src/etc/dhcp/dhclient-exit-hooks.d
diff options
context:
space:
mode:
authorGabriel Skupien <g.skupien@vyos.io>2020-04-26 12:23:58 +0200
committerGabriel Skupien <g.skupien@vyos.io>2020-04-26 12:23:58 +0200
commited4a493b734cac1fbf73df4a067a12d52d3fea57 (patch)
tree28a3056a95dd593f581ab633f78cb06d4ac4c4fd /src/etc/dhcp/dhclient-exit-hooks.d
parent7765d528ce304275350f87c748fa7988ffb4bc26 (diff)
downloadvyos-1x-ed4a493b734cac1fbf73df4a067a12d52d3fea57.tar.gz
vyos-1x-ed4a493b734cac1fbf73df4a067a12d52d3fea57.zip
dhclient: T1381: Improved RFC3442 routes processing
Several improvements in processing RFC3442 routes (support for route deletion, DHCP RENEW and link-local routes)
Diffstat (limited to 'src/etc/dhcp/dhclient-exit-hooks.d')
-rw-r--r--src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup64
-rw-r--r--src/etc/dhcp/dhclient-exit-hooks.d/02-vyos-dhcp-renew-rfc3442148
2 files changed, 211 insertions, 1 deletions
diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup b/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup
index ce846f6c3..88a4d9db9 100644
--- a/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup
+++ b/src/etc/dhcp/dhclient-exit-hooks.d/01-vyos-cleanup
@@ -1,12 +1,74 @@
+# NOTE: here we use 'ip' wrapper, therefore a route will be actually deleted via /usr/sbin/ip or vtysh, according to the system state
+
if [[ $reason =~ (EXPIRE|FAIL|RELEASE|STOP) ]]; then
# delete dynamic nameservers from a configuration if lease was deleted
logmsg info "Deleting nameservers with tag \"dhcp-${interface}\" via vyos-hostsd-client"
vyos-hostsd-client --delete-name-servers --tag dhcp-${interface}
- # try to delete default ip route (NOTE: here we use 'ip' wrapper, therefore a route will be actually deleted via /usr/sbin/ip or vtysh, according to the system state)
+ # try to delete default ip route
for router in $old_routers; do
logmsg info "Deleting default route: via $router dev ${interface}"
ip -4 route del default via $router dev ${interface}
done
+ # delete rfc3442 routes
+ if [ -n "$old_rfc3442_classless_static_routes" ]; then
+ set -- $old_rfc3442_classless_static_routes
+ while [ $# -gt 0 ]; do
+ net_length=$1
+ via_arg=''
+ case $net_length in
+ 32|31|30|29|28|27|26|25)
+ if [ $# -lt 9 ]; then
+ return 1
+ fi
+ net_address="${2}.${3}.${4}.${5}"
+ gateway="${6}.${7}.${8}.${9}"
+ shift 9
+ ;;
+ 24|23|22|21|20|19|18|17)
+ if [ $# -lt 8 ]; then
+ return 1
+ fi
+ net_address="${2}.${3}.${4}.0"
+ gateway="${5}.${6}.${7}.${8}"
+ shift 8
+ ;;
+ 16|15|14|13|12|11|10|9)
+ if [ $# -lt 7 ]; then
+ return 1
+ fi
+ net_address="${2}.${3}.0.0"
+ gateway="${4}.${5}.${6}.${7}"
+ shift 7
+ ;;
+ 8|7|6|5|4|3|2|1)
+ if [ $# -lt 6 ]; then
+ return 1
+ fi
+ net_address="${2}.0.0.0"
+ gateway="${3}.${4}.${5}.${6}"
+ shift 6
+ ;;
+ 0) # default route
+ if [ $# -lt 5 ]; then
+ return 1
+ fi
+ net_address="0.0.0.0"
+ gateway="${2}.${3}.${4}.${5}"
+ shift 5
+ ;;
+ *) # error
+ return 1
+ ;;
+ esac
+ # take care of link-local routes
+ if [ "${gateway}" != '0.0.0.0' ]; then
+ via_arg="via ${gateway}"
+ fi
+ # delete route (ip detects host routes automatically)
+ ip -4 route del "${net_address}/${net_length}" \
+ ${via_arg} dev "${interface}" >/dev/null 2>&1
+ done
+ fi
fi
if [[ $reason =~ (EXPIRE6|RELEASE6|STOP6) ]]; then
diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/02-vyos-dhcp-renew-rfc3442 b/src/etc/dhcp/dhclient-exit-hooks.d/02-vyos-dhcp-renew-rfc3442
new file mode 100644
index 000000000..9202fe72d
--- /dev/null
+++ b/src/etc/dhcp/dhclient-exit-hooks.d/02-vyos-dhcp-renew-rfc3442
@@ -0,0 +1,148 @@
+# support for RFC3442 routes in DHCP RENEW
+
+function convert_to_cidr () {
+ cidr=""
+ set -- $1
+ while [ $# -gt 0 ]; do
+ net_length=$1
+
+ case $net_length in
+ 32|31|30|29|28|27|26|25)
+ if [ $# -lt 9 ]; then
+ return 1
+ fi
+ net_address="${2}.${3}.${4}.${5}"
+ gateway="${6}.${7}.${8}.${9}"
+ shift 9
+ ;;
+ 24|23|22|21|20|19|18|17)
+ if [ $# -lt 8 ]; then
+ return 1
+ fi
+ net_address="${2}.${3}.${4}.0"
+ gateway="${5}.${6}.${7}.${8}"
+ shift 8
+ ;;
+ 16|15|14|13|12|11|10|9)
+ if [ $# -lt 7 ]; then
+ return 1
+ fi
+ net_address="${2}.${3}.0.0"
+ gateway="${4}.${5}.${6}.${7}"
+ shift 7
+ ;;
+ 8|7|6|5|4|3|2|1)
+ if [ $# -lt 6 ]; then
+ return 1
+ fi
+ net_address="${2}.0.0.0"
+ gateway="${3}.${4}.${5}.${6}"
+ shift 6
+ ;;
+ 0) # default route
+ if [ $# -lt 5 ]; then
+ return 1
+ fi
+ net_address="0.0.0.0"
+ gateway="${2}.${3}.${4}.${5}"
+ shift 5
+ ;;
+ *) # error
+ return 1
+ ;;
+ esac
+
+ cidr+="${net_address}/${net_length}:${gateway} "
+ done
+}
+
+# main script starts here
+
+RUN="yes"
+
+if [ "$RUN" = "yes" ]; then
+ convert_to_cidr "$old_rfc3442_classless_static_routes"
+ old_cidr=$cidr
+ convert_to_cidr "$new_rfc3442_classless_static_routes"
+ new_cidr=$cidr
+
+ if [ "$reason" = "RENEW" ]; then
+ if [ "$new_rfc3442_classless_static_routes" != "$old_rfc3442_classless_static_routes" ]; then
+ logmsg info "RFC3442 route change detected, old_routes: $old_rfc3442_classless_static_routes"
+ logmsg info "RFC3442 route change detected, new_routes: $new_rfc3442_classless_static_routes"
+ if [ -z "$new_rfc3442_classless_static_routes" ]; then
+ # delete all routes from the old_rfc3442_classless_static_routes
+ for route in $old_cidr; do
+ network=$(printf "${route}" | awk -F ":" '{print $1}')
+ gateway=$(printf "${route}" | awk -F ":" '{print $2}')
+ # take care of link-local routes
+ if [ "${gateway}" != '0.0.0.0' ]; then
+ via_arg="via ${gateway}"
+ else
+ via_arg=""
+ fi
+ ip -4 route del "${network}" "${via_arg}" dev "${interface}" >/dev/null 2>&1
+ done
+ elif [ -z "$old_rfc3442_classless_static_routes" ]; then
+ # add all routes from the new_rfc3442_classless_static_routes
+ for route in $new_cidr; do
+ network=$(printf "${route}" | awk -F ":" '{print $1}')
+ gateway=$(printf "${route}" | awk -F ":" '{print $2}')
+ # take care of link-local routes
+ if [ "${gateway}" != '0.0.0.0' ]; then
+ via_arg="via ${gateway}"
+ else
+ via_arg=""
+ fi
+ ip -4 route add "${network}" "${via_arg}" dev "${interface}" >/dev/null 2>&1
+ done
+ else
+ # update routes
+ # delete old
+ for old_route in $old_cidr; do
+ match="false"
+ for new_route in $new_cidr; do
+ if [[ "$old_route" == "$new_route" ]]; then
+ match="true"
+ break
+ fi
+ done
+ if [[ "$match" == "false" ]]; then
+ # delete old_route
+ network=$(printf "${old_route}" | awk -F ":" '{print $1}')
+ gateway=$(printf "${old_route}" | awk -F ":" '{print $2}')
+ # take care of link-local routes
+ if [ "${gateway}" != '0.0.0.0' ]; then
+ via_arg="via ${gateway}"
+ else
+ via_arg=""
+ fi
+ ip -4 route del "${network}" "${via_arg}" dev "${interface}" >/dev/null 2>&1
+ fi
+ done
+ # add new
+ for new_route in $new_cidr; do
+ match="false"
+ for old_route in $old_cidr; do
+ if [[ "$new_route" == "$old_route" ]]; then
+ match="true"
+ break
+ fi
+ done
+ if [[ "$match" == "false" ]]; then
+ # add new_route
+ network=$(printf "${new_route}" | awk -F ":" '{print $1}')
+ gateway=$(printf "${new_route}" | awk -F ":" '{print $2}')
+ # take care of link-local routes
+ if [ "${gateway}" != '0.0.0.0' ]; then
+ via_arg="via ${gateway}"
+ else
+ via_arg=""
+ fi
+ ip -4 route add "${network}" "${via_arg}" dev "${interface}" >/dev/null 2>&1
+ fi
+ done
+ fi
+ fi
+ fi
+fi