[pkg-dhcp-devel] Bug#609408: isc-dhcp: various improvements to dhclient-script & its hooks

Peter Marschall peter at adpm.de
Sun Jan 9 09:58:23 UTC 2011


Package: isc-dhcp
Version: 4.1.1-P1-15
Severity: normal
Tags: patch ipv6

Hi, please find attached a patch series against
  git://git.debian.org/pkg-dhcp/isc-dhcp.git
that improve various asepcts of dhclient-scripts.

Here are the highlights:
* remove bashisms
* DHCPv6 support (currently for Linux only)
* convert to using iproute2's ip instead of the
  venerable ifconfig & route (Linux only)
* add comments to improve understanding
  it took me days to understand the whole thing
* cleanup / harmonization / code deduplication

I have tested these changed scripts on 2 systems
with DHCP & DHCPv6 and can confirm they work.

These patches should also fix the following bugs:
* 567141
  The patch in that bug was correct (but could be improved)
* 591589
  The patch from that 591589 was incomplete:
  it did not include changes to make_resolv_conf
and most probably
* 275653 (at least for Linux)
  with ip instead of ifconfig the issues should be gone
  
I am sorry for filing a separate bug, but not having a public git repo myself,
I did not find a better way to submit all the patches in order.
On the other hand, as this is one patch series with the patches depending on
each other, I thought it better to have them in one common place instead of
splitting them by bugs.

Please tell me what you think of the patches and if there's a better way to
submit patches.

Thanks for maintaining isc-dhcp in Debian
Peter


-- System Information:
Debian Release: 6.0
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (500, 'stable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.32-5-amd64 (SMP w/4 CPU cores)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
-------------- next part --------------
>From 107945b26bb57d027bc7634e7b28ce69364eed98 Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 12:41:37 +0100
Subject: [PATCH 01/14] dhclient-script.linux: fix domain_name in domain_search check

* Fix the check whether $new_domain_name is an element of $new_domain_search
  in make_resolv_conf() of dhclient-script.linux by iterating over the
  individual elements of $new_domain_search instead of errorneously
  treating them as one big blob.
* Fix usage of $domain_in_search_list
* Check $new_domain_name and "${new_domain_name}." against elements
  of $new_domain_search as elements of $new_domain search seem to get
  "." appended autmatically in the server

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/dhclient-script.linux |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/debian/dhclient-script.linux b/debian/dhclient-script.linux
index 222b748..3c103ec 100644
--- a/debian/dhclient-script.linux
+++ b/debian/dhclient-script.linux
@@ -23,12 +23,13 @@ make_resolv_conf() {
 	    #new_domain_search="${new_domain_search% }"
 	    if [ "$new_domain_name" ]; then
 		domain_in_search_list=""
-		for domain in "$new_domain_search"; do
-			if [ "$domain" = "$new_domain_name" ]; then
-				domain_in_search="Yes"
+		for domain in $new_domain_search; do
+			if [ "$domain" = "${new_domain_name}" ] ||
+			if [ "$domain" = "${new_domain_name}" ]; then
+				domain_in_search_list="Yes"
 			fi
 		done
-		if [ ! "$domain_in_search" ]; then
+		if [ -z "$domain_in_search_list" ]; then
 	    		new_domain_search="$new_domain_name $new_domain_search"
 		fi
 	    fi
-- 
1.7.2.3

-------------- next part --------------
>From 6b86ccf6098511c232fa28970e457ac3846e90ca Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 13:10:01 +0100
Subject: [PATCH 02/14] dhclient-script.*: fix indentation to improve readability


Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/dhclient-script.kfreebsd      |   52 ++++++++++++++--------------
 debian/dhclient-script.kfreebsd.udeb |   34 +++++++++---------
 debian/dhclient-script.linux         |   62 +++++++++++++++++-----------------
 debian/dhclient-script.linux.udeb    |    8 ++--
 4 files changed, 78 insertions(+), 78 deletions(-)

diff --git a/debian/dhclient-script.kfreebsd b/debian/dhclient-script.kfreebsd
index c7985ff..c3cd259 100644
--- a/debian/dhclient-script.kfreebsd
+++ b/debian/dhclient-script.kfreebsd
@@ -9,18 +9,18 @@ make_resolv_conf() {
         if [ -n "$new_domain_name" ]; then
             echo domain ${new_domain_name%% *} >>$new_resolv_conf
         fi
-	if [ -n "$new_domain_search" ]; then
-		new_domain_search="${new_domain_search% }"
-	    if [ -n "$new_domain_name" ]; then
-	    	new_domain_search="$new_domain_name $new_domain_search"
-	    fi
-	    echo "search ${new_domain_search}" >> $new_resolv_conf
-	elif [ -n "$new_domain_name" ]; then
-		echo "search ${new_domain_name}" >> $new_resolv_conf
-	fi
+        if [ -n "$new_domain_search" ]; then
+            new_domain_search="${new_domain_search% }"
+            if [ -n "$new_domain_name" ]; then
+                new_domain_search="$new_domain_name $new_domain_search"
+            fi
+            echo "search ${new_domain_search}" >> $new_resolv_conf
+        elif [ -n "$new_domain_name" ]; then
+            echo "search ${new_domain_name}" >> $new_resolv_conf
+        fi
         if [ -n "$new_domain_name_servers" ]; then
-                   for nameserver in $new_domain_name_servers; do
-                       echo nameserver $nameserver >>$new_resolv_conf
+            for nameserver in $new_domain_name_servers; do
+                echo nameserver $nameserver >>$new_resolv_conf
             done
         else # keep 'old' nameservers
             sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p /etc/resolv.conf >>$new_resolv_conf
@@ -129,10 +129,10 @@ case "$reason" in
         ;;
     BOUND|RENEW|REBIND|REBOOT)
 
-	if [ -n "$old_host_name" -a -n "$host_name" -a \
-     	     "$host_name" != "$old_host_name" ]; then
-    	    hostname "$new_host_name"
-	fi
+        if [ -n "$old_host_name" -a -n "$host_name" -a \
+             "$host_name" != "$old_host_name" ]; then
+            hostname "$new_host_name"
+        fi
 
         if [ -n "$old_ip_address" -a -n "$alias_ip_address" -a \
              "$alias_ip_address" != "$old_ip_address" ]; then
@@ -149,12 +149,12 @@ case "$reason" in
             ifconfig $interface inet 0 down
         fi
 
-	# point to point
-	if [ "$new_subnet_mask" == "255.255.255.255" ]; then
-		for router in $new_routers; do
-	    	    route add $router $new_ip_address
-		done
-	fi
+        # point to point
+        if [ "$new_subnet_mask" == "255.255.255.255" ]; then
+            for router in $new_routers; do
+                route add $router $new_ip_address
+            done
+        fi
 
         if [ -z "$old_ip_address" -o "$old_ip_address" != "$new_ip_address" -o \
             "$reason" = "BOUND" -o "$reason" = "REBOOT" ]; then
@@ -204,7 +204,7 @@ case "$reason" in
         fi
 
         ;;
-	
+
     TIMEOUT)
         if [ -n "$alias_ip_address" ]; then
             ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
@@ -220,11 +220,11 @@ case "$reason" in
         if [ -z "$first_router" ] || ping -q -c 1 $first_router; then
             if [ "$new_ip_address" != "$alias_ip_address" -a \
                 -n "$alias_ip_address" ]; then
-	        ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
-	        route add $alias_ip_address 127.0.0.1
+                ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
+                route add $alias_ip_address 127.0.0.1
             fi
-	    route add $new_ip_address 127.1 >/dev/null 2>&1
-	    
+            route add $new_ip_address 127.1 >/dev/null 2>&1
+
             for router in $new_routers; do
                 route add default $router $metric_arg
             done
diff --git a/debian/dhclient-script.kfreebsd.udeb b/debian/dhclient-script.kfreebsd.udeb
index 522a345..3347539 100644
--- a/debian/dhclient-script.kfreebsd.udeb
+++ b/debian/dhclient-script.kfreebsd.udeb
@@ -44,15 +44,15 @@ fi
 if [ -n "$old_broadcast_address" ]; then
     old_broadcast_arg="broadcast $old_broadcast_address"
 fi
-    
+
 # Execute the operation
 case "$reason" in
     MEDIUM|ARPCHECK|ARPSEND)
         # Do nothing
         ;;
     PREINIT)
-	ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
-	    broadcast 255.255.255.255 up
+        ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
+            broadcast 255.255.255.255 up
 
         # We need to give the kernel some time to get the interface up.
         sleep 1
@@ -60,29 +60,29 @@ case "$reason" in
     BOUND|RENEW|REBIND|REBOOT)
 
         set_hostname
-        
+
         if [ -n "$old_ip_address" ] && \
              [ "$old_ip_address" != "$new_ip_address" ]; then
             # IP address changed. Bringing down the interface will delete all routes,
             # and clear the ARP cache.
-	    ifconfig $interface inet -alias $old_ip_address $medium
-	    route delete $old_ip_address 127.1 >/dev/null 2>&1
-	    ifconfig $interface inet 0 down
+            ifconfig $interface inet -alias $old_ip_address $medium
+            route delete $old_ip_address 127.1 >/dev/null 2>&1
+            ifconfig $interface inet 0 down
         fi
 
         if [ -n "$new_interface_mtu" ]; then
-	    ifconfig $interface mtu $new_interface_mtu || true
+            ifconfig $interface mtu $new_interface_mtu || true
         fi
 
         if [ -z "$old_ip_address" ] || [ "$old_ip_address" != "$new_ip_address" ] || \
             [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
 
-	    ifconfig $interface inet $new_ip_address $new_subnet_arg \
-	        $new_broadcast_arg $medium $mtu_arg
-	    route add $new_ip_address 127.1 $metric_arg >/dev/null 2>&1 || true
-	    for router in $new_routers; do
-	        route add default $router >/dev/null 2>&1
-	    done
+            ifconfig $interface inet $new_ip_address $new_subnet_arg \
+                $new_broadcast_arg $medium $mtu_arg
+            route add $new_ip_address 127.1 $metric_arg >/dev/null 2>&1 || true
+            for router in $new_routers; do
+                route add default $router >/dev/null 2>&1
+            done
         fi
 
         make_resolv_conf
@@ -98,15 +98,15 @@ case "$reason" in
 
     EXPIRE|FAIL|RELEASE|STOP)
         if [ -n "$old_ip_address" ]; then
-	    route delete $old_ip_address 127.1 >/dev/null 2>&1
+            route delete $old_ip_address 127.1 >/dev/null 2>&1
             # Shut down interface, which will delete routes and clear arp cache.
-	    ifconfig $interface inet 0 down
+            ifconfig $interface inet 0 down
         fi
 
         ;;
 
     TIMEOUT)
-	ifconfig $interface down
+        ifconfig $interface down
 
         ;;
 esac
diff --git a/debian/dhclient-script.linux b/debian/dhclient-script.linux
index 3c103ec..21ee7c1 100644
--- a/debian/dhclient-script.linux
+++ b/debian/dhclient-script.linux
@@ -19,27 +19,27 @@ make_resolv_conf() {
         if [ "$new_domain_name" ]; then
             echo domain ${new_domain_name%% *} >>$new_resolv_conf
         fi
-	if [ "$new_domain_search" ]; then
-	    #new_domain_search="${new_domain_search% }"
-	    if [ "$new_domain_name" ]; then
-		domain_in_search_list=""
-		for domain in $new_domain_search; do
-			if [ "$domain" = "${new_domain_name}" ] ||
-			if [ "$domain" = "${new_domain_name}" ]; then
-				domain_in_search_list="Yes"
-			fi
-		done
-		if [ -z "$domain_in_search_list" ]; then
-	    		new_domain_search="$new_domain_name $new_domain_search"
-		fi
-	    fi
-	    echo "search ${new_domain_search}" >> $new_resolv_conf
-	elif [ "$new_domain_name" ]; then
-		echo "search ${new_domain_name}" >> $new_resolv_conf
-	fi
+        if [ "$new_domain_search" ]; then
+            #new_domain_search="${new_domain_search% }"
+            if [ "$new_domain_name" ]; then
+                domain_in_search_list=""
+                for domain in $new_domain_search; do
+                    if [ "$domain" = "${new_domain_name}" ] ||
+                       [ "$domain" = "${new_domain_name}." ]; then
+                        domain_in_search_list="Yes"
+                    fi
+                done
+                if [ -z "$domain_in_search_list" ]; then
+                    new_domain_search="$new_domain_name $new_domain_search"
+                fi
+            fi
+            echo "search ${new_domain_search}" >> $new_resolv_conf
+        elif [ "$new_domain_name" ]; then
+            echo "search ${new_domain_name}" >> $new_resolv_conf
+        fi
         if [ "$new_domain_name_servers" ]; then
-                   for nameserver in $new_domain_name_servers; do
-                       echo nameserver $nameserver >>$new_resolv_conf
+            for nameserver in $new_domain_name_servers; do
+                echo nameserver $nameserver >>$new_resolv_conf
             done
         else # keep 'old' nameservers
             sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p /etc/resolv.conf >>$new_resolv_conf
@@ -153,10 +153,10 @@ case "$reason" in
         ;;
     BOUND|RENEW|REBIND|REBOOT)
 
-	if [ -n "$old_host_name" -a -n "$host_name" -a \
-     	     "$host_name" != "$old_host_name" ]; then
-    	    hostname "$new_host_name"
-	fi
+        if [ -n "$old_host_name" -a -n "$host_name" -a \
+            "$host_name" != "$old_host_name" ]; then
+            hostname "$new_host_name"
+        fi
 
         if [ -n "$old_ip_address" -a -n "$alias_ip_address" -a \
              "$alias_ip_address" != "$old_ip_address" ]; then
@@ -178,12 +178,12 @@ case "$reason" in
             ifconfig $interface inet $new_ip_address $new_subnet_arg \
                 $new_broadcast_arg $mtu_arg
 
-	    # point to point
-	    if [ "$new_subnet_mask" == "255.255.255.255" ]; then
-	    	for router in $new_routers; do
-	    	    route add -host $router dev $interface
-	    	done
-	    fi
+            # point to point
+            if [ "$new_subnet_mask" == "255.255.255.255" ]; then
+                for router in $new_routers; do
+                    route add -host $router dev $interface
+                done
+            fi
 
             for router in $new_routers; do
                 route add default dev $interface gw $router $metric_arg
@@ -236,7 +236,7 @@ case "$reason" in
                 ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
                 route add -host $alias_ip_address dev $interface:0
             fi
-	    
+
             for router in $new_routers; do
                 route add default dev $interface gw $router $metric_arg
             done
diff --git a/debian/dhclient-script.linux.udeb b/debian/dhclient-script.linux.udeb
index 14f167e..e42a55f 100644
--- a/debian/dhclient-script.linux.udeb
+++ b/debian/dhclient-script.linux.udeb
@@ -44,14 +44,14 @@ fi
 if [ -n "$old_broadcast_address" ]; then
     old_broadcast_arg="broadcast $old_broadcast_address"
 fi
-    
+
 # Execute the operation
 case "$reason" in
     MEDIUM|ARPCHECK|ARPSEND)
         # Do nothing
         ;;
     PREINIT)
-	ip link set $interface up
+        ip link set $interface up
 
         # We need to give the kernel some time to get the interface up.
         sleep 1
@@ -59,7 +59,7 @@ case "$reason" in
     BOUND|RENEW|REBIND|REBOOT)
 
         set_hostname
-        
+
         if [ -n "$old_ip_address" ] && \
              [ "$old_ip_address" != "$new_ip_address" ]; then
             # IP address changed. Bringing down the interface will delete all routes,
@@ -76,7 +76,7 @@ case "$reason" in
             [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
 
             ip link set $interface up
-	    ip addr flush dev $interface
+            ip addr flush dev $interface
             ip addr add $new_ip_address$new_mask $new_broadcast_arg dev $interface
 
             for router in $new_routers; do
-- 
1.7.2.3

-------------- next part --------------
>From bc9fc30c6dbff8d04a61e985d8b1144502417eef Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 13:40:23 +0100
Subject: [PATCH 03/14] dhclient-script:* remove bashisms

Prepare for dhclient-script to be used without bash.

Further work is required in the hook scripts

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/dhclient-script.kfreebsd      |   38 ++++++++++++++++++---------------
 debian/dhclient-script.kfreebsd.udeb |   15 ++++++++-----
 debian/dhclient-script.linux         |   38 ++++++++++++++++++---------------
 debian/dhclient-script.linux.udeb    |   15 ++++++++-----
 4 files changed, 60 insertions(+), 46 deletions(-)

diff --git a/debian/dhclient-script.kfreebsd b/debian/dhclient-script.kfreebsd
index c3cd259..ea03628 100644
--- a/debian/dhclient-script.kfreebsd
+++ b/debian/dhclient-script.kfreebsd
@@ -3,8 +3,9 @@
 # Based on Linux and FreeBSD scripts.
 
 make_resolv_conf() {
-    if [ -n "$new_domain_name" -o -n "$new_domain_name_servers" ]; then
-        local new_resolv_conf=/etc/resolv.conf.dhclient-new
+    local new_resolv_conf
+    if [ -n "$new_domain_name" ] || [ -n "$new_domain_name_servers" ]; then
+        new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
         if [ -n "$new_domain_name" ]; then
             echo domain ${new_domain_name%% *} >>$new_resolv_conf
@@ -32,8 +33,9 @@ make_resolv_conf() {
 }
 
 run_hook() {
-    local script="$1"
+    local script
     local exit_status
+    script="$1"
     shift	# discard the first argument, then the rest are the script's
 
     if [ -f $script ]; then
@@ -50,8 +52,9 @@ run_hook() {
 }
 
 run_hookdir() {
-    local dir="$1"
+    local dir
     local exit_status
+    dir="$1"
     shift	# See run_hook
 
     if [ -d "$dir" ]; then
@@ -129,19 +132,19 @@ case "$reason" in
         ;;
     BOUND|RENEW|REBIND|REBOOT)
 
-        if [ -n "$old_host_name" -a -n "$host_name" -a \
-             "$host_name" != "$old_host_name" ]; then
+        if [ -n "$old_host_name" ] && [ -n "$host_name" ] &&
+           [ "$host_name" != "$old_host_name" ]; then
             hostname "$new_host_name"
         fi
 
-        if [ -n "$old_ip_address" -a -n "$alias_ip_address" -a \
-             "$alias_ip_address" != "$old_ip_address" ]; then
+        if [ -n "$old_ip_address" ] && [ -n "$alias_ip_address" ] &&
+           [ "$alias_ip_address" != "$old_ip_address" ]; then
             # Possible new alias. Remove old alias.
             ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
             route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
         fi
-        if [ -n "$old_ip_address" -a \
-             "$old_ip_address" != "$new_ip_address" ]; then
+        if [ -n "$old_ip_address" ] &&
+           [ "$old_ip_address" != "$new_ip_address" ]; then
             ifconfig $interface inet -alias $old_ip_address $medium
             route delete $old_ip_address 127.1 >/dev/null 2>&1
             # IP address changed. Bringing down the interface will delete all other
@@ -150,14 +153,15 @@ case "$reason" in
         fi
 
         # point to point
-        if [ "$new_subnet_mask" == "255.255.255.255" ]; then
+        if [ "$new_subnet_mask" = "255.255.255.255" ]; then
             for router in $new_routers; do
                 route add $router $new_ip_address
             done
         fi
 
-        if [ -z "$old_ip_address" -o "$old_ip_address" != "$new_ip_address" -o \
-            "$reason" = "BOUND" -o "$reason" = "REBOOT" ]; then
+        if [ -z "$old_ip_address" ] ||
+           [ "$old_ip_address" != "$new_ip_address" ] ||
+           [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
 
             ifconfig $interface inet $new_ip_address $new_subnet_arg \
                 $new_broadcast_arg $medium $mtu_arg
@@ -174,8 +178,8 @@ case "$reason" in
             fi
         fi
 
-        if [ "$new_ip_address" != "$alias_ip_address" -a -n "$alias_ip_address" ];
-            then
+        if [ -n "$alias_ip_address" ] &&
+           [ "$new_ip_address" != "$alias_ip_address" ]; then
             ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
             route add $alias_ip_address 127.0.0.1
         fi
@@ -218,8 +222,8 @@ case "$reason" in
         first_router="$1"
 
         if [ -z "$first_router" ] || ping -q -c 1 $first_router; then
-            if [ "$new_ip_address" != "$alias_ip_address" -a \
-                -n "$alias_ip_address" ]; then
+            if [ -n "$alias_ip_address" ] &&
+               [ "$new_ip_address" != "$alias_ip_address" ]; then
                 ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
                 route add $alias_ip_address 127.0.0.1
             fi
diff --git a/debian/dhclient-script.kfreebsd.udeb b/debian/dhclient-script.kfreebsd.udeb
index 3347539..73f556d 100644
--- a/debian/dhclient-script.kfreebsd.udeb
+++ b/debian/dhclient-script.kfreebsd.udeb
@@ -11,8 +11,9 @@ set -e
 # Modified for Debian.  Matt Zimmerman and Eloy Paris, December 2003
 
 make_resolv_conf() {
+    local new_resolv_conf
     if [ -n "$new_domain_name" ] || [ -n "$new_domain_name_servers" ]; then
-        local new_resolv_conf=/etc/resolv.conf.dhclient-new
+        new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
         if [ -n "$new_domain_name" ]; then
             echo "search $new_domain_name" >>$new_resolv_conf
@@ -25,7 +26,8 @@ make_resolv_conf() {
 }
 
 set_hostname() {
-    local current_hostname=$(hostname)
+    local current_hostname
+    current_hostname=$(hostname)
     if [ -z "$current_hostname" ] || [ "$current_hostname" = "(none)" ]; then
         hostname "$new_host_name"
     fi
@@ -61,8 +63,8 @@ case "$reason" in
 
         set_hostname
 
-        if [ -n "$old_ip_address" ] && \
-             [ "$old_ip_address" != "$new_ip_address" ]; then
+        if [ -n "$old_ip_address" ] &&
+           [ "$old_ip_address" != "$new_ip_address" ]; then
             # IP address changed. Bringing down the interface will delete all routes,
             # and clear the ARP cache.
             ifconfig $interface inet -alias $old_ip_address $medium
@@ -74,8 +76,9 @@ case "$reason" in
             ifconfig $interface mtu $new_interface_mtu || true
         fi
 
-        if [ -z "$old_ip_address" ] || [ "$old_ip_address" != "$new_ip_address" ] || \
-            [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
+        if [ -z "$old_ip_address" ] ||
+           [ "$old_ip_address" != "$new_ip_address" ] ||
+           [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
 
             ifconfig $interface inet $new_ip_address $new_subnet_arg \
                 $new_broadcast_arg $medium $mtu_arg
diff --git a/debian/dhclient-script.linux b/debian/dhclient-script.linux
index 21ee7c1..d065140 100644
--- a/debian/dhclient-script.linux
+++ b/debian/dhclient-script.linux
@@ -13,8 +13,9 @@
 # The alias handling in here probably still sucks. -mdz
 
 make_resolv_conf() {
-    if [ "$new_domain_name" -o "$new_domain_name_servers" ]; then
-        local new_resolv_conf=/etc/resolv.conf.dhclient-new
+    local new_resolv_conf
+    if [ "$new_domain_name" ] || [ "$new_domain_name_servers" ]; then
+        new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
         if [ "$new_domain_name" ]; then
             echo domain ${new_domain_name%% *} >>$new_resolv_conf
@@ -51,8 +52,9 @@ make_resolv_conf() {
 }
 
 run_hook() {
-    local script="$1"
+    local script
     local exit_status
+    script="$1"
     shift	# discard the first argument, then the rest are the script's
 
     if [ -f $script ]; then
@@ -69,8 +71,9 @@ run_hook() {
 }
 
 run_hookdir() {
-    local dir="$1"
+    local dir
     local exit_status
+    dir="$1"
     shift	# See run_hook
 
     if [ -d "$dir" ]; then
@@ -153,33 +156,34 @@ case "$reason" in
         ;;
     BOUND|RENEW|REBIND|REBOOT)
 
-        if [ -n "$old_host_name" -a -n "$host_name" -a \
-            "$host_name" != "$old_host_name" ]; then
+        if [ -n "$old_host_name" ] && [ -n "$host_name" ] &&
+           [ "$host_name" != "$old_host_name" ]; then
             hostname "$new_host_name"
         fi
 
-        if [ -n "$old_ip_address" -a -n "$alias_ip_address" -a \
-             "$alias_ip_address" != "$old_ip_address" ]; then
+        if [ -n "$old_ip_address" ] && [ -n "$alias_ip_address" ] &&
+           [ "$alias_ip_address" != "$old_ip_address" ]; then
             # Possible new alias. Remove old alias.
             ifconfig $interface:0- inet 0
         fi
 
-        if [ -n "$old_ip_address" -a \
-             "$old_ip_address" != "$new_ip_address" ]; then
+        if [ -n "$old_ip_address" ] &&
+           [ "$old_ip_address" != "$new_ip_address" ]; then
             # IP address changed. Bringing down the interface will delete all routes,
             # and clear the ARP cache.
             ifconfig $interface inet 0
 
         fi
 
-        if [ -z "$old_ip_address" -o "$old_ip_address" != "$new_ip_address" -o \
-            "$reason" = "BOUND" -o "$reason" = "REBOOT" ]; then
+        if [ -z "$old_ip_address" ] ||
+           [ "$old_ip_address" != "$new_ip_address" ] ||
+           [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
 
             ifconfig $interface inet $new_ip_address $new_subnet_arg \
                 $new_broadcast_arg $mtu_arg
 
             # point to point
-            if [ "$new_subnet_mask" == "255.255.255.255" ]; then
+            if [ "$new_subnet_mask" = "255.255.255.255" ]; then
                 for router in $new_routers; do
                     route add -host $router dev $interface
                 done
@@ -190,8 +194,8 @@ case "$reason" in
             done
         fi
 
-        if [ "$new_ip_address" != "$alias_ip_address" -a -n "$alias_ip_address" ];
-            then
+        if [ -n "$alias_ip_address" ] &&
+           [ "$new_ip_address" != "$alias_ip_address" ]; then
             ifconfig $interface:0- inet 0
             ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
             route add -host $alias_ip_address $interface:0
@@ -231,8 +235,8 @@ case "$reason" in
         first_router="$1"
 
         if [ -z "$first_router" ] || ping -q -c 1 $first_router; then
-            if [ "$new_ip_address" != "$alias_ip_address" -a \
-                -n "$alias_ip_address" ]; then
+            if [ -n "$alias_ip_address" ] &&
+               [ "$new_ip_address" != "$alias_ip_address" ]; then
                 ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
                 route add -host $alias_ip_address dev $interface:0
             fi
diff --git a/debian/dhclient-script.linux.udeb b/debian/dhclient-script.linux.udeb
index e42a55f..4028b2e 100644
--- a/debian/dhclient-script.linux.udeb
+++ b/debian/dhclient-script.linux.udeb
@@ -11,8 +11,9 @@ set -e
 # Modified for Debian.  Matt Zimmerman and Eloy Paris, December 2003
 
 make_resolv_conf() {
+    local new_resolv_conf
     if [ -n "$new_domain_name" ] || [ -n "$new_domain_name_servers" ]; then
-        local new_resolv_conf=/etc/resolv.conf.dhclient-new
+        new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
         if [ -n "$new_domain_name" ]; then
             echo "search $new_domain_name" >>$new_resolv_conf
@@ -25,7 +26,8 @@ make_resolv_conf() {
 }
 
 set_hostname() {
-    local current_hostname=$(cat /proc/sys/kernel/hostname)
+    local current_hostname
+    current_hostname=$(cat /proc/sys/kernel/hostname)
     if [ -z "$current_hostname" ] || [ "$current_hostname" = "(none)" ]; then
         echo "$new_host_name" > /proc/sys/kernel/hostname
     fi
@@ -60,8 +62,8 @@ case "$reason" in
 
         set_hostname
 
-        if [ -n "$old_ip_address" ] && \
-             [ "$old_ip_address" != "$new_ip_address" ]; then
+        if [ -n "$old_ip_address" ] &&
+           [ "$old_ip_address" != "$new_ip_address" ]; then
             # IP address changed. Bringing down the interface will delete all routes,
             # and clear the ARP cache.
             ip addr del $old_ip_address$old_mask $old_broadcast_arg dev $interface
@@ -72,8 +74,9 @@ case "$reason" in
             ip link set $interface mtu $new_interface_mtu || true
         fi
 
-        if [ -z "$old_ip_address" ] || [ "$old_ip_address" != "$new_ip_address" ] || \
-            [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
+        if [ -z "$old_ip_address" ] ||
+           [ "$old_ip_address" != "$new_ip_address" ] ||
+           [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
 
             ip link set $interface up
             ip addr flush dev $interface
-- 
1.7.2.3

-------------- next part --------------
>From 2e62c2e9c329cdb7e4ddc3f7c37aa5602cce7e8d Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 13:46:05 +0100
Subject: [PATCH 04/14] dhclient-script.{linux,kfreebsd}: fix setting of hostname


Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/dhclient-script.kfreebsd |    4 ++--
 debian/dhclient-script.linux    |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/debian/dhclient-script.kfreebsd b/debian/dhclient-script.kfreebsd
index ea03628..2f49165 100644
--- a/debian/dhclient-script.kfreebsd
+++ b/debian/dhclient-script.kfreebsd
@@ -132,8 +132,8 @@ case "$reason" in
         ;;
     BOUND|RENEW|REBIND|REBOOT)
 
-        if [ -n "$old_host_name" ] && [ -n "$host_name" ] &&
-           [ "$host_name" != "$old_host_name" ]; then
+        if [ -n "$old_host_name" ] && [ -n "$new_host_name" ] &&
+           [ "$old_host_name" != "$new_host_name" ]; then
             hostname "$new_host_name"
         fi
 
diff --git a/debian/dhclient-script.linux b/debian/dhclient-script.linux
index d065140..811a307 100644
--- a/debian/dhclient-script.linux
+++ b/debian/dhclient-script.linux
@@ -156,8 +156,8 @@ case "$reason" in
         ;;
     BOUND|RENEW|REBIND|REBOOT)
 
-        if [ -n "$old_host_name" ] && [ -n "$host_name" ] &&
-           [ "$host_name" != "$old_host_name" ]; then
+        if [ -n "$old_host_name" ] && [ -n "$new_host_name" ] &&
+           [ "$old_host_name" != "$new_host_name" ]; then
             hostname "$new_host_name"
         fi
 
-- 
1.7.2.3

-------------- next part --------------
>From d23f5808e91cf3d6999f4f9643f7ccfee215e01e Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 13:58:00 +0100
Subject: [PATCH 05/14] rfc3442-classless-routes: remove bashisms

Replace rfc3442-classless-routes by a version without bashisms.
In my opinion this also makes the algorithm easier to understand.

Together with the "deBASHification" of dhclient-script, this allows
to switch over to other shells to run dhclient-script under.

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/rfc3442-classless-routes |   88 ++++++++++++++++++++++++---------------
 1 files changed, 54 insertions(+), 34 deletions(-)

diff --git a/debian/rfc3442-classless-routes b/debian/rfc3442-classless-routes
index 33c6c72..6e14946 100644
--- a/debian/rfc3442-classless-routes
+++ b/debian/rfc3442-classless-routes
@@ -1,39 +1,59 @@
+# set classless routes based on the format specified in RFC3442
+# e.g.:
+#   new_rfc3442_classless_static_routes='24 192 168 10 192 168 1 1 8 10 10 17 66 41'
+# specifies the routes:
+#   192.168.10.0/24 via 192.168.1.1
+#   10.0.0.0/8 via 10.10.17.66.41
+
 RUN="yes"
 
 
 if [ "$RUN" = "yes" ]; then
-        if [ "$new_rfc3442_classless_static_routes" != "" ]; then
-                if [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
-                        rfc_routes=($new_rfc3442_classless_static_routes)
-
-                        for(( i=0; i < ${#rfc_routes[@]}; )); do
-                                net_length=${rfc_routes[$i]}
-
-                                ((i++))
-
-                                net_address=(0 0 0 0)
-                                for(( j=0; j < $[$net_length / 8 + \
-                                    ($net_length % 8 ? 1 : 0)]; j++, i++)); do
-
-                                        net_address[$j]=${rfc_routes[$i]}
-                                done
-
-                                gateway=(0 0 0 0)
-                                for (( j=0; j < 4; j++, i++ )); do
-                                        gateway[$j]=${rfc_routes[$i]}
-                                done
-
-                                old_IFS="$IFS"
-                                IFS='.'
-
-                                if [ "$net_length" == "32" ]; then
-                                        /sbin/route add -host "${net_address[*]}" gw "${gateway[*]}"
-                                else
-                                        /sbin/route add -net "${net_address[*]}/$net_length" gw "${gateway[*]}"
-                                fi
-                                IFS="$old_IFS"
-
-                        done
-                fi
-        fi
+	if [ -n "$new_rfc3442_classless_static_routes" ]; then
+		if [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
+
+			set -- $new_rfc3442_classless_static_routes
+
+			while [ $# -gt 0 ]; do
+				net_length=$1
+
+				case $net_length in
+					32|31|30|29|28|27|26|25)
+						net_address="${2}.${3}.${4}.${5}"
+						gateway="${6}.${7}.${8}.${9}"
+						shift 9
+						;;
+					24|23|22|21|20|19|18|17)
+						net_address="${2}.${3}.${4}.0"
+						gateway="${5}.${6}.${7}.${8}"
+						shift 8
+						;;
+					16|15|14|13|12|11|10|9)
+						net_address="${2}.${3}.0.0"
+						gateway="${4}.${5}.${6}.${7}"
+						shift 7
+						;;
+					8|7|6|5|4|3|2|1)
+						net_address="${2}.0.0.0"
+						gateway="${3}.${4}.${5}.${6}"
+						shift 6
+						;;
+					0)	# default route
+						net_address="0.0.0.0"
+						gateway="${2}.${3}.${4}.${5}"
+						shift 5
+						;;
+					*)	# error
+						return 1
+						;;
+				esac
+
+				if [ "$net_length" -eq 32 ]; then
+					/sbin/route add -host "${net_address}" gw "${gateway}"
+				else
+					/sbin/route add -net "${net_address}/${net_length}" gw "${gateway}"
+				fi
+			done
+		fi
+	fi
 fi
-- 
1.7.2.3

-------------- next part --------------
>From 67a605b234bf8f8534b6e0f80a827b41da0db6c0 Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 14:04:56 +0100
Subject: [PATCH 06/14] dhclient-script.{linux.kfreebsd}: check for $new_domain_search

Check for $new_domain_search in make_resolv_conf() too, as trigger
to start updating /etc/resolv.conf

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/dhclient-script.kfreebsd |    3 ++-
 debian/dhclient-script.linux    |    3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/debian/dhclient-script.kfreebsd b/debian/dhclient-script.kfreebsd
index 2f49165..b6f3bfd 100644
--- a/debian/dhclient-script.kfreebsd
+++ b/debian/dhclient-script.kfreebsd
@@ -4,7 +4,8 @@
 
 make_resolv_conf() {
     local new_resolv_conf
-    if [ -n "$new_domain_name" ] || [ -n "$new_domain_name_servers" ]; then
+    if [ -n "$new_domain_search" ] || [ -n "$new_domain_name" ] ||
+       [ -n "$new_domain_name_servers" ]; then
         new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
         if [ -n "$new_domain_name" ]; then
diff --git a/debian/dhclient-script.linux b/debian/dhclient-script.linux
index 811a307..6f9c726 100644
--- a/debian/dhclient-script.linux
+++ b/debian/dhclient-script.linux
@@ -14,7 +14,8 @@
 
 make_resolv_conf() {
     local new_resolv_conf
-    if [ "$new_domain_name" ] || [ "$new_domain_name_servers" ]; then
+    if [ -n "$new_domain_search" ] || [ -n "$new_domain_name" ] ||
+       [ -n "$new_domain_name_servers" ]; then
         new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
         if [ "$new_domain_name" ]; then
-- 
1.7.2.3

-------------- next part --------------
>From 3d48de0551efb6e0378448432ddf47d79df642ab Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 14:28:47 +0100
Subject: [PATCH 07/14] dhclient-script.linux: synchronize a bit more with dhclient-script.kfreebsd

Change
	if [ "$..." ]
to
	if [ -n "$..." ]
to minimize differences to dhclient-script.kfreebsd

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/dhclient-script.linux |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/debian/dhclient-script.linux b/debian/dhclient-script.linux
index 6f9c726..12583db 100644
--- a/debian/dhclient-script.linux
+++ b/debian/dhclient-script.linux
@@ -18,12 +18,12 @@ make_resolv_conf() {
        [ -n "$new_domain_name_servers" ]; then
         new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
-        if [ "$new_domain_name" ]; then
+        if [ -n "$new_domain_name" ]; then
             echo domain ${new_domain_name%% *} >>$new_resolv_conf
         fi
-        if [ "$new_domain_search" ]; then
+        if [ -n "$new_domain_search" ]; then
             #new_domain_search="${new_domain_search% }"
-            if [ "$new_domain_name" ]; then
+            if [ -n "$new_domain_name" ]; then
                 domain_in_search_list=""
                 for domain in $new_domain_search; do
                     if [ "$domain" = "${new_domain_name}" ] ||
@@ -36,10 +36,10 @@ make_resolv_conf() {
                 fi
             fi
             echo "search ${new_domain_search}" >> $new_resolv_conf
-        elif [ "$new_domain_name" ]; then
+        elif [ -n "$new_domain_name" ]; then
             echo "search ${new_domain_name}" >> $new_resolv_conf
         fi
-        if [ "$new_domain_name_servers" ]; then
+        if [ -n "$new_domain_name_servers" ]; then
             for nameserver in $new_domain_name_servers; do
                 echo nameserver $nameserver >>$new_resolv_conf
             done
-- 
1.7.2.3

-------------- next part --------------
>From d4bbc4f8762e4f36c07debe14e335fda29cb3850 Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 15:23:40 +0100
Subject: [PATCH 08/14] dhclient-script.*: add comments & empty lines for easier reading

Harmonize "paragraphs" between the 4 dhclient-script implementations.

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/dhclient-script.kfreebsd      |   20 ++++++++++++++++----
 debian/dhclient-script.kfreebsd.udeb |   10 +++++++++-
 debian/dhclient-script.linux         |   17 ++++++++++++-----
 debian/dhclient-script.linux.udeb    |   10 +++++++++-
 4 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/debian/dhclient-script.kfreebsd b/debian/dhclient-script.kfreebsd
index b6f3bfd..ef72750 100644
--- a/debian/dhclient-script.kfreebsd
+++ b/debian/dhclient-script.kfreebsd
@@ -2,15 +2,19 @@
 # dhclient-script for GNU/kFreeBSD. Aurelien Jarno, May, 2005.
 # Based on Linux and FreeBSD scripts.
 
+# update /etc/resolv.conf based on received values
 make_resolv_conf() {
     local new_resolv_conf
+
     if [ -n "$new_domain_search" ] || [ -n "$new_domain_name" ] ||
        [ -n "$new_domain_name_servers" ]; then
         new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
+
         if [ -n "$new_domain_name" ]; then
             echo domain ${new_domain_name%% *} >>$new_resolv_conf
         fi
+
         if [ -n "$new_domain_search" ]; then
             new_domain_search="${new_domain_search% }"
             if [ -n "$new_domain_name" ]; then
@@ -20,6 +24,7 @@ make_resolv_conf() {
         elif [ -n "$new_domain_name" ]; then
             echo "search ${new_domain_name}" >> $new_resolv_conf
         fi
+
         if [ -n "$new_domain_name_servers" ]; then
             for nameserver in $new_domain_name_servers; do
                 echo nameserver $nameserver >>$new_resolv_conf
@@ -27,12 +32,14 @@ make_resolv_conf() {
         else # keep 'old' nameservers
             sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p /etc/resolv.conf >>$new_resolv_conf
         fi
+
         chown --reference=/etc/resolv.conf $new_resolv_conf
         chmod --reference=/etc/resolv.conf $new_resolv_conf
         mv -f $new_resolv_conf /etc/resolv.conf
     fi
 }
 
+# run given script
 run_hook() {
     local script
     local exit_status
@@ -43,7 +50,6 @@ run_hook() {
         . $script "$@"
     fi
 
-
     if [ -n "$exit_status" ] && [ "$exit_status" -ne 0 ]; then
         logger -p daemon.err "$script returned non-zero exit status $exit_status"
         save_exit_status=$exit_status
@@ -52,6 +58,7 @@ run_hook() {
     return $exit_status
 }
 
+# run scripts in given directory
 run_hookdir() {
     local dir
     local exit_status
@@ -85,6 +92,8 @@ exit_with_hooks() {
     exit $exit_status
 }
 
+
+# set up some variables for DHCPv4 handlers below
 if [ -n "$new_broadcast_address" ]; then
     new_broadcast_arg="broadcast $new_broadcast_address"
 fi
@@ -123,16 +132,17 @@ case "$reason" in
         # The DHCP client is requesting that an interface be
         # configured as required in order to send packets prior to
         # receiving an actual address. - dhclient-script(8)
-
         if [ -n "$alias_ip_address" ]; then
             ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
             route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
         fi
+
         ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
             broadcast 255.255.255.255 up
+
         ;;
-    BOUND|RENEW|REBIND|REBOOT)
 
+    BOUND|RENEW|REBIND|REBOOT)
         if [ -n "$old_host_name" ] && [ -n "$new_host_name" ] &&
            [ "$old_host_name" != "$new_host_name" ]; then
             hostname "$new_host_name"
@@ -144,6 +154,7 @@ case "$reason" in
             ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
             route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
         fi
+
         if [ -n "$old_ip_address" ] &&
            [ "$old_ip_address" != "$new_ip_address" ]; then
             ifconfig $interface inet -alias $old_ip_address $medium
@@ -163,13 +174,14 @@ case "$reason" in
         if [ -z "$old_ip_address" ] ||
            [ "$old_ip_address" != "$new_ip_address" ] ||
            [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
-
             ifconfig $interface inet $new_ip_address $new_subnet_arg \
                 $new_broadcast_arg $medium $mtu_arg
             route add $new_ip_address 127.1 $metric_arg >/dev/null 2>&1
+
             for router in $new_routers; do
                 route add default $router >/dev/null 2>&1
             done
+
             if [ -n "$new_static_routes" ]; then
                 set -- $new_static_routes
                 while [ $# -gt 1 ]; do
diff --git a/debian/dhclient-script.kfreebsd.udeb b/debian/dhclient-script.kfreebsd.udeb
index 73f556d..335ba28 100644
--- a/debian/dhclient-script.kfreebsd.udeb
+++ b/debian/dhclient-script.kfreebsd.udeb
@@ -10,17 +10,22 @@ set -e
 # Updated for Linux 2.[12] by Brian J. Murrell, January 1999.
 # Modified for Debian.  Matt Zimmerman and Eloy Paris, December 2003
 
+# update /etc/resolv.conf based on received values
 make_resolv_conf() {
     local new_resolv_conf
+
     if [ -n "$new_domain_name" ] || [ -n "$new_domain_name_servers" ]; then
         new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
+
         if [ -n "$new_domain_name" ]; then
             echo "search $new_domain_name" >>$new_resolv_conf
         fi
+
         for nameserver in $new_domain_name_servers; do
             echo "nameserver $nameserver" >>$new_resolv_conf
         done
+
         mv $new_resolv_conf /etc/resolv.conf
     fi
 }
@@ -28,11 +33,13 @@ make_resolv_conf() {
 set_hostname() {
     local current_hostname
     current_hostname=$(hostname)
+
     if [ -z "$current_hostname" ] || [ "$current_hostname" = "(none)" ]; then
         hostname "$new_host_name"
     fi
 }
 
+# set up some variables for DHCP handlers below
 if [ -n "$new_subnet_mask" ]; then
     new_mask="/$(ptom $new_subnet_mask)"
 fi
@@ -58,9 +65,10 @@ case "$reason" in
 
         # We need to give the kernel some time to get the interface up.
         sleep 1
+
         ;;
-    BOUND|RENEW|REBIND|REBOOT)
 
+    BOUND|RENEW|REBIND|REBOOT)
         set_hostname
 
         if [ -n "$old_ip_address" ] &&
diff --git a/debian/dhclient-script.linux b/debian/dhclient-script.linux
index 12583db..6667c49 100644
--- a/debian/dhclient-script.linux
+++ b/debian/dhclient-script.linux
@@ -12,15 +12,19 @@
 
 # The alias handling in here probably still sucks. -mdz
 
+# update /etc/resolv.conf based on received values
 make_resolv_conf() {
     local new_resolv_conf
+
     if [ -n "$new_domain_search" ] || [ -n "$new_domain_name" ] ||
        [ -n "$new_domain_name_servers" ]; then
         new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
+
         if [ -n "$new_domain_name" ]; then
             echo domain ${new_domain_name%% *} >>$new_resolv_conf
         fi
+
         if [ -n "$new_domain_search" ]; then
             #new_domain_search="${new_domain_search% }"
             if [ -n "$new_domain_name" ]; then
@@ -39,6 +43,7 @@ make_resolv_conf() {
         elif [ -n "$new_domain_name" ]; then
             echo "search ${new_domain_name}" >> $new_resolv_conf
         fi
+
         if [ -n "$new_domain_name_servers" ]; then
             for nameserver in $new_domain_name_servers; do
                 echo nameserver $nameserver >>$new_resolv_conf
@@ -46,12 +51,14 @@ make_resolv_conf() {
         else # keep 'old' nameservers
             sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p /etc/resolv.conf >>$new_resolv_conf
         fi
+
         chown --reference=/etc/resolv.conf $new_resolv_conf
         chmod --reference=/etc/resolv.conf $new_resolv_conf
         mv -f $new_resolv_conf /etc/resolv.conf
     fi
 }
 
+# run given script
 run_hook() {
     local script
     local exit_status
@@ -62,7 +69,6 @@ run_hook() {
         . $script "$@"
     fi
 
-
     if [ -n "$exit_status" ] && [ "$exit_status" -ne 0 ]; then
         logger -p daemon.err "$script returned non-zero exit status $exit_status"
         save_exit_status=$exit_status
@@ -71,6 +77,7 @@ run_hook() {
     return $exit_status
 }
 
+# run scripts in given directory
 run_hookdir() {
     local dir
     local exit_status
@@ -104,6 +111,8 @@ exit_with_hooks() {
     exit $exit_status
 }
 
+
+# set up some variables for DHCPv4 handlers below
 if [ -n "$new_broadcast_address" ]; then
     new_broadcast_arg="broadcast $new_broadcast_address"
 fi
@@ -147,16 +156,16 @@ case "$reason" in
         # The DHCP client is requesting that an interface be
         # configured as required in order to send packets prior to
         # receiving an actual address. - dhclient-script(8)
-
         if [ -n "$alias_ip_address" ]; then
             # Bring down alias interface. Its routes will disappear too.
             ifconfig $interface:0- inet 0
         fi
+
         ifconfig $interface inet 0 up
 
         ;;
-    BOUND|RENEW|REBIND|REBOOT)
 
+    BOUND|RENEW|REBIND|REBOOT)
         if [ -n "$old_host_name" ] && [ -n "$new_host_name" ] &&
            [ "$old_host_name" != "$new_host_name" ]; then
             hostname "$new_host_name"
@@ -173,13 +182,11 @@ case "$reason" in
             # IP address changed. Bringing down the interface will delete all routes,
             # and clear the ARP cache.
             ifconfig $interface inet 0
-
         fi
 
         if [ -z "$old_ip_address" ] ||
            [ "$old_ip_address" != "$new_ip_address" ] ||
            [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
-
             ifconfig $interface inet $new_ip_address $new_subnet_arg \
                 $new_broadcast_arg $mtu_arg
 
diff --git a/debian/dhclient-script.linux.udeb b/debian/dhclient-script.linux.udeb
index 4028b2e..505b035 100644
--- a/debian/dhclient-script.linux.udeb
+++ b/debian/dhclient-script.linux.udeb
@@ -10,17 +10,22 @@ set -e
 # Updated for Linux 2.[12] by Brian J. Murrell, January 1999.
 # Modified for Debian.  Matt Zimmerman and Eloy Paris, December 2003
 
+# update /etc/resolv.conf based on received values
 make_resolv_conf() {
     local new_resolv_conf
+
     if [ -n "$new_domain_name" ] || [ -n "$new_domain_name_servers" ]; then
         new_resolv_conf=/etc/resolv.conf.dhclient-new
         rm -f $new_resolv_conf
+
         if [ -n "$new_domain_name" ]; then
             echo "search $new_domain_name" >>$new_resolv_conf
         fi
+
         for nameserver in $new_domain_name_servers; do
             echo "nameserver $nameserver" >>$new_resolv_conf
         done
+
         mv $new_resolv_conf /etc/resolv.conf
     fi
 }
@@ -28,11 +33,13 @@ make_resolv_conf() {
 set_hostname() {
     local current_hostname
     current_hostname=$(cat /proc/sys/kernel/hostname)
+
     if [ -z "$current_hostname" ] || [ "$current_hostname" = "(none)" ]; then
         echo "$new_host_name" > /proc/sys/kernel/hostname
     fi
 }
 
+# set up some variables for DHCP handlers below
 if [ -n "$new_subnet_mask" ]; then
     new_mask="/$(ptom $new_subnet_mask)"
 fi
@@ -57,9 +64,10 @@ case "$reason" in
 
         # We need to give the kernel some time to get the interface up.
         sleep 1
+
         ;;
-    BOUND|RENEW|REBIND|REBOOT)
 
+    BOUND|RENEW|REBIND|REBOOT)
         set_hostname
 
         if [ -n "$old_ip_address" ] &&
-- 
1.7.2.3

-------------- next part --------------
>From 477b3dc158e29a105f7137ad2741a6f4c0a63a08 Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 16:12:14 +0100
Subject: [PATCH 09/14] dhclient-script.linux: add DHCPv6 support

* add handlers for DHCPv6
* extend make_resolv_conf() by DHCPv6 part

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/dhclient-script.linux |   76 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/debian/dhclient-script.linux b/debian/dhclient-script.linux
index 6667c49..7f74b4e 100644
--- a/debian/dhclient-script.linux
+++ b/debian/dhclient-script.linux
@@ -16,6 +16,7 @@
 make_resolv_conf() {
     local new_resolv_conf
 
+    # DHCPv4
     if [ -n "$new_domain_search" ] || [ -n "$new_domain_name" ] ||
        [ -n "$new_domain_name_servers" ]; then
         new_resolv_conf=/etc/resolv.conf.dhclient-new
@@ -55,6 +56,26 @@ make_resolv_conf() {
         chown --reference=/etc/resolv.conf $new_resolv_conf
         chmod --reference=/etc/resolv.conf $new_resolv_conf
         mv -f $new_resolv_conf /etc/resolv.conf
+    # DHCPv6
+    elif [ -n "$new_dhcp6_domain_search" ] || [ -n "$new_dhcp6_name_servers" ]; then
+        new_resolv_conf=/etc/resolv.conf.dhclient-new
+        rm -f $new_resolv_conf
+
+        if [ -n "$new_dhcp6_domain_search" ]; then
+            echo "search ${new_dhcp6_domain_search}" >> $new_resolv_conf
+        fi
+
+        if [ -n "$new_dhcp6_name_servers" ]; then
+            for nameserver in $new_dhcp6_name_servers; do
+                echo nameserver $nameserver >>$new_resolv_conf
+            done
+        else # keep 'old' nameservers
+            sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p /etc/resolv.conf >>$new_resolv_conf
+        fi
+
+        chown --reference=/etc/resolv.conf $new_resolv_conf
+        chmod --reference=/etc/resolv.conf $new_resolv_conf
+        mv -f $new_resolv_conf /etc/resolv.conf
     fi
 }
 
@@ -149,6 +170,9 @@ run_hookdir /etc/dhcp/dhclient-enter-hooks.d
 
 # Execute the operation
 case "$reason" in
+
+    ### DHCPv4 Handlers
+
     MEDIUM|ARPCHECK|ARPSEND)
         # Do nothing
         ;;
@@ -261,6 +285,58 @@ case "$reason" in
         fi
 
         ;;
+
+    ### DHCPv6 Handlers
+    # TODO handle prefix change: ?based on ${old_ip6_prefix} and ${new_ip6_prefix}?
+
+    PREINIT6)
+        # ensure interface is up
+        ip link set ${interface} up
+
+        # flush any stale global permanent IPs from interface
+        ip -6 addr flush dev ${interface} scope global permanent
+
+        ;;
+
+    BOUND6|RENEW6|REBIND6)
+        if [ -z "${new_ip6_address}" ] || [ -z "${new_ip6_prefixlen}" ]; then
+            exit_with_hooks 2
+        fi
+
+        # set leased IP
+        ip -6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \
+            dev ${interface} scope global
+
+        # update /etc/resolv.conf
+        if [ "${reason}" = BOUND6 ] ||
+           [ "${new_dhcp6_name_servers}" != "${old_dhcp6_name_servers}" ] ||
+           [ "${new_dhcp6_domain_search}" != "${old_dhcp6_domain_search}" ]; then
+            make_resolv_conf
+        fi
+
+        ;;
+
+    DEPREF6)
+        if [ -z "${cur_ip6_prefixlen}" ]; then
+            exit_with_hooks 2
+        fi
+
+        # set preferred lifetime of leased IP to 0
+        ip -6 addr change ${cur_ip6_address}/${cur_ip6_prefixlen} \
+            dev ${interface} scope global preferred_lft 0
+
+        ;;
+
+    EXPIRE6|RELEASE6|STOP6)
+        if [ -z "${old_ip6_address}" ] || [ -z "${old_ip6_prefixlen}" ]; then
+            exit_with_hooks 2
+        fi
+
+        # delete leased IP
+        ip -6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \
+            dev ${interface}
+
+        ;;
 esac
 
 exit_with_hooks 0
-- 
1.7.2.3

-------------- next part --------------
>From 72a65cc05a45d88b3676f3b5b1ccd6b9f909cb86 Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 16:30:08 +0100
Subject: [PATCH 10/14] debug-*: show more complete list of DHCP variables

Show many more variables:
* all prefixes: cur_, new_, old_  & empty prefix as a trick for un-prefixed vars
* include DHCPv6 related variables

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/debug-enter |   24 +++++++++++++++++-------
 debian/debug-exit  |   25 ++++++++++++++++++-------
 2 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/debian/debug-enter b/debian/debug-enter
index 26564f5..2bdd5fd 100644
--- a/debian/debug-enter
+++ b/debian/debug-enter
@@ -13,14 +13,24 @@ if [ "$RUN" = "yes" ]; then
 	echo `date`: entering dhclient-enter-hooks.d, dumping variables. \
 		>> /tmp/dhclient-script.debug
 
-	for i in reason interface medium alias_ip_address new_ip_address \
-		new_subnet_mask new_domain_name new_domain_search \
-		new_domain_name_servers \
-		new_routers new_static_routes old_ip_address old_subnet_mask \
-		old_domain_name old_domain_search old_domain_name_servers \
-		old_routers old_static_routes; do
+	# loop over the 4 possible prefixes: (empty), cur_, new_, old_
+	for prefix in '' 'cur_' 'new_' 'old_'; do
+		# loop over the DHCP variables passed to dhclient-script
+		for basevar in reason interface medium alias_ip_address \
+			       ip_address host_name network_number subnet_mask \
+			       broadcast_address routers static_routes \
+			       rfc3442_classless_static_routes \
+			       domain_name domain_search domain_name_servers \
+			       netbios_name_servers netbios_scope \
+			       ntp_servers \
+			       ip6_address ip6_prefix ip6_prefixlen \
+			       dhcp6_domain_search dhcp6_name_servers ; do
+			var="${prefix}${basevar}"
 
-		echo $i=\'${!i}\' >> /tmp/dhclient-script.debug
+			if [ -n "${!var}" ]; then
+				echo "$var='${!var}'" >> /tmp/dhclient-script.debug
+			fi
+		done
 	done
 
 	echo '--------------------------' >> /tmp/dhclient-script.debug
diff --git a/debian/debug-exit b/debian/debug-exit
index 9173ac5..e16d204 100644
--- a/debian/debug-exit
+++ b/debian/debug-exit
@@ -13,13 +13,24 @@ if [ "$RUN" = "yes" ]; then
 	echo `date`: entering dhclient-exit-hooks.d, dumping variables. \
 		>> /tmp/dhclient-script.debug
 
-	for i in reason interface medium alias_ip_address new_ip_address \
-			new_subnet_mask new_domain_name new_domain_search \
-			new_domain_name_servers new_routers new_static_routes \
-			old_ip_address old_subnet_mask old_domain_name \
-			old_domain_search old_domain_name_servers old_routers \
-			old_static_routes; do
-		echo $i=\'${!i}\' >> /tmp/dhclient-script.debug
+	# loop over the 4 possible prefixes: (empty), cur_, new_, old_
+	for prefix in '' 'cur_' 'new_' 'old_'; do
+		# loop over the DHCP variables passed to dhclient-script
+		for basevar in reason interface medium alias_ip_address \
+			       ip_address host_name network_number subnet_mask \
+			       broadcast_address routers static_routes \
+			       rfc3442_classless_static_routes \
+			       domain_name domain_search domain_name_servers \
+			       netbios_name_servers netbios_scope \
+			       ntp_servers \
+			       ip6_address ip6_prefix ip6_prefixlen \
+			       dhcp6_domain_search dhcp6_name_servers ; do
+			var="${prefix}${basevar}"
+
+			if [ -n "${!var}" ]; then
+				echo "$var='${!var}'" >> /tmp/dhclient-script.debug
+			fi
+		done
 	done
 
 	echo '--------------------------' >> /tmp/dhclient-script.debug
-- 
1.7.2.3

-------------- next part --------------
>From c26a63a363884a811b385f0c0881e05c5dfe1535 Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 19:36:48 +0100
Subject: [PATCH 11/14] dhclient-script.{linux,kfreebsd}: remove unused variables

* $old_subnet_arg is nowhere used in dhclient-script.{linux,kfreebsd},
  so remove its definition.
* the same applies to $safe_exit_satus
* $new_domain_search is a list of domain names that cannot sensibly end
  with spaces. Remove this check

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/dhclient-script.kfreebsd |    5 -----
 debian/dhclient-script.linux    |    5 -----
 2 files changed, 0 insertions(+), 10 deletions(-)

diff --git a/debian/dhclient-script.kfreebsd b/debian/dhclient-script.kfreebsd
index ef72750..f3f93bd 100644
--- a/debian/dhclient-script.kfreebsd
+++ b/debian/dhclient-script.kfreebsd
@@ -16,7 +16,6 @@ make_resolv_conf() {
         fi
 
         if [ -n "$new_domain_search" ]; then
-            new_domain_search="${new_domain_search% }"
             if [ -n "$new_domain_name" ]; then
                 new_domain_search="$new_domain_name $new_domain_search"
             fi
@@ -52,7 +51,6 @@ run_hook() {
 
     if [ -n "$exit_status" ] && [ "$exit_status" -ne 0 ]; then
         logger -p daemon.err "$script returned non-zero exit status $exit_status"
-        save_exit_status=$exit_status
     fi
 
     return $exit_status
@@ -103,9 +101,6 @@ fi
 if [ -n "$new_subnet_mask" ]; then
     new_subnet_arg="netmask $new_subnet_mask"
 fi
-if [ -n "$old_subnet_mask" ]; then
-    old_subnet_arg="netmask $old_subnet_mask"
-fi
 if [ -n "$alias_subnet_mask" ]; then
     alias_subnet_arg="netmask $alias_subnet_mask"
 fi
diff --git a/debian/dhclient-script.linux b/debian/dhclient-script.linux
index 7f74b4e..3ab16bf 100644
--- a/debian/dhclient-script.linux
+++ b/debian/dhclient-script.linux
@@ -27,7 +27,6 @@ make_resolv_conf() {
         fi
 
         if [ -n "$new_domain_search" ]; then
-            #new_domain_search="${new_domain_search% }"
             if [ -n "$new_domain_name" ]; then
                 domain_in_search_list=""
                 for domain in $new_domain_search; do
@@ -92,7 +91,6 @@ run_hook() {
 
     if [ -n "$exit_status" ] && [ "$exit_status" -ne 0 ]; then
         logger -p daemon.err "$script returned non-zero exit status $exit_status"
-        save_exit_status=$exit_status
     fi
 
     return $exit_status
@@ -143,9 +141,6 @@ fi
 if [ -n "$new_subnet_mask" ]; then
     new_subnet_arg="netmask $new_subnet_mask"
 fi
-if [ -n "$old_subnet_mask" ]; then
-    old_subnet_arg="netmask $old_subnet_mask"
-fi
 if [ -n "$alias_subnet_mask" ]; then
     alias_subnet_arg="netmask $alias_subnet_mask"
 fi
-- 
1.7.2.3

-------------- next part --------------
>From ffcb3e25d7f9d1c7a065e8cfc13e15552df1f953 Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 21:48:56 +0100
Subject: [PATCH 12/14] dhclient-script.linux: convert to iproute2

Convert the IPv4 part from ifconfig & route to iproute2's ip
and comment what is done.

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/dhclient-script.linux |  106 +++++++++++++++++++++++++----------------
 1 files changed, 65 insertions(+), 41 deletions(-)

diff --git a/debian/dhclient-script.linux b/debian/dhclient-script.linux
index 3ab16bf..624a17e 100644
--- a/debian/dhclient-script.linux
+++ b/debian/dhclient-script.linux
@@ -139,18 +139,18 @@ if [ -n "$old_broadcast_address" ]; then
     old_broadcast_arg="broadcast $old_broadcast_address"
 fi
 if [ -n "$new_subnet_mask" ]; then
-    new_subnet_arg="netmask $new_subnet_mask"
+    new_mask="/$new_subnet_mask"
 fi
 if [ -n "$alias_subnet_mask" ]; then
-    alias_subnet_arg="netmask $alias_subnet_mask"
+    alias_mask="/$alias_subnet_mask"
 fi
 # The 576 MTU is only used for X.25 and dialup connections
 # where the admin wants low latency.  Such a low MTU can cause
 # problems with UDP traffic, among other things.  As such,
 # disallow MTUs from 576 and below by default, so that broken
 # MTUs are ignored, but higher stuff is allowed (1492, 1500, etc).
-if [ -n "$new_interface_mtu" ] && [ $new_interface_mtu -gt 576 ]; then
-    mtu_arg="mtu $new_interface_mtu"
+if [ -z "$new_interface_mtu" ] || [ "$new_interface_mtu" -lt 576 ]; then
+    new_interface_mtu=''
 fi
 if [ -n "$IF_METRIC" ]; then
     metric_arg="metric $IF_METRIC"	# interfaces(5), "metric" option
@@ -175,107 +175,131 @@ case "$reason" in
         # The DHCP client is requesting that an interface be
         # configured as required in order to send packets prior to
         # receiving an actual address. - dhclient-script(8)
+
+        # ensure interface is up
+        ip link set dev ${interface} up
+
         if [ -n "$alias_ip_address" ]; then
-            # Bring down alias interface. Its routes will disappear too.
-            ifconfig $interface:0- inet 0
+            # flush alias IP from interface
+            ip -4 addr flush dev ${interface} label ${interface}:0
         fi
 
-        ifconfig $interface inet 0 up
-
         ;;
 
     BOUND|RENEW|REBIND|REBOOT)
         if [ -n "$old_host_name" ] && [ -n "$new_host_name" ] &&
            [ "$old_host_name" != "$new_host_name" ]; then
+            # hostname changed => set it
             hostname "$new_host_name"
         fi
 
         if [ -n "$old_ip_address" ] && [ -n "$alias_ip_address" ] &&
            [ "$alias_ip_address" != "$old_ip_address" ]; then
-            # Possible new alias. Remove old alias.
-            ifconfig $interface:0- inet 0
+            # alias IP may have changed => flush it
+            ip -4 addr flush dev ${interface} label ${interface}:0
         fi
 
         if [ -n "$old_ip_address" ] &&
            [ "$old_ip_address" != "$new_ip_address" ]; then
-            # IP address changed. Bringing down the interface will delete all routes,
-            # and clear the ARP cache.
-            ifconfig $interface inet 0
+            # leased IP has changed => flush it
+            ip -4 addr flush dev ${interface} label ${interface}
         fi
 
         if [ -z "$old_ip_address" ] ||
            [ "$old_ip_address" != "$new_ip_address" ] ||
            [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
-            ifconfig $interface inet $new_ip_address $new_subnet_arg \
-                $new_broadcast_arg $mtu_arg
+            # new IP has been leased or leased IP changed => set it
+            ip -4 addr add ${new_ip_address}${new_mask} ${new_broadcast_arg} \
+                dev ${interface} label ${interface}
 
-            # point to point
-            if [ "$new_subnet_mask" = "255.255.255.255" ]; then
-                for router in $new_routers; do
-                    route add -host $router dev $interface
-                done
+            if [ -n "$new_interface_mtu" ]; then
+                # set MTU
+                ip link set dev ${interface} mtu ${new_interface_mtu}
             fi
 
             for router in $new_routers; do
-                route add default dev $interface gw $router $metric_arg
+                if [ "$new_subnet_mask" = "255.255.255.255" ]; then
+                    # point-to-point connection => set explicit route
+                    ip -4 route add ${router} dev $interface >/dev/null 2>&1
+                fi
+
+                # set default route
+                ip -4 route add default via ${router} dev ${interface} \
+                    ${metric_arg} >/dev/null 2>&1
             done
         fi
 
         if [ -n "$alias_ip_address" ] &&
            [ "$new_ip_address" != "$alias_ip_address" ]; then
-            ifconfig $interface:0- inet 0
-            ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
-            route add -host $alias_ip_address $interface:0
+            # separate alias IP given, which may have changed
+            # => flush it, set it & add host route to it
+            ip -4 addr flush dev ${interface} label ${interface}:0
+            ip -4 addr add ${alias_ip_address}${alias_mask} \
+                dev ${interface} label ${interface}:0
+            ip -4 route add ${alias_ip_address} dev ${interface} >/dev/null 2>&1
         fi
 
+        # update /etc/resolv.conf
         make_resolv_conf
 
         ;;
 
     EXPIRE|FAIL|RELEASE|STOP)
         if [ -n "$alias_ip_address" ]; then
-            # Turn off alias interface.
-            ifconfig $interface:0- inet 0
+            # flush alias IP
+            ip -4 addr flush dev ${interface} label ${interface}:0
         fi
 
         if [ -n "$old_ip_address" ]; then
-            # Shut down interface, which will delete routes and clear arp cache.
-            ifconfig $interface inet 0
+            # flush leased IP
+            ip -4 addr flush dev ${interface} label ${interface}
         fi
 
         if [ -n "$alias_ip_address" ]; then
-            ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
-            route add -host $alias_ip_address $interface:0
+            # alias IP given => set it & add host route to it
+            ip -4 addr add ${alias_ip_address}${alias_network_arg} \
+                dev ${interface} label ${interface}:0
+            ip -4 route add ${alias_ip_address} dev ${interface} >/dev/null 2>&1
         fi
 
         ;;
 
     TIMEOUT)
         if [ -n "$alias_ip_address" ]; then
-            ifconfig $interface:0- inet 0
+            # flush alias IP
+            ip -4 addr flush dev ${interface} label ${interface}:0
         fi
 
-        ifconfig $interface inet $new_ip_address $new_subnet_arg \
-            $new_broadcast_arg $mtu_arg
+        # set IP from recorded lease
+        ip -4 addr add ${new_ip_address}${new_mask} ${new_broadcast_arg} \
+            dev ${interface} label ${interface}
 
-        set -- $new_routers
-        first_router="$1"
+        if [ -n "$new_interface_mtu" ]; then
+            # set MTU
+            ip link set dev ${interface} mtu ${new_interface_mtu}
+        fi
 
-        if [ -z "$first_router" ] || ping -q -c 1 $first_router; then
+        # if there is no router recorded in the lease or the 1st router answers pings
+        if [ -z "$new_routers" ] || ping -q -c 1 "${new_routers%% *}"; then
             if [ -n "$alias_ip_address" ] &&
                [ "$new_ip_address" != "$alias_ip_address" ]; then
-                ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
-                route add -host $alias_ip_address dev $interface:0
+                # separate alias IP given => set up the alias IP & add host route to it
+                ip -4 addr add ${alias_ip_address}${alias_mask} \
+                    dev ${interface} label ${interface}:0
+                ip -4 route add ${alias_ip_address} dev ${interface} >/dev/null 2>&1
             fi
 
+            # set default route
             for router in $new_routers; do
-                route add default dev $interface gw $router $metric_arg
+                ip -4 route add default via ${router} dev ${interface} \
+                    ${metric_arg} >/dev/null 2>&1
             done
 
+            # update /etc/resolv.conf
             make_resolv_conf
         else
-            # Changed from 'ifconfig $interface inet 0 down' - see Debian bug #144666
-            ifconfig $interface inet 0
+            # flush all IPs from interface
+            ip -4 addr flush dev ${interface}
             exit_with_hooks 2 "$@"
         fi
 
-- 
1.7.2.3

-------------- next part --------------
>From 2d205f5fbb87e7e3e97666da912ee9e999ba3696 Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sat, 8 Jan 2011 22:45:12 +0100
Subject: [PATCH 13/14] rfc3442-classless-routes: split by OS and convert to iproute2

* split rfc3442-classless-routes into a variant for kfreebsd & linux
* convert the linux variant to iproute2
* update rules to install the correct variant per OS

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/rfc3442-classless-routes          |   59 ------------------------------
 debian/rfc3442-classless-routes.kfreebsd |   59 ++++++++++++++++++++++++++++++
 debian/rfc3442-classless-routes.linux    |   57 +++++++++++++++++++++++++++++
 debian/rules                             |    3 +-
 4 files changed, 118 insertions(+), 60 deletions(-)
 delete mode 100644 debian/rfc3442-classless-routes
 create mode 100644 debian/rfc3442-classless-routes.kfreebsd
 create mode 100644 debian/rfc3442-classless-routes.linux

diff --git a/debian/rfc3442-classless-routes b/debian/rfc3442-classless-routes
deleted file mode 100644
index 6e14946..0000000
--- a/debian/rfc3442-classless-routes
+++ /dev/null
@@ -1,59 +0,0 @@
-# set classless routes based on the format specified in RFC3442
-# e.g.:
-#   new_rfc3442_classless_static_routes='24 192 168 10 192 168 1 1 8 10 10 17 66 41'
-# specifies the routes:
-#   192.168.10.0/24 via 192.168.1.1
-#   10.0.0.0/8 via 10.10.17.66.41
-
-RUN="yes"
-
-
-if [ "$RUN" = "yes" ]; then
-	if [ -n "$new_rfc3442_classless_static_routes" ]; then
-		if [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
-
-			set -- $new_rfc3442_classless_static_routes
-
-			while [ $# -gt 0 ]; do
-				net_length=$1
-
-				case $net_length in
-					32|31|30|29|28|27|26|25)
-						net_address="${2}.${3}.${4}.${5}"
-						gateway="${6}.${7}.${8}.${9}"
-						shift 9
-						;;
-					24|23|22|21|20|19|18|17)
-						net_address="${2}.${3}.${4}.0"
-						gateway="${5}.${6}.${7}.${8}"
-						shift 8
-						;;
-					16|15|14|13|12|11|10|9)
-						net_address="${2}.${3}.0.0"
-						gateway="${4}.${5}.${6}.${7}"
-						shift 7
-						;;
-					8|7|6|5|4|3|2|1)
-						net_address="${2}.0.0.0"
-						gateway="${3}.${4}.${5}.${6}"
-						shift 6
-						;;
-					0)	# default route
-						net_address="0.0.0.0"
-						gateway="${2}.${3}.${4}.${5}"
-						shift 5
-						;;
-					*)	# error
-						return 1
-						;;
-				esac
-
-				if [ "$net_length" -eq 32 ]; then
-					/sbin/route add -host "${net_address}" gw "${gateway}"
-				else
-					/sbin/route add -net "${net_address}/${net_length}" gw "${gateway}"
-				fi
-			done
-		fi
-	fi
-fi
diff --git a/debian/rfc3442-classless-routes.kfreebsd b/debian/rfc3442-classless-routes.kfreebsd
new file mode 100644
index 0000000..6e14946
--- /dev/null
+++ b/debian/rfc3442-classless-routes.kfreebsd
@@ -0,0 +1,59 @@
+# set classless routes based on the format specified in RFC3442
+# e.g.:
+#   new_rfc3442_classless_static_routes='24 192 168 10 192 168 1 1 8 10 10 17 66 41'
+# specifies the routes:
+#   192.168.10.0/24 via 192.168.1.1
+#   10.0.0.0/8 via 10.10.17.66.41
+
+RUN="yes"
+
+
+if [ "$RUN" = "yes" ]; then
+	if [ -n "$new_rfc3442_classless_static_routes" ]; then
+		if [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
+
+			set -- $new_rfc3442_classless_static_routes
+
+			while [ $# -gt 0 ]; do
+				net_length=$1
+
+				case $net_length in
+					32|31|30|29|28|27|26|25)
+						net_address="${2}.${3}.${4}.${5}"
+						gateway="${6}.${7}.${8}.${9}"
+						shift 9
+						;;
+					24|23|22|21|20|19|18|17)
+						net_address="${2}.${3}.${4}.0"
+						gateway="${5}.${6}.${7}.${8}"
+						shift 8
+						;;
+					16|15|14|13|12|11|10|9)
+						net_address="${2}.${3}.0.0"
+						gateway="${4}.${5}.${6}.${7}"
+						shift 7
+						;;
+					8|7|6|5|4|3|2|1)
+						net_address="${2}.0.0.0"
+						gateway="${3}.${4}.${5}.${6}"
+						shift 6
+						;;
+					0)	# default route
+						net_address="0.0.0.0"
+						gateway="${2}.${3}.${4}.${5}"
+						shift 5
+						;;
+					*)	# error
+						return 1
+						;;
+				esac
+
+				if [ "$net_length" -eq 32 ]; then
+					/sbin/route add -host "${net_address}" gw "${gateway}"
+				else
+					/sbin/route add -net "${net_address}/${net_length}" gw "${gateway}"
+				fi
+			done
+		fi
+	fi
+fi
diff --git a/debian/rfc3442-classless-routes.linux b/debian/rfc3442-classless-routes.linux
new file mode 100644
index 0000000..18ce0c3
--- /dev/null
+++ b/debian/rfc3442-classless-routes.linux
@@ -0,0 +1,57 @@
+# set classless routes based on the format specified in RFC3442
+# e.g.:
+#   new_rfc3442_classless_static_routes='24 192 168 10 192 168 1 1 8 10 10 17 66 41'
+# specifies the routes:
+#   192.168.10.0/24 via 192.168.1.1
+#   10.0.0.0/8 via 10.10.17.66.41
+
+RUN="yes"
+
+
+if [ "$RUN" = "yes" ]; then
+	if [ -n "$new_rfc3442_classless_static_routes" ]; then
+		if [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
+
+			set -- $new_rfc3442_classless_static_routes
+
+			while [ $# -gt 0 ]; do
+				net_length=$1
+
+				case $net_length in
+					32|31|30|29|28|27|26|25)
+						net_address="${2}.${3}.${4}.${5}"
+						gateway="${6}.${7}.${8}.${9}"
+						shift 9
+						;;
+					24|23|22|21|20|19|18|17)
+						net_address="${2}.${3}.${4}.0"
+						gateway="${5}.${6}.${7}.${8}"
+						shift 8
+						;;
+					16|15|14|13|12|11|10|9)
+						net_address="${2}.${3}.0.0"
+						gateway="${4}.${5}.${6}.${7}"
+						shift 7
+						;;
+					8|7|6|5|4|3|2|1)
+						net_address="${2}.0.0.0"
+						gateway="${3}.${4}.${5}.${6}"
+						shift 6
+						;;
+					0)	# default route
+						net_address="0.0.0.0"
+						gateway="${2}.${3}.${4}.${5}"
+						shift 5
+						;;
+					*)	# error
+						return 1
+						;;
+				esac
+
+				# set route (ip detects host routes automatically)
+				ip -4 route add "${net_address}/${net_length}" \
+					via "${gateway}" dev "${interface}" >/dev/null 2>&1
+			done
+		fi
+	fi
+fi
diff --git a/debian/rules b/debian/rules
index 71cbea9..847cbe9 100755
--- a/debian/rules
+++ b/debian/rules
@@ -134,11 +134,12 @@ install-stamp: build-stamp
 
 	cp debian/debug-enter debian/isc-dhcp-client/etc/dhcp/dhclient-enter-hooks.d/debug
 	cp debian/debug-exit debian/isc-dhcp-client/etc/dhcp/dhclient-exit-hooks.d/debug
-	cp debian/rfc3442-classless-routes debian/isc-dhcp-client/etc/dhcp/dhclient-exit-hooks.d
 
 	dh_install
 
 	cp debian/dhclient-script.$(DEB_HOST_ARCH_OS) `pwd`/debian/isc-dhcp-client/sbin/dhclient-script
+	cp debian/rfc3442-classless-routes.$(DEB_HOST_ARCH_OS) \
+		`pwd`/debian/isc-dhcp-client/etc/dhcp/dhclient-exit-hooks.d/rfc3442-classless-routes
 
 	# Install Linux specific documentation
 ifeq ($(DEB_HOST_ARCH_OS), linux)
-- 
1.7.2.3

-------------- next part --------------
>From a2427a87106e6789c7f510f1599eb2711698b1d4 Mon Sep 17 00:00:00 2001
From: Peter Marschall <peter at adpm.de>
Date: Sun, 9 Jan 2011 09:55:30 +0100
Subject: [PATCH 14/14] debug hooks: only use one common source

Stop duplication of debug-enter and debug-exit that only differ
in the path of the script shown.
Replace them with one common source, but keep them separate in the packages.

Signed-off-by: Peter Marschall <peter at adpm.de>
---
 debian/debug-enter |   37 -------------------------------------
 debian/debug-exit  |   37 -------------------------------------
 debian/debug-hook  |   38 ++++++++++++++++++++++++++++++++++++++
 debian/rules       |    4 ++--
 4 files changed, 40 insertions(+), 76 deletions(-)
 delete mode 100644 debian/debug-enter
 delete mode 100644 debian/debug-exit
 create mode 100644 debian/debug-hook

diff --git a/debian/debug-enter b/debian/debug-enter
deleted file mode 100644
index 2bdd5fd..0000000
--- a/debian/debug-enter
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# The purpose of this script is just to show the variables that are
-# available to all the scripts in this directory. All these scripts
-# are called from /etc/dhcp3/dhclient-script, which exports all the
-# variables shown before. If you want to debug a problem with your DHCP
-# setup you can enable this script and take a look at
-# /tmp/dhclient-script.debug.
-
-# To enable this script set the following variable to "yes"
-RUN="no"
-
-if [ "$RUN" = "yes" ]; then
-	echo `date`: entering dhclient-enter-hooks.d, dumping variables. \
-		>> /tmp/dhclient-script.debug
-
-	# loop over the 4 possible prefixes: (empty), cur_, new_, old_
-	for prefix in '' 'cur_' 'new_' 'old_'; do
-		# loop over the DHCP variables passed to dhclient-script
-		for basevar in reason interface medium alias_ip_address \
-			       ip_address host_name network_number subnet_mask \
-			       broadcast_address routers static_routes \
-			       rfc3442_classless_static_routes \
-			       domain_name domain_search domain_name_servers \
-			       netbios_name_servers netbios_scope \
-			       ntp_servers \
-			       ip6_address ip6_prefix ip6_prefixlen \
-			       dhcp6_domain_search dhcp6_name_servers ; do
-			var="${prefix}${basevar}"
-
-			if [ -n "${!var}" ]; then
-				echo "$var='${!var}'" >> /tmp/dhclient-script.debug
-			fi
-		done
-	done
-
-	echo '--------------------------' >> /tmp/dhclient-script.debug
-fi
diff --git a/debian/debug-exit b/debian/debug-exit
deleted file mode 100644
index e16d204..0000000
--- a/debian/debug-exit
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# The purpose of this script is just to show the variables that are
-# available to all the scripts in this directory. All these scripts
-# are called from /etc/dhcp3/dhclient-script, which exports all the
-# variables shown before. If you want to debug a problem with your DHCP
-# setup you can enable this script and take a look at
-# /tmp/dhclient-script.debug.
-
-# To enable this script set the following variable to "yes"
-RUN="no"
-
-if [ "$RUN" = "yes" ]; then
-	echo `date`: entering dhclient-exit-hooks.d, dumping variables. \
-		>> /tmp/dhclient-script.debug
-
-	# loop over the 4 possible prefixes: (empty), cur_, new_, old_
-	for prefix in '' 'cur_' 'new_' 'old_'; do
-		# loop over the DHCP variables passed to dhclient-script
-		for basevar in reason interface medium alias_ip_address \
-			       ip_address host_name network_number subnet_mask \
-			       broadcast_address routers static_routes \
-			       rfc3442_classless_static_routes \
-			       domain_name domain_search domain_name_servers \
-			       netbios_name_servers netbios_scope \
-			       ntp_servers \
-			       ip6_address ip6_prefix ip6_prefixlen \
-			       dhcp6_domain_search dhcp6_name_servers ; do
-			var="${prefix}${basevar}"
-
-			if [ -n "${!var}" ]; then
-				echo "$var='${!var}'" >> /tmp/dhclient-script.debug
-			fi
-		done
-	done
-
-	echo '--------------------------' >> /tmp/dhclient-script.debug
-fi
diff --git a/debian/debug-hook b/debian/debug-hook
new file mode 100644
index 0000000..efe9fc2
--- /dev/null
+++ b/debian/debug-hook
@@ -0,0 +1,38 @@
+#
+# The purpose of this script is just to show the variables that are
+# available to all the scripts in this directory. All these scripts
+# are called from /etc/dhcp3/dhclient-script, which exports all the
+# variables shown before. If you want to debug a problem with your DHCP
+# setup you can enable this script and take a look at
+# /tmp/dhclient-script.debug.
+
+# To enable this script set the following variable to "yes"
+RUN="no"
+
+if [ "$RUN" = "yes" ]; then
+	echo $(date): entering ${0%/*}, dumping variables. \
+		>> /tmp/dhclient-script.debug
+
+	# loop over the 4 possible prefixes: (empty), cur_, new_, old_
+	for prefix in '' 'cur_' 'new_' 'old_'; do
+		# loop over the DHCP variables passed to dhclient-script
+		for basevar in reason interface medium alias_ip_address \
+			       ip_address host_name network_number subnet_mask \
+			       broadcast_address routers static_routes \
+			       rfc3442_classless_static_routes \
+			       domain_name domain_search domain_name_servers \
+			       netbios_name_servers netbios_scope \
+			       ntp_servers \
+			       ip6_address ip6_prefix ip6_prefixlen \
+			       dhcp6_domain_search dhcp6_name_servers ; do
+			var="${prefix}${basevar}"
+
+			# show only variables with values set
+			if [ -n "${!var}" ]; then
+				echo "$var='${!var}'" >> /tmp/dhclient-script.debug
+			fi
+		done
+	done
+
+	echo '--------------------------' >> /tmp/dhclient-script.debug
+fi
diff --git a/debian/rules b/debian/rules
index 847cbe9..d9684df 100755
--- a/debian/rules
+++ b/debian/rules
@@ -132,8 +132,8 @@ install-stamp: build-stamp
 			$(DESTDIR)/usr/share/man/ja/man8; \
 	done
 
-	cp debian/debug-enter debian/isc-dhcp-client/etc/dhcp/dhclient-enter-hooks.d/debug
-	cp debian/debug-exit debian/isc-dhcp-client/etc/dhcp/dhclient-exit-hooks.d/debug
+	cp debian/debug-hook debian/isc-dhcp-client/etc/dhcp/dhclient-enter-hooks.d/debug
+	cp debian/debug-hook debian/isc-dhcp-client/etc/dhcp/dhclient-exit-hooks.d/debug
 
 	dh_install
 
-- 
1.7.2.3



More information about the pkg-dhcp-devel mailing list