#!/bin/sh
# dhclient-script for Linux. Dan Halbert, March, 1997.
# Updated for Linux 2.[12] by Brian J. Murrell, January 1999.

# Notes:

# 0. This script is based on the netbsd script supplied with dhcp-970306.

# 1. This script was modified to work with iproute2

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 [ -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.
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
}

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)"

	if [ $(($dhc_dbus & 31)) -eq 31 ]; then
		exit 0
	fi
fi

# 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

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
