]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - release/picobsd/floppy.tree/sbin/dhclient-script
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / release / picobsd / floppy.tree / sbin / dhclient-script
1 #!/bin/sh
2 #
3 # $OpenBSD: dhclient-script,v 1.6 2004/05/06 18:22:41 claudio Exp $
4 # $FreeBSD$
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
22 ARP=/usr/sbin/arp
23 HOSTNAME=/bin/hostname
24 IFCONFIG='/sbin/ifconfig -n'
25
26 LOCALHOST=127.0.0.1
27
28 if [ -x /usr/bin/logger ]; then
29         LOGGER="/usr/bin/logger -s -p user.notice -t dhclient"
30 else
31         LOGGER=echo
32 fi
33
34 #
35 # Helper functions that implement common actions.
36 #
37
38 check_hostname() {
39         current_hostname=`$HOSTNAME`
40         if [ -z "$current_hostname" ]; then
41                 $LOGGER "New Hostname ($interface): $new_host_name"
42                 $HOSTNAME $new_host_name
43         elif [ "$current_hostname" = "$old_host_name" -a \
44                "$new_host_name" != "$old_host_name" ]; then
45                 $LOGGER "New Hostname ($interface): $new_host_name"
46                 $HOSTNAME $new_host_name
47         fi
48 }
49
50 arp_flush() {
51         arp -an -i $interface | \
52                 sed -n -e 's/^.*(\(.*\)) at .*$/arp -d \1/p' | \
53                 sh >/dev/null 2>&1
54 }
55
56 delete_old_address() {
57         eval "$IFCONFIG $interface inet -alias $old_ip_address $medium"
58 }
59
60 add_new_address() {
61         eval "$IFCONFIG $interface \
62                 inet $new_ip_address \
63                 netmask $new_subnet_mask \
64                 broadcast $new_broadcast_address \
65                 $medium"
66
67         $LOGGER "New IP Address ($interface): $new_ip_address"
68         $LOGGER "New Subnet Mask ($interface): $new_subnet_mask"
69         $LOGGER "New Broadcast Address ($interface): $new_broadcast_address"
70         $LOGGER "New Routers ($interface): $new_routers"
71 }
72
73 delete_old_alias() {
74         if [ -n "$alias_ip_address" ]; then
75                 $IFCONFIG $interface inet -alias $alias_ip_address > /dev/null 2>&1
76                 #route delete $alias_ip_address $LOCALHOST > /dev/null 2>&1
77         fi
78 }
79
80 add_new_alias() {
81         if [ -n "$alias_ip_address" ]; then
82                 $IFCONFIG $interface inet alias $alias_ip_address netmask \
83                     $alias_subnet_mask
84                 #route add $alias_ip_address $LOCALHOST
85         fi
86 }
87
88 fill_classless_routes() {
89         set $1
90         while [ $# -ge 5 ]; do
91                 if [ $1 -eq 0 ]; then
92                         route="default"
93                 elif [ $1 -le 8 ]; then
94                         route="$2.0.0.0/$1"
95                         shift
96                 elif [ $1 -le 16 ]; then
97                         route="$2.$3.0.0/$1"
98                         shift; shift
99                 elif [ $1 -le 24 ]; then
100                         route="$2.$3.$4.0/$1"
101                         shift; shift; shift
102                 else
103                         route="$2.$3.$4.$5/$1"
104                         shift; shift; shift; shift
105                 fi
106                 shift
107                 router="$1.$2.$3.$4"
108                 classless_routes="$classless_routes $route $router"
109                 shift; shift; shift; shift
110         done
111 }
112
113 delete_old_routes() {
114         #route delete "$old_ip_address" $LOCALHOST >/dev/null 2>&1
115         if [ -n "$old_classless_routes" ]; then
116                 fill_classless_routes "$old_classless_routes"
117                 set $classless_routes
118                 while [ $# -gt 1 ]; do
119                         route delete "$1" "$2"
120                         shift; shift
121                 done
122                 return 0;
123         fi
124
125         # If we supported multiple default routes, we'd be removing each
126         # one here.  We don't so just delete the default route if it's
127         # through our interface.
128         if is_default_interface; then
129                 route delete default >/dev/null 2>&1
130         fi
131
132         if [ -n "$old_static_routes" ]; then
133                 set $old_static_routes
134                 while [ $# -gt 1 ]; do
135                         route delete "$1" "$2"
136                         shift; shift
137                 done
138         fi
139
140         arp_flush
141 }
142
143 add_new_routes() {
144         #route add $new_ip_address $LOCALHOST >/dev/null 2>&1
145
146         # RFC 3442: If the DHCP server returns both a Classless Static
147         # Routes option and a Router option, the DHCP client MUST ignore
148         # the Router option.
149         #
150         # DHCP clients that support this option (Classless Static Routes)
151         # MUST NOT install the routes specified in the Static Routes
152         # option (option code 33) if both a Static Routes option and the
153         # Classless Static Routes option are provided.
154
155         if [ -n "$new_classless_routes" ]; then
156                 fill_classless_routes "$new_classless_routes"
157                 $LOGGER "New Classless Static Routes ($interface): $classless_routes"
158                 set $classless_routes
159                 while [ $# -gt 1 ]; do
160                         if [ "0.0.0.0" = "$2" ]; then
161                                 route add "$1" -iface "$interface"
162                         else
163                                 route add "$1" "$2"
164                         fi
165                         shift; shift
166                 done
167                 return
168         fi
169
170         for router in $new_routers; do
171                 if is_default_interface; then
172
173                         if [ "$new_ip_address" = "$router" ]; then
174                                 route add default -iface $router >/dev/null 2>&1
175                         else
176                                 route add default $router >/dev/null 2>&1
177                         fi
178                 fi
179                 # 2nd and subsequent default routers error out, so explicitly
180                 # stop processing the list after the first one.
181                 break
182         done
183
184         if [ -n "$new_static_routes" ]; then
185                 $LOGGER "New Static Routes ($interface): $new_static_routes"
186                 set $new_static_routes
187                 while [ $# -gt 1 ]; do
188                         route add $1 $2
189                         shift; shift
190                 done
191         fi
192 }
193
194 add_new_resolv_conf() {
195         # XXX Old code did not create/update resolv.conf unless both
196         # $new_domain_name and $new_domain_name_servers were provided.  PR
197         # #3135 reported some ISP's only provide $new_domain_name_servers and
198         # thus broke the script. This code creates the resolv.conf if either
199         # are provided.
200
201         local tmpres=/var/run/resolv.conf.${interface}
202         rm -f $tmpres
203
204         if [ -n "$new_domain_name" ]; then
205                 echo "search $new_domain_name" >>$tmpres
206         fi
207
208         if [ -n "$new_domain_name_servers" ]; then
209                 for nameserver in $new_domain_name_servers; do
210                         echo "nameserver $nameserver" >>$tmpres
211                 done
212         fi
213
214         if [ -f $tmpres ]; then
215                 if [ -f /etc/resolv.conf.tail ]; then
216                         cat /etc/resolv.conf.tail >>$tmpres
217                 fi
218
219                 # When resolv.conf is not changed actually, we don't
220                 # need to update it.
221                 # If /usr is not mounted yet, we cannot use cmp, then
222                 # the following test fails.  In such case, we simply
223                 # ignore an error and do update resolv.conf.
224                 if cmp -s $tmpres /etc/resolv.conf; then
225                         rm -f $tmpres
226                         return 0
227                 fi 2>/dev/null
228
229                 # In case (e.g. during OpenBSD installs) /etc/resolv.conf
230                 # is a symbolic link, take care to preserve the link and write
231                 # the new data in the correct location.
232
233                 if [ -f /etc/resolv.conf ]; then
234                         cat /etc/resolv.conf > /etc/resolv.conf.save
235                 fi
236                 cat $tmpres > /etc/resolv.conf
237                 rm -f $tmpres
238
239                 # Try to ensure correct ownership and permissions.
240                 chown -RL root:wheel /etc/resolv.conf
241                 chmod -RL 644 /etc/resolv.conf
242
243                 return 0
244         fi
245
246         return 1
247 }
248
249 # Must be used on exit.   Invokes the local dhcp client exit hooks, if any.
250 exit_with_hooks() {
251         exit_status=$1
252         if [ -f /etc/dhclient-exit-hooks ]; then
253                 . /etc/dhclient-exit-hooks
254         fi
255         # probably should do something with exit status of the local script
256         exit $exit_status
257 }
258
259 # Get the interface with the current ipv4 default route on it using only
260 # commands that are available prior to /usr being mounted.
261 is_default_interface()
262 {
263         routeget="`route -n get -inet default`"
264         oldifs="$IFS"
265         IFS="
266 "
267         defif=
268         for line in $routeget ; do
269                 case $line in
270                 *interface:*)
271                         defif=${line##*: }
272                         ;;
273                 esac
274         done
275         IFS=${oldifs}
276
277         if [ -z "$defif" -o "$defif" = "$interface" ]; then
278                 return 0
279         else
280                 return 1
281         fi
282 }
283
284 #
285 # Start of active code.
286 #
287
288 # Invoke the local dhcp client enter hooks, if they exist.
289 if [ -f /etc/dhclient-enter-hooks ]; then
290         exit_status=0
291         . /etc/dhclient-enter-hooks
292         # allow the local script to abort processing of this state
293         # local script must set exit_status variable to nonzero.
294         if [ $exit_status -ne 0 ]; then
295                 exit $exit_status
296         fi
297 fi
298
299 case $reason in
300 MEDIUM)
301         eval "$IFCONFIG $interface $medium"
302         eval "$IFCONFIG $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
303         sleep 1
304         ;;
305
306 PREINIT)
307         delete_old_alias
308         $IFCONFIG $interface inet alias 0.0.0.0 netmask 0.0.0.0 broadcast 255.255.255.255 up
309         ;;
310
311 ARPCHECK|ARPSEND)
312         ;;
313
314 BOUND|RENEW|REBIND|REBOOT)
315         check_hostname
316         if [ -n "$old_ip_address" ]; then
317                 if [ "$old_ip_address" != "$alias_ip_address" ]; then
318                         delete_old_alias
319                 fi
320                 if [ "$old_ip_address" != "$new_ip_address" ]; then
321                         delete_old_address
322                         delete_old_routes
323                 fi
324         fi
325         if [ "$reason" = BOUND ] || \
326            [ "$reason" = REBOOT ] || \
327            [ -z "$old_ip_address" ] || \
328            [ "$old_ip_address" != "$new_ip_address" ]; then
329                 add_new_address
330                 add_new_routes
331         fi
332         if [ "$new_ip_address" != "$alias_ip_address" ]; then
333                 add_new_alias
334         fi
335         if is_default_interface; then
336                 add_new_resolv_conf
337         fi
338         ;;
339
340 EXPIRE|FAIL)
341         delete_old_alias
342         if [ -n "$old_ip_address" ]; then
343                 delete_old_address
344                 delete_old_routes
345         fi
346         if [ -x $ARP ]; then
347                 $ARP -d -a -i $interface
348         fi
349         # XXX Why add alias we just deleted above?
350         add_new_alias
351         if is_default_interface; then
352                 if [ -f /etc/resolv.conf.save ]; then
353                         cat /etc/resolv.conf.save > /etc/resolv.conf
354                 fi
355         fi
356         ;;
357
358 TIMEOUT)
359         delete_old_alias
360         add_new_address
361         sleep 1
362         if [ -n "$new_routers" ]; then
363                 $LOGGER "New Routers ($interface): $new_routers"
364                 set "$new_routers"
365                 if ping -q -c 1 -t 1 "$1"; then
366                         if [ "$new_ip_address" != "$alias_ip_address" ]; then
367                                 add_new_alias
368                         fi
369                         add_new_routes
370                         if ! is_default_interface; then
371                                 exit_with_hooks 0
372                         fi
373                         if add_new_resolv_conf; then
374                                 exit_with_hooks 0
375                         fi
376                 fi
377         fi
378         eval "$IFCONFIG $interface inet -alias $new_ip_address $medium"
379         delete_old_routes
380         exit_with_hooks 1
381         ;;
382 esac
383
384 exit_with_hooks 0