Submitted By: DJ Lucas (dj at linuxfromscratch dot org)
Date: 2008-05-27
Initial Package Version: 3.0.2
Origin: Bruce Dubbs, Kevin Fleming, Jim Gifford, and DJ Lucas
Description: Modifies client script to use only iproute2
Upstream Status:  Submitted

diff -Naur dhcp-4.0.0-orig/client/scripts/linux dhcp-4.0.0/client/scripts/linux
--- dhcp-4.0.0-orig/client/scripts/linux	2007-06-06 17:57:32.000000000 -0500
+++ dhcp-4.0.0/client/scripts/linux	2008-05-26 23:59:24.000000000 -0500
@@ -1,26 +1,18 @@
 #!/bin/bash
 # dhclient-script for Linux. Dan Halbert, March, 1997.
 # Updated for Linux 2.[12] by Brian J. Murrell, January 1999.
-# No guarantees about this. I'm a novice at the details of Linux
-# networking.
+# iproute2 update for IPv4 addresses courtesy of 
+# Linux From Scratch (www.linuxfromscratch.org) May 2008.
 
 # Notes:
 
-# 0. This script is based on the netbsd script supplied with dhcp-970306.
+# This script is based on the netbsd script supplied with dhcp-970306.
 
-# 1. ifconfig down apparently deletes all relevant routes and flushes
-# the arp cache, so this doesn't need to be done explicitly.
-
-# 2. The alias address handling here has not been tested AT ALL.
-# I'm just going by the doc of modern Linux ip aliasing, which uses
-# notations like eth0:0, eth0:1, for each alias.
-
-# 3. I have to calculate the network address, and calculate the broadcast
-# address if it is not supplied. This might be much more easily done
-# by the dhclient C code, and passed on.
-
-# 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious
-# of the $1 in its args.
+# Updated to use ip for IPv4 addresses.  Older versions of iproute2 only
+# allow CIDR notation.  The cidr_convert() function and its helpers,
+# dec2binary() and mask_to_binary() were added to account for this in the
+# IPv4 parts. Contributions by Bruce Dubbs, Kevin Fleming, Jim Gifford,
+# and DJ Lucas.
 
 # 'ip' just looks too weird.  /sbin/ip looks less weird.
 ip=/sbin/ip
@@ -57,6 +49,27 @@
   fi
 }
 
+dec_to_bin() {
+    local n=$1
+    local ret=""
+    while [ $n != 0 ]; do
+        ret=$[$n%2]$ret
+        n=$[$n>>1]
+    done
+    echo $ret
+}
+
+mask_to_bin() {
+    echo `dec_to_bin $1``dec_to_bin $2``dec_to_bin $3``dec_to_bin $4`
+}
+
+cidr_convert() {
+    netmask=$1
+    local mask=`mask_to_bin ${netmask//./ }`
+    mask=${mask%%0*}
+    echo ${#mask}
+}
+
 # Must be used on exit.   Invokes the local dhcp client exit hooks, if any.
 exit_with_hooks() {
   exit_status=$1
@@ -78,11 +91,6 @@
   fi
 fi
 
-release=`uname -r`
-release=`expr $release : '\(.*\)\..*'`
-relminor=`echo $release |sed -e 's/[0-9]*\.\([0-9][0-9]*\)\(\..*\)*$/\1/'`
-relmajor=`echo $release |sed -e 's/\([0-9][0-9]*\)\..*$/\1/'`
-
 ###
 ### DHCPv4 Handlers
 ###
@@ -94,13 +102,10 @@
   old_broadcast_arg="broadcast $old_broadcast_address"
 fi
 if [ x$new_subnet_mask != x ]; then
-  new_subnet_arg="netmask $new_subnet_mask"
+  new_subnet_arg=`cidr_convert $new_subnet_mask`
 fi
 if [ x$old_subnet_mask != x ]; then
-  old_subnet_arg="netmask $old_subnet_mask"
-fi
-if [ x$alias_subnet_mask != x ]; then
-  alias_subnet_arg="netmask $alias_subnet_mask"
+  old_subnet_arg=`cidr_convert $old_subnet_mask`
 fi
 
 if [ x$reason = xMEDIUM ]; then
@@ -111,17 +116,10 @@
 if [ x$reason = xPREINIT ]; then
   if [ x$alias_ip_address != x ]; then
     # Bring down alias interface. Its routes will disappear too.
-    ifconfig $interface:0- inet 0
-  fi
-  if [ $relmajor -lt 2 ] || ( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] )
-   then
-    ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
-		broadcast 255.255.255.255 up
-    # Add route to make broadcast work. Do not omit netmask.
-    route add default dev $interface netmask 0.0.0.0
-  else
-    ifconfig $interface 0 up
+    ${ip} link set $interface down
+    ${ip} addr del $alias_ip_address  dev $interface
   fi
+  ${ip} link set $interface up
 
   # We need to give the kernel some time to get the interface up.
   sleep 1
@@ -144,82 +142,52 @@
     fi
   fi
     
-  if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
-		[ x$alias_ip_address != x$old_ip_address ]; then
-    # Possible new alias. Remove old alias.
-    ifconfig $interface:0- inet 0
-  fi
   if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then
-    # IP address changed. Bringing down the interface will delete all routes,
-    # and clear the ARP cache.
-    ifconfig $interface inet 0 down
+    # IP address changed. Bring down the interface, delete all routes, and
+    # clear the ARP cache.
+    ${ip} link set $interface down
+    ${ip} addr flush dev $interface
 
   fi
   if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
      [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
 
-    ifconfig $interface inet $new_ip_address $new_subnet_arg \
-							$new_broadcast_arg
-    # Add a network route to the computed network address.
-    if [ $relmajor -lt 2 ] || \
-		( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] ); then
-      route add -net $new_network_number $new_subnet_arg dev $interface
-    fi
+    ${ip} link set $interface up
+    ${ip} addr add $new_ip_address/$new_subnet_arg $new_broadcast_arg \
+        label $interface dev $interface
+
+# Add a network route to the computed network address.
     for router in $new_routers; do
-      route add default gw $router
+      ${ip} route add default via $router
     done
   fi
-  if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
-   then
-    ifconfig $interface:0- inet 0
-    ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
-    route add -host $alias_ip_address $interface:0
-  fi
   make_resolv_conf
   exit_with_hooks 0
 fi
 
 if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
    || [ x$reason = xSTOP ]; then
-  if [ x$alias_ip_address != x ]; then
-    # Turn off alias interface.
-    ifconfig $interface:0- inet 0
-  fi
   if [ x$old_ip_address != x ]; then
-    # Shut down interface, which will delete routes and clear arp cache.
-    ifconfig $interface inet 0 down
-  fi
-  if [ x$alias_ip_address != x ]; then
-    ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
-    route add -host $alias_ip_address $interface:0
+    # Shut down interface, delete routes, and clear arp cache.
+    ${ip} link set $interface down
+    ${ip} addr flush dev $interface
   fi
   exit_with_hooks 0
 fi
 
 if [ x$reason = xTIMEOUT ]; then
-  if [ x$alias_ip_address != x ]; then
-    ifconfig $interface:0- inet 0
-  fi
-  ifconfig $interface inet $new_ip_address $new_subnet_arg \
-					$new_broadcast_arg
+  ${ip} link set $interface up
+  ${ip} addr set $new_ip_address/$new_subnet_arg $new_broadcast_arg \
+      label $interface dev $interface
   set $new_routers
-  if ping -q -c 1 $1; then
-    if [ x$new_ip_address != x$alias_ip_address ] && \
-			[ x$alias_ip_address != x ]; then
-      ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
-      route add -host $alias_ip_address dev $interface:0
-    fi
-    if [ $relmajor -lt 2 ] || \
-		( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] ); then
-      route add -net $new_network_number
-    fi
-    for router in $new_routers; do
-      route add default gw $router
-    done
-    make_resolv_conf
-    exit_with_hooks 0
-  fi
-  ifconfig $interface inet 0 down
+  for router in $new_routers; do
+    ${ip} route add default via $router
+  done
+  
+  make_resolv_conf
+  exit_with_hooks 0
+  ${ip} link set $interface down
+  ${ip} addr flush dev $interface
   exit_with_hooks 1
 fi
 
