Initial import from FreeBSD RELENG_4:
[games.git] / sbin / dhclient / dhclient-script.sh
1 #!/bin/sh
2
3 #############################################################################
4 #
5 # Copyright (c) 1999, MindStep Corporation
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
10 # are met:
11 # 1. Redistributions of source code must retain the above copyright
12 #    notice, this list of conditions and the following disclaimer.
13 # 2. Redistributions in binary form must reproduce the above copyright
14 #    notice, this list of conditions and the following disclaimer in the
15 #    documentation and/or other materials provided with the distribution.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 # SUCH DAMAGE.
28 #
29 #
30 #############################################################################
31 #
32 # This script was written by Patrick Bihan-Faou, patrick@mindstep.com,
33 # Please contact us for bug reports, etc.
34 #
35 #############################################################################
36 # $MindStep_Id: dhclient-script.sh,v 1.8 1999/12/07 22:11:08 patrick Exp $
37 # $MindStep_Tag: CONTRIB_19991207 $
38 # $FreeBSD: src/sbin/dhclient/dhclient-script.sh,v 1.2.2.1 2002/04/11 10:21:20 murray Exp $
39 #############################################################################
40
41
42 #############################################################################
43 # hook functions prototypes
44 #
45 # The "pre_state_XXX_hook" functions are called before the main
46 # work is done for the state XXX
47 #
48 # The "post_state_XXX_hook" functions are called after the main
49 # work is done for the state XXX
50 #
51 # These functions are meant to be overridden by the user's
52 # dhclient-enter-hooks file
53 #############################################################################
54
55 pre_state_MEDIUM_hook () { }
56 pre_state_PREINIT_hook () { }
57 pre_state_ARPCHECK_hook () { }
58 pre_state_ARPSEND_hook () { }
59 pre_state_RENEW_hook () { }
60 pre_state_REBIND_hook () { }
61 pre_state_BOUND_hook () { }
62 pre_state_REBOOT_hook () { }
63 pre_state_EXPIRE_hook () { }
64 pre_state_FAIL_hook () { }
65 pre_state_TIMEOUT_hook () { }
66 post_state_MEDIUM_hook () { }
67 post_state_PREINIT_hook () { }
68 post_state_ARPCHECK_hook () { }
69 post_state_ARPSEND_hook () { }
70 post_state_RENEW_hook () { }
71 post_state_REBIND_hook () { }
72 post_state_BOUND_hook () { }
73 post_state_REBOOT_hook () { }
74 post_state_EXPIRE_hook () { }
75 post_state_FAIL_hook () { }
76 post_state_TIMEOUT_hook () { }
77
78 #############################################################################
79 # make_resolv_conf
80 #
81 # This function is called to update the information related to the
82 # DNS configuration (the resolver part)
83 #############################################################################
84 make_resolv_conf () 
85 {
86    if [ "x$new_domain_name" != x ] && [ "x$new_domain_name_servers" != x ]; then
87      echo search $new_domain_name >/etc/resolv.conf
88      for nameserver in $new_domain_name_servers; do
89        echo nameserver $nameserver >>/etc/resolv.conf
90      done
91    fi
92 }
93
94 # Must be used on exit.   Invokes the local dhcp client exit hooks, if any.
95 exit_with_hooks () {
96   exit_status=$1
97   if [ -x /etc/dhclient-exit-hooks ]; then
98     . /etc/dhclient-exit-hooks
99   fi
100 # probably should do something with exit status of the local script
101   return $exit_status
102 }
103
104 #############################################################################
105 # set_XXX
106 # unset_XXX
107 #
108 # These function each deal with one particular setting.
109 # They are OS dependent and may be overridden in the 
110 # dhclient-enter-hooks file if needed.
111 #
112 # These functions are called with either "new" or "old" to indicate which
113 # set of variables to use (new_ip_address or old_ip_address...)
114 #
115 #############################################################################
116
117 update_hostname ()
118 {
119         local current_hostname=`/bin/hostname`
120         if      [ "$current_hostname" = "" ] || \
121                 [ "$current_hostname" = "$old_host_name" ]
122         then
123                 if [ "$new_host_name" != "$old_host_name" ]
124                 then
125                         $LOGGER "New Hostname: $new_host_name"
126                         hostname $new_host_name
127                 fi
128         fi
129 }
130
131 set_ip_address () 
132 {
133         local ip
134         local mask
135         local bcast
136
137         if [ $# -lt 1 ]
138         then
139                 return  1
140         fi
141
142         eval ip="\$${1}_ip_address"
143         eval mask="\$${1}_subnet_mask"
144         eval bcast="\$${1}_broadcast_address"
145
146         if [ "$ip" != "" ]
147         then
148                 ifconfig $interface inet $ip netmask $mask broadcast $bcast $medium
149 #               route add $ip 127.0.0.1 > /dev/null 2>&1
150         fi
151 }
152
153 unset_ip_address () 
154 {
155         local ip
156
157         if [ $# -lt 1 ]
158         then
159                 return  1
160         fi
161
162         eval ip="\$${1}_ip_address"
163
164         if [ "$ip" != "" ]
165         then
166                 ifconfig $interface inet -alias $ip $medium
167 #               route delete $ip 127.0.0.1 > /dev/null 2>&1
168         fi
169 }
170
171 set_ip_alias () 
172 {
173         if [ "$alias_ip_address" != "" ]
174         then
175                 ifconfig $interface inet alias $alias_ip_address netmask $alias_subnet_mask
176 #               route add $alias_ip_address 127.0.0.1
177         fi
178 }
179
180 unset_ip_alias () 
181 {
182         if [ "$alias_ip_address" != "" ]
183         then
184                 ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
185 #               route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
186         fi
187 }
188
189 set_routers () 
190 {
191         local router_list
192
193         if [ $# -lt 1 ]
194         then
195                 return  1
196         fi
197
198         eval router_list="\$${1}_routers"
199
200         for router in $router_list
201         do
202                 route add default $router >/dev/null 2>&1
203         done
204 }
205
206 unset_routers () 
207 {
208         local router_list
209
210         if [ $# -lt 1 ]
211         then
212                 return  1
213         fi
214
215         eval router_list="\$${1}_routers"
216
217         for router in $router_list
218         do
219                 route delete default $router >/dev/null 2>&1
220         done
221 }
222
223 set_static_routes () 
224 {
225         local static_routes
226
227         if [ $# -lt 1 ]
228         then
229                 return  1
230         fi
231
232         eval static_routes="\$${1}_static_routes"
233
234         set static_routes
235
236         while [ $# -ge 2 ]
237         do
238                 $LOGGER "New Static Route: $1 -> $2"
239                 route add $1 $2
240                 shift; shift
241         done
242 }
243
244 unset_static_routes () 
245 {
246         local static_routes
247
248         if [ $# -lt 1 ]
249         then
250                 return  1
251         fi
252
253         eval static_routes="\$${1}_static_routes"
254
255         set static_routes
256
257         while [ $# -ge 2 ]
258         do
259                 route delete $1 $2
260                 shift; shift
261         done
262 }
263
264 #############################################################################
265 #
266 # utility functions grouping what needs to be done in logical units.
267 #
268 #############################################################################
269
270 set_all ()
271 {
272         set_ip_address new
273         set_routers new
274         set_static_routes new
275
276         if      [ "$new_ip_address" != "$alias_ip_address" ]
277         then
278                 set_ip_alias
279         fi
280 }
281
282 set_others ()
283 {
284         update_hostname
285         make_resolv_conf
286 }
287
288 clear_arp_table () 
289 {
290         arp -d -a
291 }
292
293 unset_all ()
294 {
295         if [ "$alias_ip_address" != "$old_ip_address" ]
296         then
297                 unset_ip_alias
298         fi
299
300         if [ "$old_ip_address" != "" ] 
301         then
302                 unset_ip_address old
303                 unset_routers old
304                 unset_static_routes old
305                 clear_arp_table
306         fi
307 }
308
309 test_new_lease () 
310 {
311         local rc
312
313         set $new_routers
314
315         if [ $# -ge 1 ]
316         then
317                 set_ip_address new
318         if ping -q -c 1 $1
319                 then
320                         rc=0
321                 else
322                         rc=1
323                 fi
324                 unset_ip_address new
325         else
326                 rc=1
327         fi
328         return  $rc
329 }
330
331 #############################################################################
332 # Main State functions.
333 #
334 # There is a state function for each state of the DHCP client
335 # These functions are OS specific and should be be tampered with.
336 #############################################################################
337
338 in_state_MEDIUM () 
339 {
340   ifconfig $interface $medium
341   ifconfig $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1
342   sleep 1
343   exit_status=0
344 }
345
346 in_state_PREINIT () 
347 {
348         unset_ip_alias
349
350         ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
351                         broadcast 255.255.255.255 up
352         exit_status=0
353 }
354
355 in_state_ARPCHECK () 
356 {
357   exit_status=0
358 }
359
360 in_state_ARPSEND () 
361 {
362   exit_status=0
363 }
364
365 in_state_RENEW () 
366 {
367         if [ "$old_ip_address" != "$new_ip_address" ]
368         then
369                 unset_all
370                 set_all
371         fi
372
373         set_others
374 }
375
376 in_state_REBIND () {
377         in_state_RENEW
378 }
379
380 in_state_BOUND () {
381         unset_all
382         set_all
383         set_others
384 }
385
386 in_state_REBOOT () {
387         in_state_BOUND
388 }
389
390 in_state_EXPIRE () 
391 {
392         unset_all
393         set_ip_alias
394         exit_status=0
395 }
396
397 in_state_FAIL () {
398         in_state_EXPIRE
399 }
400
401 in_state_TIMEOUT () 
402 {
403         unset_all
404
405         if test_new_lease
406         then
407                 set_all
408                 set_others
409         else
410                 $LOGGER "No good lease information in TIMEOUT state"    
411                 set_ip_alias
412                 exit_status=1
413         fi
414 }
415
416 #############################################################################
417 # Main functions:
418 #
419 # dhclient_script_init() parses the optional "enter_hooks" script which can
420 #   override any of the state functions
421 #
422 # This function also parses the variables and notifies the detected changes.
423 #############################################################################
424 dhclient_script_init ()
425 {
426         if [ -x /usr/bin/logger ]; then
427                 LOGGER="/usr/bin/logger -s -p user.notice -t dhclient"
428         else
429                 LOGGER=echo
430         fi
431
432         # Invoke the local dhcp client enter hooks, if they exist.
433         if [ -x /etc/dhclient-enter-hooks ]
434         then
435                 exit_status=0
436                 . /etc/dhclient-enter-hooks
437                 # allow the local script to abort processing of this state
438                 # local script must set exit_status variable to nonzero.
439                 if [ $exit_status -ne 0 ]
440                 then
441                         exit $exit_status
442                 fi
443         fi
444
445         if [ "$new_network_number" != "" ]
446         then
447                 $LOGGER "New Network Number: $new_network_number"
448         fi
449
450         if [ "$new_ip_address" != "" ]
451         then
452                 $LOGGER "New IP Address: $new_ip_address"
453         fi
454
455         if [ "$new_broadcast_address" != "" ]
456         then
457                 $LOGGER "New Broadcast Address: $new_broadcast_address"
458         fi
459
460         if [ "$new_subnet_mask" != "" ]
461         then
462                 $LOGGER "New Subnet Mask for $interface: $new_subnet_mask"
463         fi
464
465         if [ "$alias_subnet_mask" != "" ]
466         then
467         fi
468 }
469
470 #############################################################################
471 # dhclient_main() does the appropriate work depending on the state of
472 # the dhcp client
473 #############################################################################
474 dhclient_script_main ()
475 {
476 #       set -x
477         exit_status=0
478
479         case $reason in
480                 MEDIUM|\
481                 PREINIT|\
482                 ARPCHECK|\
483                 ARPSEND|\
484                 RENEW|\
485                 REBIND|\
486                 BOUND|\
487                 REBOOT|\
488                 EXPIRE|\
489                 FAIL|\
490                 TIMEOUT)
491                         pre_state_${reason}_hook
492                         in_state_${reason}
493                         post_state_${reason}_hook
494                         ;;
495                 *)
496                         $LOGGER "dhclient-script called with invalid reason $reason"
497                         exit_status=1
498                         ;;
499         esac
500
501         exit_with_hooks $exit_status
502 }
503
504 #############################################################################
505 # Let's do the work...
506 #############################################################################
507
508 dhclient_script_init
509 dhclient_script_main
510 exit $exit_status
511
512 #############################################################################
513 # That's all folks
514 #############################################################################