|
|
Hello all.
Since we have working multipath, I considered to update dhclient-script
to support it. Also I made it more fail-safe - updating routes is now
real update process, not "remove all and add all". Also a few "XXX"
comments fixed (correctly, I hope).
I didn't get point of adding routes from bound addresses to 127.0.0.1, so
I removed them; please correct me if it was wrong.
Runs a few days on my heavily-roaming notebook.
--
Best wishes,
Vadim Zhukov
--- dhclient-script.orig Thu Jul 31 01:17:04 2008
+++ dhclient-script Thu Jul 31 03:46:45 2008
@@ -22,10 +22,17 @@
# Helper functions that implement common actions.
#
+delete_route() {
+ route -q delete "$@"
+}
+
+add_route() {
+ route add -mpath -nostatic "$@"
+}
+
delete_old_address() {
if [ -n "$old_ip_address" ]; then
ifconfig $interface inet $old_ip_address delete $medium
- route delete "$old_ip_address" 127.0.0.1 >/dev/null 2>&1
fi
}
@@ -35,15 +42,11 @@
netmask $new_subnet_mask \
broadcast $new_broadcast_address \
$medium
-
- # XXX Original TIMEOUT code did not do this unless $new_routers was set?
- route add $new_ip_address 127.0.0.1 >/dev/null 2>&1
}
delete_old_alias() {
if [ -n "$alias_ip_address" ]; then
ifconfig $interface inet $alias_ip_address delete > /dev/null
2>&1
- route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
fi
}
@@ -51,46 +54,57 @@
if [ -n "$alias_ip_address" ]; then
ifconfig $interface inet $alias_ip_address alias netmask \
$alias_subnet_mask
- route add $alias_ip_address 127.0.0.1
fi
}
-delete_old_routes() {
- # Delete existing default route. We only allow one, so no need to
- # process $old_routers list.
- route delete default >/dev/null 2>&1
+update_routes() {
+ # Do not touch same routes, just remove/add changes, using update
+ # technique if possible.
- if [ -n "$old_static_routes" ]; then
- set $old_static_routes
- while [ $# -gt 1 ]; do
- route delete "$1" "$2"
- shift; shift
- done
- fi
-
- arp -dan
-}
-
-add_new_routes() {
- route delete default >/dev/null 2>&1
+ all_old_routes="$old_static_routes"
+ for router in $old_routers; do
+ all_old_routes="$all_old_routes default $router"
+ done
+ all_new_routes="$new_static_routes"
for router in $new_routers; do
- if [ "$new_ip_address" = "$router" ]; then
- route add default -iface $router >/dev/null 2>&1
- else
- route add default $router >/dev/null 2>&1
- fi
- # 2nd and subsequent default routers error out, so explicitly
- # stop processing the list after the first one.
- break
+ all_new_routes="$all_new_routes default $router"
done
- if [ -n "$new_static_routes" ]; then
- set $new_static_routes
- while [ $# -gt 1 ]; do
- route add $1 $2
- shift; shift
+ # Since we use multipath and do not touch same routes, we can safely
+ # add new routes before removing old.
+ if [ -n "$all_old_routes" ]; then
+ set -A routes -- $all_new_routes
+ while [ "${#routes[@]}" -ge 2 ]; do
+ set -- "${routes[@]}"
+ dst="$1"; shift
+ gtw="$2"; shift
+ set -A routes -- "$@"
+ set -- $all_old_routes
+ while [ "$#" -ge 2 ]; do
+ if [ "$gtw" = "$1" -a "$gtw" = "$2" ]; then
+ continue 2
+ fi
+ done
+ add_route "$dst" "$gtw"
done
+
+ set -A routes -- $all_old_routes
+ while [ "${#routes[@]}" -ge 2 ]; do
+ set -- "${routes[@]}"
+ dst="$1"; shift
+ gtw="$2"; shift
+ set -A routes -- "$@"
+ set -- $all_new_routes
+ while [ "$#" -ge 2 ]; do
+ if [ "$dst" = "$1" -a "$gtw" = "$2" ]; then
+ continue 2
+ fi
+ done
+ delete_route "$dst" "$gtw"
+ done
fi
+
+ arp -dan
}
add_new_resolv_conf() {
@@ -162,7 +176,6 @@
fi
if [ "$old_ip_address" != "$new_ip_address" ]; then
delete_old_address
- delete_old_routes
fi
fi
if [ "$reason" = BOUND ] ||
@@ -170,11 +183,11 @@
[ -z "$old_ip_address" ] ||
[ "$old_ip_address" != "$new_ip_address" ]; then
add_new_address
- add_new_routes
fi
if [ "$new_ip_address" != "$alias_ip_address" ]; then
add_new_alias
fi
+ update_routes
add_new_resolv_conf
;;
@@ -182,12 +195,13 @@
delete_old_alias
if [ -n "$old_ip_address" ]; then
delete_old_address
- delete_old_routes
+ update_routes
fi
- # XXX Why add alias we just deleted above?
+ # Add alias we just deleted above - it's intended to be used in
+ # non-DHCP enviornments as a "safe default", see dhclient.conf(5).
add_new_alias
if [ -f /etc/resolv.conf.save ]; then
- cat /etc/resolv.conf.save > /etc/resolv.conf
+ mv /etc/resolv.conf.save /etc/resolv.conf
fi
;;
@@ -196,21 +210,36 @@
add_new_address
sleep 1
if [ -n "$new_routers" ]; then
- set "$new_routers"
- if ping -q -c 1 -w 1 "$1"; then
- if [ "$new_ip_address" != "$alias_ip_address" ]; then
- add_new_alias
+ # Set up provided configuration if any default route specified
+ # could be reached.
+ set -- "$new_routers"
+ while [ "$#" -gt 0 ]; do
+ if ping -q -c 1 -w 1 "$1"; then
+ if [ "$new_ip_address" != "$alias_ip_address" ]
+ then
+ add_new_alias
+ fi
+ update_routes
+ if add_new_resolv_conf; then
+ exit 0
+ fi
fi
- add_new_routes
- if add_new_resolv_conf; then
- exit 0
- fi
- fi
+ shift
+ done
+ else
+ # Preserve static routes, they can be used even without default
+ update_routes
+ exit 0
fi
+
+ # Do not call delete_old_address() and remove "new" IP address instead
+ # because there may be no "old" address if we timed out from beginning.
ifconfig $interface inet $new_ip_address delete $medium
- # XXX Why not a delete_old_address as before all other invocations of
- # delete_old_routes?
- delete_old_routes
+
+ # Force removing all "old" routes
+ new_routers=""
+ new_static_routes=""
+ update_routes
exit 1
;;
esac
|
|