dhclient-script revision 154760
1#!/bin/sh
2#
3# $OpenBSD: dhclient-script,v 1.6 2004/05/06 18:22:41 claudio Exp $
4# $FreeBSD: head/sbin/dhclient/dhclient-script 154760 2006-01-24 06:11:55Z brooks $
5#
6# Copyright (c) 2003 Kenneth R Westerback <krw@openbsd.org>
7#
8# Permission to use, copy, modify, and distribute this software for any
9# purpose with or without fee is hereby granted, provided that the above
10# copyright notice and this permission notice appear in all copies.
11#
12# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19#
20#
21
22ARP=/usr/sbin/arp
23AWK=/usr/bin/awk
24HOSTNAME=/bin/hostname
25NETSTAT=/usr/bin/netstat
26
27LOCALHOST=127.0.0.1
28
29if [ -x /usr/bin/logger ]; then
30	LOGGER="/usr/bin/logger -s -p user.notice -t dhclient"
31else
32	LOGGER=echo
33fi
34
35#
36# Helper functions that implement common actions.
37#
38
39check_hostname() {
40	current_hostname=`$HOSTNAME`
41	if [ -z "$current_hostname" ]; then
42		$LOGGER "New Hostname ($interface): $new_host_name"
43		$HOSTNAME $new_host_name
44	elif [ "$current_hostname" = "$old_host_name" -a \
45	       "$new_host_name" != "$old_host_name" ]; then
46		$LOGGER "New Hostname ($interface): $new_host_name"
47		$HOSTNAME $new_host_name
48	fi
49}
50
51arp_flush() {
52	arp -an -i $interface | \
53		sed -n -e 's/^.*(\(.*\)) at .*$/arp -d \1/p' | \
54		sh >/dev/null 2>&1
55}
56
57delete_old_address() {
58	eval "ifconfig $interface inet -alias $old_ip_address $medium"
59}
60
61add_new_address() {
62	eval "ifconfig $interface \
63		inet $new_ip_address \
64		netmask $new_subnet_mask \
65		broadcast $new_broadcast_address \
66		$medium"
67
68	$LOGGER "New IP Address ($interface): $new_ip_address"
69	$LOGGER "New Subnet Mask ($interface): $new_subnet_mask"
70	$LOGGER "New Broadcast Address ($interface): $new_broadcast_address"
71	$LOGGER "New Routers ($interface): $new_routers"
72}
73
74delete_old_alias() {
75	if [ -n "$alias_ip_address" ]; then
76		ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
77		#route delete $alias_ip_address $LOCALHOST > /dev/null 2>&1
78	fi
79}
80
81add_new_alias() {
82	if [ -n "$alias_ip_address" ]; then
83		ifconfig $interface inet alias $alias_ip_address netmask \
84		    $alias_subnet_mask
85		#route add $alias_ip_address $LOCALHOST
86	fi
87}
88
89delete_old_routes() {
90	#route delete "$old_ip_address" $LOCALHOST >/dev/null 2>&1
91	for router in $old_routers; do
92		if [ $if_defaultroute = x -o $if_defaultroute = $interface ]; then
93			route delete default $route >/dev/null 2>&1
94		fi
95	done
96
97	if [ -n "$old_static_routes" ]; then
98		set $old_static_routes
99		while [ $# -gt 1 ]; do
100			route delete "$1" "$2"
101			shift; shift
102		done
103	fi
104
105	arp_flush
106}
107
108add_new_routes() {
109	#route add $new_ip_address $LOCALHOST >/dev/null 2>&1
110	for router in $new_routers; do
111		if [ "$new_ip_address" = "$router" ]; then
112			route add default -iface $router >/dev/null 2>&1
113		else
114			route add default $router >/dev/null 2>&1
115		fi
116		# 2nd and subsequent default routers error out, so explicitly
117		# stop processing the list after the first one.
118		break
119	done
120
121	if [ -n "$new_static_routes" ]; then
122		$LOGGER "New Static Routes ($interface): $new_static_routes"
123		set $new_static_routes
124		while [ $# -gt 1 ]; do
125			route add $1 $2
126			shift; shift
127		done
128	fi
129}
130
131add_new_resolv_conf() {
132	# XXX Old code did not create/update resolv.conf unless both
133	# $new_domain_name and $new_domain_name_servers were provided.  PR
134	# #3135 reported some ISP's only provide $new_domain_name_servers and
135	# thus broke the script. This code creates the resolv.conf if either
136	# are provided.
137
138	local tmpres=${TMPDIR:-/tmp}/resolv.conf.std
139	rm -f $tmpres
140
141	if [ -n "$new_domain_name" ]; then
142		echo "search $new_domain_name" >>$tmpres
143	fi
144
145	if [ -n "$new_domain_name_servers" ]; then
146		for nameserver in $new_domain_name_servers; do
147			echo "nameserver $nameserver" >>$tmpres
148		done
149	fi
150
151	if [ -f $tmpres ]; then
152		if [ -f /etc/resolv.conf.tail ]; then
153			cat /etc/resolv.conf.tail >>$tmpres
154		fi
155
156		# When resolv.conf is not changed actually, we don't
157		# need to update it.
158		# If /usr is not mounted yet, we cannot use cmp, then
159		# the following test fails.  In such case, we simply
160		# ignore an error and do update resolv.conf.
161		if cmp -s $tmpres /etc/resolv.conf; then
162			rm -f $tmpres
163			return 0
164		fi 2>/dev/null
165
166		# In case (e.g. during OpenBSD installs) /etc/resolv.conf
167		# is a symbolic link, take care to preserve the link and write
168		# the new data in the correct location.
169
170		if [ -f /etc/resolv.conf ]; then
171			cat /etc/resolv.conf > /etc/resolv.conf.save
172		fi
173		cat $tmpres > /etc/resolv.conf
174		rm -f $tmpres
175
176		# Try to ensure correct ownership and permissions.
177		chown -RL root:wheel /etc/resolv.conf
178		chmod -RL 644 /etc/resolv.conf
179
180		return 0
181	fi
182
183	return 1
184}
185
186# Must be used on exit.   Invokes the local dhcp client exit hooks, if any.
187exit_with_hooks() {
188	exit_status=$1
189	if [ -f /etc/dhclient-exit-hooks ]; then
190		. /etc/dhclient-exit-hooks
191	fi
192	# probably should do something with exit status of the local script
193	exit $exit_status
194}
195
196#
197# Start of active code.
198#
199
200# Invoke the local dhcp client enter hooks, if they exist.
201if [ -f /etc/dhclient-enter-hooks ]; then
202	exit_status=0
203	. /etc/dhclient-enter-hooks
204	# allow the local script to abort processing of this state
205	# local script must set exit_status variable to nonzero.
206	if [ $exit_status -ne 0 ]; then
207		exit $exit_status
208	fi
209fi
210
211if [ -x $NETSTAT ]; then
212	if_defaultroute=`$NETSTAT -rnf inet | $AWK '{if ($1=="default") printf $6}'`
213else
214	if_defaultroute="x"
215fi
216
217case $reason in
218MEDIUM)
219	eval "ifconfig $interface $medium"
220	eval "ifconfig $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
221	sleep 1
222	;;
223
224PREINIT)
225	delete_old_alias
226	ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 broadcast 255.255.255.255 up
227	;;
228
229ARPCHECK|ARPSEND)
230	;;
231
232BOUND|RENEW|REBIND|REBOOT)
233	check_hostname
234	if [ -n "$old_ip_address" ]; then
235		if [ "$old_ip_address" != "$alias_ip_address" ]; then
236			delete_old_alias
237		fi
238		if [ "$old_ip_address" != "$new_ip_address" ]; then
239			delete_old_address
240			delete_old_routes
241		fi
242	fi
243	if [ "$reason" = BOUND ] || \
244	   [ "$reason" = REBOOT ] || \
245	   [ -z "$old_ip_address" ] || \
246	   [ "$old_ip_address" != "$new_ip_address" ]; then
247		add_new_address
248		add_new_routes
249	fi
250	if [ "$new_ip_address" != "$alias_ip_address" ]; then
251		add_new_alias
252	fi
253	add_new_resolv_conf
254	;;
255
256EXPIRE|FAIL)
257	delete_old_alias
258	if [ -n "$old_ip_address" ]; then
259		delete_old_address
260		delete_old_routes
261	fi
262	if [ -x $ARP ]; then
263		$ARP -d -a -i $interface
264	fi
265	# XXX Why add alias we just deleted above?
266	add_new_alias
267	if [ -f /etc/resolv.conf.save ]; then
268		cat /etc/resolv.conf.save > /etc/resolv.conf
269	fi
270	;;
271
272TIMEOUT)
273	delete_old_alias
274	add_new_address
275	sleep 1
276	if [ -n "$new_routers" ]; then
277		$LOGGER "New Routers ($interface): $new_routers"
278		set "$new_routers"
279		if ping -q -c 1 -t 1 "$1"; then
280			if [ "$new_ip_address" != "$alias_ip_address" ]; then
281				add_new_alias
282			fi
283			add_new_routes
284			if add_new_resolv_conf; then
285				exit_with_hooks 0
286			fi
287		fi
288	fi
289	eval "ifconfig $interface inet -alias $new_ip_address $medium"
290	delete_old_routes
291	exit_with_hooks 1
292	;;
293esac
294
295exit_with_hooks 0
296