Subject: bin/21275: Dhclient weirdness
To: None <email@example.com>
From: None <firstname.lastname@example.org>
Date: 04/23/2003 01:32:46
>Synopsis: dhclient sometimes fails to set default route
>Arrival-Date: Wed Apr 23 06:33:00 UTC 2003
>Release: NetBSD 1.6
System: NetBSD hal 1.6 NetBSD 1.6 (FREAR2) #0: Thu Apr 10 02:25:05 CDT 2003 user@hal:/home/user/sys/src/sys/arch/i386/compile/FREAR2 i386
Sometimes /sbin/dhclient does not pass a correct environment to
/sbin/dhclient-script and this causes the script to behave incorrectly.
I have two physical interfaces, an rtk with a static ip and a fxp with a
dynamic ip on the internet. In my case, the dynamic IP is assigned from a
DSL router unit that is the HomePortal 1000S made by 2-Wire. The router is
under my control and can be configured to assign my fxp a public or private
IP via dhcp.
When transitioning from a public to a private IP, the environment for
/sbin/dhclient-script contains reason=BOUND and does not contain the
variables old_ip_address or old_routers. Because those two variables
are unset, dhclient-script incorrectly decides not to adjust the default
route. When transitioning from a private IP to a public one, the
environment contains reason=BOUND and does have values set for old_ip_address
and old_routers, however these values are incorrect. $old_ip_address
reflects the new ip address (and is therefore equal to $new_ip_address)
and the same goes for $old_routers. This again causes dhclient-script to
decide not to update the default route.
Use a netbsd 1.6 system with a dhclient configured interface, connect it
to a homeportal router and toggle the dmz setting for the netbsd interface.
I have fixed the problem by writing a /etc/dhclient-enter-hooks script
that correctly sets the old_ip_address and old_router variables.
This script attempts to be generic, however may not be as portable as I had
This fix is a kludge, and a real fix is to correct /sbin/dhclient so that it
always sets the correct environment variables.
My /etc/dhclient-enter-hooks script is included:
# It seems that if the IP we had been assigned is changed, there is a problem.
# NetBSD 1.6's /sbin/dhclient-script doesn't want to set the default route
# for a primary interface change in some circumstances.
# This script detects that situation and corrects it.
# For the detection part, the env during a failure looks like this:
# old_ip_address != our current ip
# old_routers != the real default route
# For the correction part, we need to correctly set the variables
# First things first, the only dhclient case we need to fix is the BOUND case
# (ip addr chg). We'll do this at the VERY START because 99% of the times
# we are run will be reason=RENEW.
if [ \( "x$reason" != "xBOUND" \) ]; then
# Function to check for a valid IP address...
# Inputs like " 22.214.171.124" and "126.96.36.199 " will fail, so will "255.255.300.255".
# Of course, "255.255.255.255" and "0.0.0.0" and everything in between work.
# Returns 0 on valid input, 1 for a failure
local IP_NUM_REGEX IP_REGEX REGEX_RESULT
if [ $# -ne 1 ]; then
REGEX_RESULT="`echo "$1" | egrep "$IP_REGEX" > /dev/null 2>&1 ;echo $?`"
if [ "$REGEX_RESULT" -ne 0 ]; then
# echo Fatal: Couldn\'t determine IP\! >&2
# exit 1
return 1 # Signal a failure
return 0 # The argument is indeed strictly an IP
# Load our existing IP address... Store it as $old_ip_address
# The line imm. below is buggy, so we use two vars and it works.. Humm??
#real_old_ip_address="`ifconfig $interface |grep inet| head -1 | cut -d\ -f 2`"
real_old_ip_address1="`ifconfig $interface |grep inet| head -1`"
real_old_ip_address="`echo $real_old_ip_address1 | cut -d\ -f 2`"
if Verify_IP_Addr "$real_old_ip_address"; then
# Load our default route's IP addres... Store it as $old_routers
# Similarly, the line below is buggy, so the two var approach fixes it..
#real_old_routers="`netstat -nr | grep default | sed 's/^ *default *//' | \
# cut -d\ -f 1`"
real_old_routers1="`netstat -nr | grep default | head -1`"
real_old_routers="`echo $real_old_routers1 | sed 's/^ *default *//' | cut -d\ -f 1`"
if Verify_IP_Addr "$real_old_routers"; then
unset real_old_ip_address real_old_routers