-#!/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.
+if [ -n "$dhc_dbus" -a -x /usr/bin/dbus-send ]; then
+ /usr/bin/dbus-send \
+ --system \
+ --dest=com.redhat.dhcp \
+ --type=method_call \
+ /com/redhat/dhcp/$interface \
+ com.redhat.dhcp.set \
+ 'string:'"$(unset PATH SHLVL _ PWD dhc_dbus ; env)"
-# 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.
+ if [ $(($dhc_dbus & 31)) -eq 31 ]; then
+ exit 0
+ fi
+fi
-if [ -n "${dhc_dbus}" ]; then
- if [ -x /usr/bin/dbus-send ]; then
- /usr/bin/dbus-send \
- --system \
- --dest=com.redhat.dhcp \
- --type=method_call \
- /com/redhat/dhcp/$interface \
- com.redhat.dhcp.set \
- 'string:'"`env | /bin/egrep -v '^(PATH|SHLVL|_|PWD|dhc_dbus)\='`";
+calc_prefix()
+{
+ local old_IFS=$IFS
+ IFS='.'
+ local netmask=$(echo $1)
+ IFS=$old_IFS
- if (( ( dhc_dbus & 31 ) == 31 )); then
- exit 0;
- fi;
- fi;
-fi;
+ 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
+ elif [ -n "${new_dhcp6_name_servers}" ] ; then
+ :> /etc/resolv.conf.dhclient6
+ chmod 644 /etc/resolv.conf.dhclient6
+
+ if [ "x${new_dhcp6_domain_search}" != x ] ; then
+ echo search ${new_dhcp6_domain_search} >> /etc/resolv.conf.dhclient6
+ fi
+ for nameserver in ${new_dhcp6_name_servers} ; do
+ echo nameserver ${nameserver} >> /etc/resolv.conf.dhclient6
+ done
+ mv /etc/resolv.conf.dhclient6 /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
+ 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/'`
+###
+### DHCPv4 Handlers
+###
-if [ x$new_broadcast_address != x ]; then
- new_broadcast_arg="broadcast $new_broadcast_address"
+if [ -n "$new_broadcast_address" ]; then
+ new_broadcast_arg="broadcast $new_broadcast_address"
fi
-if [ x$old_broadcast_address != x ]; then
- old_broadcast_arg="broadcast $old_broadcast_address"
+if [ -n "$old_broadcast_address" ]; then
+ old_broadcast_arg="broadcast $old_broadcast_address"
fi
-if [ x$new_subnet_mask != x ]; then
- new_subnet_arg="netmask $new_subnet_mask"
+if [ -n "$new_subnet_mask" ]; then
+ new_subnet_arg="$(calc_prefix $new_subnet_mask)"
fi
-if [ x$old_subnet_mask != x ]; then
- old_subnet_arg="netmask $old_subnet_mask"
+if [ -n "$old_subnet_mask" ]; then
+ old_subnet_arg="$(calc_prefix $old_subnet_mask)"
fi
-if [ x$alias_subnet_mask != x ]; then
- alias_subnet_arg="netmask $alias_subnet_mask"
+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"
-if [ x$reason = xMEDIUM ]; then
- # Linux doesn't do mediums (ok, ok, media).
- exit_with_hooks 0
-fi
+case "$reason" in
+ MEDIUM)
+ # Linux doesn't do mediums (ok, ok, media).
+ ;;
-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
+ 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
-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
+ # We need to give the kernel some time to get the interface up.
+ sleep 1
+ ;;
-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
+ 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 [ 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
+ 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
+ ;;
+
+ PREINIT6)
+ # Ensure interface is up.
+ /sbin/ip link set ${interface} up
+
+ # Remove any stale addresses from aborted clients.
+ /sbin/ip -f inet6 addr flush dev ${interface} scope global permanent
+
+ exit_with_hooks 0
+ ;;
+ BOUND6)
+ if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
+ exit_with_hooks 2;
+ fi
+
+ /sbin/ip -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \
+ dev ${interface} scope global
+
+ # Check for nameserver options.
+ make_resolv_conf
+
+ exit_with_hooks 0
+ ;;
+
+ RENEW6|REBIND6)
+ # Make sure nothing has moved around on us.
+
+ # Nameservers/domains/etc.
+ if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] ||
+ [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ] ; then
+ make_resolv_conf
+ fi
+
+ exit_with_hooks 0
+ ;;
+
+ DEPREF6)
+ if [ x${new_ip6_prefixlen} = x ] ; then
+ exit_with_hooks 2;
+ fi
+
+ # There doesn't appear to be a way to update an addr to indicate
+ # preference.
+ # /sbin/ip -f inet6 addr ??? ${new_ip6_address}/${new_ip6_prefixlen} \
+ # dev ${interface} scope global deprecated?
+
+ exit_with_hooks 0
+ ;;
+
+ EXPIRE6|RELEASE6|STOP6)
+ if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then
+ exit_with_hooks 2;
+ fi
+
+ /sbin/ip -f inet6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \
+ dev ${interface}
+
+ exit_with_hooks 0
+ ;;
+
+ *)
+ ;;
+esac
exit_with_hooks 0