--- dhcp-3.1.0a3/client/scripts/linux.orig 2006-07-22 04:24:16.000000000 +0200 +++ dhcp-3.1.0a3/client/scripts/linux 2007-04-16 17:25:06.000000000 +0200 @@ -1,208 +1,227 @@ -#!/bin/bash +#!/bin/sh # 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. # Notes: # 0. 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. +# 1. This script was modified to work with iproute2 -# 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. +calc_prefix() +{ + local old_IFS=$IFS + IFS='.' + local netmask=$(echo $1) + IFS=$old_IFS + + local ret=0 + local endp=0 + for n in $netmask ; do + for i in 128 64 32 16 8 4 2 1 ; do + if [ $(($n & $i)) -ne 0 ]; then + if [ $endp -eq 0 ]; then + ret=$(($ret + 1)) + else + echo "32" + return + fi + else + endp=1 + fi + done + done + echo $ret +} make_resolv_conf() { - if [ x"$new_domain_name_servers" != x ]; then - cat /dev/null > /etc/resolv.conf.dhclient - chmod 644 /etc/resolv.conf.dhclient - if [ x"$new_domain_search" != x ]; then - echo search $new_domain_search >> /etc/resolv.conf.dhclient - elif [ x"$new_domain_name" != x ]; then - # Note that the DHCP 'Domain Name Option' is really just a domain - # name, and that this practice of using the domain name option as - # a search path is both nonstandard and deprecated. - echo search $new_domain_name >> /etc/resolv.conf.dhclient - fi - for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf.dhclient - done - - mv /etc/resolv.conf.dhclient /etc/resolv.conf - fi + if [ -n "$new_domain_name_servers" ]; then + :> /etc/resolv.conf.dhclient + chmod 644 /etc/resolv.conf.dhclient + if [ -n "$new_domain_search" ]; then + echo search $new_domain_search >> /etc/resolv.conf.dhclient + elif [ -n "$new_domain_name" ]; then + # Note that the DHCP 'Domain Name Option' is really just a domain + # name, and that this practice of using the domain name option as + # a search path is both nonstandard and deprecated. + echo search $new_domain_name >> /etc/resolv.conf.dhclient + fi + for nameserver in $new_domain_name_servers; do + echo nameserver $nameserver >>/etc/resolv.conf.dhclient + done + mv /etc/resolv.conf.dhclient /etc/resolv.conf + fi } -# Must be used on exit. Invokes the local dhcp client exit hooks, if any. +# Must be used on exit. +# Invokes the local dhcp client exit hooks, if any. exit_with_hooks() { - exit_status=$1 - if [ -f /etc/dhclient-exit-hooks ]; then - . /etc/dhclient-exit-hooks - fi -# probably should do something with exit status of the local script - exit $exit_status + exit_status=$1 + if [ -f /etc/dhclient-exit-hooks ]; then + . /etc/dhclient-exit-hooks + fi + # probably should do something with exit status of the local script + exit $exit_status } # Invoke the local dhcp client enter hooks, if they exist. if [ -f /etc/dhclient-enter-hooks ]; then - exit_status=0 - . /etc/dhclient-enter-hooks - # allow the local script to abort processing of this state - # local script must set exit_status variable to nonzero. - if [ $exit_status -ne 0 ]; then - exit $exit_status - 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/'` - -if [ x$new_broadcast_address != x ]; then - new_broadcast_arg="broadcast $new_broadcast_address" -fi -if [ x$old_broadcast_address != x ]; then - old_broadcast_arg="broadcast $old_broadcast_address" -fi -if [ x$new_subnet_mask != x ]; then - new_subnet_arg="netmask $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" -fi - -if [ x$reason = xMEDIUM ]; then - # Linux doesn't do mediums (ok, ok, media). - exit_with_hooks 0 -fi - -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 - fi - - # We need to give the kernel some time to get the interface up. - sleep 1 - - exit_with_hooks 0 -fi - -if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then - exit_with_hooks 0 -fi - -if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ - [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then - current_hostname=`hostname` - if [ x$current_hostname = x ] || \ - [ x$current_hostname = x$old_host_name ]; then - if [ x$current_hostname = x ] || \ - [ x$new_host_name != x$old_host_name ]; then - hostname $new_host_name - 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 - - 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 - for router in $new_routers; do - route add default gw $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 - 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 - set $new_routers - ############## what is -w in ping? - 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 - exit_with_hooks 1 -fi + exit_status=0 + . /etc/dhclient-enter-hooks + # allow the local script to abort processing of this state + # local script must set exit_status variable to nonzero. + if [ $exit_status -ne 0 ]; then + exit $exit_status + fi +fi + +if [ -n "$new_broadcast_address" ]; then + new_broadcast_arg="broadcast $new_broadcast_address" +fi +if [ -n "$old_broadcast_address" ]; then + old_broadcast_arg="broadcast $old_broadcast_address" +fi +if [ -n "$new_subnet_mask" ]; then + new_subnet_arg="$(calc_prefix $new_subnet_mask)" +fi +if [ -n "$old_subnet_mask" ]; then + old_subnet_arg="$(calc_prefix $old_subnet_mask)" +fi +if [ -n "$alias_subnet_mask" ]; then + alias_subnet_arg="$(calc_prefix $alias_subnet_mask)" +fi +[ -z "new_subnet_arg" ] && $new_subnet_arg="32" +[ -z "old_subnet_arg" ] && $old_subnet_arg="32" +[ -z "alias_subnet_arg" ] && $alias_subnet_arg="32" + +case "$reason" in + MEDIUM) + # Linux doesn't do mediums (ok, ok, media). + ;; + + PREINIT) + if [ -n "$alias_ip_address" ]; then + /sbin/ip addr del $alias_ip_address/$alias_subnet_arg dev $interface + fi + /sbin/ip link set $interface up + + # We need to give the kernel some time to get the interface up. + sleep 1 + ;; + + BOUND|RENEW|REBIND|REBOOT) + current_hostname=`hostname` + if [ -z "$current_hostname" ]; then + hostname $new_host_name + elif [ "$current_hostname" = "$old_host_name" -a \ + "$new_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 + # Possible new alias. Remove old alias. + /sbin/ip addr del $alias_ip_address/$alias_subnet_arg dev $interface + fi + if [ -n "$old_ip_address" -a "$old_ip_address" != "$new_ip_address" ]; then + # IP address changed. + /sbin/ip addr del $old_ip_address/$old_subnet_arg dev $interface + for router in $old_routers; do + /sbin/ip route del default via $router + done + if [ -n "$old_static_routes" ]; then + set -- $old_static_routes + while [ $# -gt 1 ]; do + /sbin/ip route del $1 via $2 + shift; shift + done + fi + fi + if [ -z "$old_ip_address" -o "$old_ip_address" != "$new_ip_address" -o \ + "$reason" = "BOUND" -o "$reason" = "REBOOT" ]; then + /sbin/ip addr add $new_ip_address/$new_subnet_arg $new_broadcast_arg dev $interface + # Add a network route to the computed network address. + for router in $new_routers; do + /sbin/ip route add default via $router + done + if [ -n "$new_static_routes" ]; then + set -- $new_static_routes + while [ $# -gt 1 ]; do + /sbin/ip route add $1 via $2 + shift; shift + done + fi + fi + if [ -n "$alias_ip_address" -a "$new_ip_address" != "$alias_ip_address" ]; then + /sbin/ip addr add $alias_ip_address/$alias_subnet_arg dev $interface + fi + make_resolv_conf + ;; + + EXPIRE|FAIL|RELEASE|STOP) + if [ -n "$alias_ip_address" ]; then + # Turn off alias interface. + /sbin/ip addr del $alias_ip_address/$alias_subnet_arg dev $interface + fi + if [ -n "$old_ip_address" ]; then + /sbin/ip addr del $old_ip_address/$old_subnet_arg dev $interface + for router in $old_routers; do + /sbin/ip route del default via $router + done + if [ -n "$old_static_routes" ]; then + set -- $old_static_routes + while [ $# -gt 1 ]; do + /sbin/ip route del $1 via $2 + shift; shift + done + fi + fi + if [ -n "$alias_ip_address" ]; then + /sbin/ip addr add $alias_ip_address/$alias_subnet_arg dev $interface + fi + ;; + + TIMEOUT) + if [ -n "$alias_ip_address" ]; then + /sbin/ip addr del $alias_ip_address/$alias_subnet_arg dev $interface + fi + /sbin/ip addr add $new_ip_address/$new_subnet_arg $new_broadcast_arg dev $interface + + set $new_routers + if ping -q -c 1 $1; then + if [ "$new_ip_address" != "$alias_ip_address" ] && \ + [ -n "$alias_ip_address" ]; then + /sbin/ip addr add $alias_ip_address/$alias_subnet_arg dev $interface + fi + for router in $new_routers; do + /sbin/ip route add default via $router + done + if [ -n "$new_static_routes" ]; then + set -- $new_static_routes + while [ $# -gt 1 ]; do + /sbin/ip route add $1 via $2 + shift; shift + done + fi + make_resolv_conf + exit_with_hooks 0 + fi + + /sbin/ip addr del $new_ip_address/$new_subnet_arg dev $interface + for router in $old_routers; do + /sbin/ip route del default via $router + done + if [ -n "$old_static_routes" ]; then + set -- $old_static_routes + while [ $# -gt 1 ]; do + /sbin/ip route del $1 via $2 + shift; shift + done + fi + exit_with_hooks 1 + ;; + *) + ;; +esac exit_with_hooks 0