1#!/bin/mksh
2# $MirOS: src/sbin/dhclient/dhclient-script,v 1.10 2008/12/27 00:27:01 tg Exp $
3# $OpenBSD: dhclient-script,v 1.10 2006/06/03 19:30:06 mpf Exp $
4#
5# Copyright (c) 2004, 2005, 2008
6#	Thorsten “mirabilos” Glaser <tg@mirbsd.org>
7# Copyright (c) 2003 Kenneth R Westerback <krw@openbsd.org>
8#
9# Permission to use, copy, modify, and distribute this software for any
10# purpose with or without fee is hereby granted, provided that the above
11# copyright notice and this permission notice appear in all copies.
12#
13# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
21#
22# Helper functions that implement common actions.
23#
24
25delete_old_address() {
26	if [ -n "$old_ip_address" ]; then
27		ifconfig $interface inet $old_ip_address delete $medium
28		route -n delete -inet "$old_ip_address" 127.0.0.1 >/dev/null 2>&1
29	fi
30}
31
32add_new_address() {
33	ifconfig $interface \
34		inet $new_ip_address \
35		netmask $new_subnet_mask \
36		broadcast $new_broadcast_address \
37		$medium
38
39	# XXX Original TIMEOUT code did not do this unless $new_routers was set?
40	route -n add -inet $new_ip_address 127.0.0.1 >/dev/null 2>&1
41}
42
43delete_old_alias() {
44	if [ -n "$alias_ip_address" ]; then
45		ifconfig $interface inet $alias_ip_address delete > /dev/null 2>&1
46		route -n delete -inet $alias_ip_address 127.0.0.1 > /dev/null 2>&1
47	fi
48}
49
50add_new_alias() {
51	if [ -n "$alias_ip_address" ]; then
52		ifconfig $interface inet $alias_ip_address alias netmask \
53		    $alias_subnet_mask
54		route -n add -inet $alias_ip_address 127.0.0.1
55	fi
56}
57
58delete_old_routes() {
59	# Delete existing default route. We only allow one, so no need to
60	# process $old_routers list.
61	route -n delete -inet default >/dev/null 2>&1
62
63	if [ -n "$old_static_routes" ]; then
64		set $old_static_routes
65		while [ $# -gt 1 ]; do
66			route -n delete -inet "$1" "$2"
67			shift; shift
68		done
69	fi
70
71	arp -dan
72}
73
74add_new_routes() {
75	route delete default >/dev/null 2>&1
76	for router in $new_routers; do
77		if [ "$new_ip_address" = "$router" ]; then
78			route -n add -inet default -iface $router >/dev/null 2>&1
79		else
80			route -n add -inet default $router >/dev/null 2>&1
81		fi
82		# 2nd and subsequent default routers error out, so explicitly
83		# stop processing the list after the first one.
84		break
85	done
86
87	if [ -n "$new_static_routes" ]; then
88		set $new_static_routes
89		while [ $# -gt 1 ]; do
90			route -n add -inet $1 $2
91			shift; shift
92		done
93	fi
94}
95
96add_new_resolv_conf() {
97	# XXX Old code did not create/update resolv.conf unless both
98	# $new_domain_name and $new_domain_name_servers were provided.  PR
99	# #3135 reported some ISPs only provide $new_domain_name_servers and
100	# thus broke the script. This code creates the resolv.conf if either
101	# are provided.
102
103	rm -f /etc/resolv.conf.std
104
105	if [ -n "$new_domain_name" ]; then
106		echo "search $new_domain_name" >>/etc/resolv.conf.std
107	fi
108
109	if [ -n "$new_domain_name_servers" ]; then
110		for nameserver in $new_domain_name_servers; do
111			echo "nameserver $nameserver" >>/etc/resolv.conf.std
112		done
113	fi
114
115	if [ -f /etc/resolv.conf.std ]; then
116		if [ -f /etc/resolv.conf.tail ]; then
117			cat /etc/resolv.conf.tail >>/etc/resolv.conf.std
118		fi
119
120		# Some people set up their own local cacheing DNS, even
121		# if they use DHCP. So fix them up.
122		if [ -f /etc/resolv.conf.lock ]; then
123			rm -f /etc/resolv.conf.save
124			return 0
125		fi
126
127		# In case (e.g. during OpenBSD installs) /etc/resolv.conf
128		# is a symbolic link, take care to preserve the link and write
129		# the new data in the correct location.
130
131		if [ -f /etc/resolv.conf ]; then
132			cat /etc/resolv.conf >/etc/resolv.conf.save
133		fi
134		cat /etc/resolv.conf.std >/etc/resolv.conf
135		rm -f /etc/resolv.conf.std
136
137		# Try to ensure correct ownership and permissions.
138		chown -RL root:wheel /etc/resolv.conf
139		chmod -RL 644 /etc/resolv.conf
140
141		return 0
142	fi
143
144	return 1
145}
146
147#
148# Start of active code.
149#
150
151if [ -n "$new_network_number" ]; then
152	echo "New Network Number: $new_network_number"
153fi
154
155if [ -n "$new_broadcast_address" ]; then
156	echo "New Broadcast Address: $new_broadcast_address"
157fi
158
159case $reason in
160MEDIUM)
161	ifconfig $interface $medium
162	sleep 1
163	;;
164
165PREINIT)
166	delete_old_alias
167	ifconfig $interface up
168	;;
169
170ARPCHECK|ARPSEND)
171	;;
172
173BOUND|RENEW|REBIND|REBOOT)
174	if [ -n "$old_ip_address" ]; then
175		if [ "$old_ip_address" != "$alias_ip_address" ]; then
176			delete_old_alias
177		fi
178		if [ "$old_ip_address" != "$new_ip_address" ]; then
179			delete_old_address
180			delete_old_routes
181		fi
182	fi
183	if [ "$reason" = BOUND ] || \
184	   [ "$reason" = REBOOT ] || \
185	   [ -z "$old_ip_address" ] || \
186	   [ "$old_ip_address" != "$new_ip_address" ]; then
187		add_new_address
188		add_new_routes
189	fi
190	if [ "$new_ip_address" != "$alias_ip_address" ]; then
191		add_new_alias
192	fi
193	add_new_resolv_conf
194	[[ -s /etc/functions ]] && (. /etc/functions; _getrnd dhcp http &)
195	;;
196
197EXPIRE|FAIL)
198	delete_old_alias
199	if [ -n "$old_ip_address" ]; then
200		delete_old_address
201		delete_old_routes
202	fi
203	# XXX Why add alias we just deleted above?
204	add_new_alias
205	if [ -f /etc/resolv.conf.save ]; then
206		[ -f /etc/resolv.conf.lock ] || \
207			cat /etc/resolv.conf.save >/etc/resolv.conf
208		rm -f /etc/resolv.conf.{std,save}
209	fi
210	;;
211
212TIMEOUT)
213	delete_old_alias
214	add_new_address
215	sleep 1
216	if [ -n "$new_routers" ]; then
217		set "$new_routers"
218		if ping -q -c 1 -w 1 "$1"; then
219			if [ "$new_ip_address" != "$alias_ip_address" ]; then
220				add_new_alias
221			fi
222			add_new_routes
223			if add_new_resolv_conf; then
224				exit 0
225			fi
226		fi
227	fi
228	ifconfig $interface inet $new_ip_address delete $medium
229	# XXX Why not a delete_old_address as before all other invocations of
230	#     delete_old_routes?
231	delete_old_routes
232	exit 1
233	;;
234esac
235
236exit 0
237