Tagging module iproute2 - iproute2-2.6.16-2
[iproute2.git] / examples / dhcp-client-script
1 #!/bin/bash
2 #
3 # dhclient-script for Linux.
4 #
5 #               This program is free software; you can redistribute it and/or
6 #               modify it under the terms of the GNU General Public License
7 #               as published by the Free Software Foundation; either version
8 #               2 of the License, or (at your option) any later version.
9 #
10 # Authors:      Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
11 #
12 # Probably, I did not understand, what this funny feature as "alias"
13 # means exactly. For now I suppose, that it is a static address, which
14 # we should install and preserve.
15 #
16
17 exec >> /tmp/DHS.log 2>&1
18
19 echo dhc-script $* reason=$reason
20 set | grep "^\(old_\|new_\|check_\)"
21
22 LOG () {
23     echo LOG $* ;
24 }
25
26 # convert 8bit mask to length
27 # arg: $1 = mask
28 #
29 Mask8ToLen() {
30         local l=0;
31
32         while [ $l -le 7 ]; do
33                 if [ $[ ( 1 << $l ) + $1 ] -eq 256 ]; then
34                         return  $[ 8 - $l ]
35                 fi
36                 l=$[ $l + 1 ]
37         done
38         return 0;
39 }
40
41 # convert inet dotted quad mask to length
42 # arg: $1 = dotquad mask
43 #
44 MaskToLen() {
45  local masklen=0
46  local mask8=$1
47
48  case $1 in
49  0.0.0.0)
50         return 0;
51         ;;
52  255.*.0.0)
53         masklen=8
54         mask8=${mask8#255.}
55         mask8=${mask8%.0.0}
56         ;;
57  255.255.*.0)
58         masklen=16
59         mask8=${mask8#255.255.}
60         mask8=${mask8%.0}
61         ;;
62  255.255.255.*)
63         masklen=24
64         mask8=${mask8#255.255.255.}
65         ;;
66  *)
67         return 255
68         ;;
69  esac
70  Mask8ToLen $mask8
71  return $[ $? + $masklen ]
72 }
73
74 # calculate ABC "natural" mask
75 # arg: $1 = dotquad address
76 #
77 ABCMask () {
78  local class;
79
80  class=${1%%.*}
81
82  if [ "$1" = "255.255.255.255" ]; then
83     echo $1
84  elif [ "$1" = "0.0.0.0" ]; then
85     echo $1
86  elif [ $class -ge 224 ]; then
87     echo 240.0.0.0
88  elif [ $class -ge 192 ]; then
89     echo 255.255.255.0
90  elif [ $class -ge 128 ]; then
91     echo 255.255.0.0
92  else
93     echo 255.0.0.0
94  fi
95 }
96
97 # calculate ABC "natural" mask length
98 # arg: $1 = dotquad address
99 #
100 ABCMaskLen () {
101  local class;
102
103  class=${1%%.*}
104
105  if [ "$1" = "255.255.255.255" ]; then
106     return 32
107  elif [ "$1" = "0.0.0.0" ]; then
108     return 0
109  elif [ $class -ge 224 ]; then
110     return 4;
111  elif [ $class -ge 192 ]; then
112     return 24;
113  elif [ $class -ge 128 ]; then
114     return 16;
115  else
116     return 8;
117  fi
118 }
119
120 # Delete IP address
121 # args: $1 = interface
122 #       $2 = address
123 #       $3 = mask
124 #       $4 = broadcast
125 #       $5 = label
126 #
127 DelINETAddr () {
128   local masklen=32
129   local addrid=$1
130
131   LOG DelINETAddr $*
132
133   if [ "$5" ]; then
134     addrid=$addrid:$5
135   fi
136   LOG ifconfig $addrid down
137   ifconfig $addrid down
138 }
139
140 # Add IP address
141 # args: $1 = interface
142 #       $2 = address
143 #       $3 = mask
144 #       $4 = broadcast
145 #       $5 = label
146 #
147 AddINETAddr () {
148   local mask_arg
149   local brd_arg
150   local addrid=$1
151
152   LOG AddINETAddr $*
153
154   if [ "$5" ]; then
155     addrid=$addrid:$5
156   fi
157   if [ "$3" ]; then
158     mask_arg="netmask $3"
159   fi
160   if [ "$4" ]; then
161     brd_arg="broadcast $4"
162   fi
163
164   LOG ifconfig $addrid $2 $mask_arg $brd_arg up
165   ifconfig $addrid $2 $mask_arg $brd_arg up
166 }
167
168 # Add default routes
169 # args: $1 = routers list
170 #
171 AddDefaultRoutes() {
172     local router
173
174     if [ "$1" ]; then
175       LOG AddDefaultRoutes $*
176       for router in $1; do
177         LOG route add default gw $router
178         route add default gw $router
179       done ;
180     fi
181 }
182
183 # Delete default routes
184 # args: $1 = routers list
185 #
186 DelDefaultRoutes() {
187     local router
188
189     if [ "$1" ]; then
190       LOG DelDefaultRoutes $*
191
192       for router in $1; do
193         LOG route del default gw $router
194         route del default gw $router
195       done
196     fi
197 }
198
199 # ping a host
200 # args: $1 = dotquad address of the host
201 #
202 PingNode() {
203     LOG PingNode $*
204     if ping -q -c 1 -w 2 $1 ; then
205         return 0;
206     fi
207     return 1;
208 }
209
210 # Check (and add route, if alive) default routers
211 # args: $1 = routers list
212 # returns: 0 if at least one router is alive.
213 #
214 CheckRouterList() {
215     local router
216     local succeed=1
217
218     LOG CheckRouterList $*
219
220     for router in $1; do
221       if PingNode $router ; then
222         succeed=0
223         route add default gw $router
224       fi
225     done
226     return $succeed
227 }
228
229 # Delete/create static routes.
230 # args: $1 = operation (del/add)
231 #       $2 = routes list in format "dst1 nexthop1 dst2 ..."
232 #
233 # BEWARE: this feature of DHCP is obsolete, because does not
234 #         support subnetting.
235 #
236 X-StaticRouteList() {
237     local op=$1
238     local lst="$2"
239     local masklen
240
241     LOG X-StaticRouteList $*
242
243     if [ "$lst" ]; then
244       set $lst
245       while [ $# -gt 1 ]; do
246         route $op -net $1 netmask `ABCMask "$1"` gw $2
247         shift; shift;
248       done
249    fi
250 }
251
252 # Create static routes.
253 # arg: $1 = routes list in format "dst1 nexthop1 dst2 ..."
254 #
255 AddStaticRouteList() {
256     LOG AddStaticRouteList $*
257     X-StaticRouteList add "$1"
258 }
259
260 # Delete static routes.
261 # arg: $1 = routes list in format "dst1 nexthop1 dst2 ..."
262 #
263 DelStaticRouteList() {
264     LOG DelStaticRouteList $*
265     X-StaticRouteList del "$1"
266 }
267
268 # Broadcast unsolicited ARP to update neighbours' caches.
269 # args: $1 = interface
270 #       $2 = address
271 #
272 UnsolicitedARP() {
273     if [ -f /sbin/arping ]; then
274         /sbin/arping -A -c 1 -I "$1" "$2" &
275         (sleep 2 ; /sbin/arping -U -c 1 -I "$1" "$2" ) &
276     fi
277 }
278
279 # Duplicate address detection.
280 # args: $1 = interface
281 #       $2 = test address
282 # returns: 0, if DAD succeeded.
283 DAD() {
284   if [ -f /sbin/arping ]; then
285         /sbin/arping -c 2 -w 3 -D -I "$1" "$2"
286         return $?
287   fi
288   return 0
289 }
290
291
292 # Setup resolver.
293 # args: NO
294 #       domain and nameserver list are passed in global variables.
295 #
296 # NOTE: we try to be careful and not to break user supplied resolv.conf.
297 #       The script mangles it, only if it has dhcp magic signature.
298 #
299 UpdateDNS() {
300     local nameserver
301     local idstring="#### Generated by DHCPCD"
302
303     LOG UpdateDNS $*
304
305     if [ "$new_domain_name" = "" -a "$new_domain_name_servers" = "" ]; then
306         return 0;
307     fi
308
309     echo $idstring > /etc/resolv.conf.dhcp
310     if [ "$new_domain_name" ]; then
311         echo search $new_domain_name >> /etc/resolv.conf.dhcp
312     fi
313     echo options ndots:1 >> /etc/resolv.conf.dhcp
314
315     if [ "$new_domain_name_servers" ]; then
316         for nameserver in $new_domain_name_servers; do
317             echo nameserver $nameserver >> /etc/resolv.conf.dhcp
318         done
319     else
320         echo nameserver 127.0.0.1 >> /etc/resolv.conf.dhcp
321     fi
322
323     if [ -f /etc/resolv.conf ]; then
324         if [ "`head -1 /etc/resolv.conf`" != "$idstring" ]; then
325             return 0
326         fi
327         if [ "$old_domain_name" = "$new_domain_name" -a
328              "$new_domain_name_servers" = "$old_domain_name_servers" ]; then
329              return 0
330         fi
331     fi
332     mv /etc/resolv.conf.dhcp /etc/resolv.conf
333 }
334
335 case $reason in
336 NBI)
337   exit 1
338   ;;
339
340 MEDIUM)
341   exit 0
342   ;;
343
344 PREINIT)
345   ifconfig $interface:dhcp down
346   ifconfig $interface:dhcp1 down
347   if [ -d /proc/sys/net/ipv4/conf/$interface ]; then
348     ifconfig $interface:dhcp 10.10.10.10 netmask 255.255.255.255
349     ifconfig $interface:dhcp down
350     if [ -d /proc/sys/net/ipv4/conf/$interface ]; then
351         LOG The interface $interface already configured.
352     fi
353   fi
354   ifconfig $interface:dhcp up
355   exit 0
356   ;;
357
358 ARPSEND)
359   exit 0
360   ;;
361
362 ARPCHECK)
363   if DAD "$interface" "$check_ip_address" ; then
364     exit 0
365   fi
366   exit 1
367   ;;
368
369 BOUND|RENEW|REBIND|REBOOT)
370   if [ "$old_ip_address" -a "$alias_ip_address" -a \
371         "$alias_ip_address" != "$old_ip_address" ]; then
372     DelINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
373   fi
374   if [ "$old_ip_address" -a "$old_ip_address" != "$new_ip_address" ]; then
375     DelINETAddr "$interface" "$old_ip_address" "$old_subnet_mask" "$old_broadcast_address" dhcp
376     DelDefaultRoutes "$old_routers"
377     DelStaticRouteList "$old_static_routes"
378   fi
379   if [ "$old_ip_address" = "" -o "$old_ip_address" != "$new_ip_address" -o \
380        "$reason" = "BOUND" -o "$reason" = "REBOOT" ]; then
381     AddINETAddr "$interface" "$new_ip_address" "$new_subnet_mask" "$new_broadcast_address" dhcp
382     AddStaticRouteList "$new_static_routes"
383     AddDefaultRoutes "$new_routers"
384     UnsolicitedARP "$interface" "$new_ip_address"
385   fi
386   if [ "$new_ip_address" != "$alias_ip_address" -a "$alias_ip_address" ]; then
387     AddINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
388   fi
389   UpdateDNS
390   exit 0
391   ;;
392
393 EXPIRE|FAIL)
394   if [ "$alias_ip_address" ]; then
395     DelINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
396   fi
397   if [ "$old_ip_address" ]; then
398     DelINETAddr "$interface" "$old_ip_address" "$old_subnet_mask" "$old_broadcast_address" dhcp
399     DelDefaultRoutes "$old_routers"
400     DelStaticRouteList "$old_static_routes"
401   fi
402   if [ "$alias_ip_address" ]; then
403     AddINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
404   fi
405   exit 0
406   ;;
407
408 TIMEOUT)
409   if [ "$alias_ip_address" ]; then
410     DelINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
411   fi
412 # Seems, <null address> means, that no more old leases found.
413 # Or does it mean bug in dhcpcd? 8) Fail for now.
414   if [ "$new_ip_address" = "<null address>" ]; then
415     if [ "$old_ip_address" ]; then
416         DelINETAddr "$interface" "$old_ip_address" "$old_subnet_mask" "$old_broadcast_address" dhcp
417     fi
418     if [ "$alias_ip_address" ]; then
419         AddINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
420     fi
421     exit 1
422   fi
423   if DAD "$interface" "$new_ip_address" ; then
424     AddINETAddr "$interface" "$new_ip_address" "$new_subnet_mask" "$new_broadcast_address" dhcp
425     UnsolicitedARP "$interface" "$new_ip_address"
426     if [ "$alias_ip_address" -a "$alias_ip_address" != "$new_ip_address" ]; then
427       AddINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
428       UnsolicitedARP "$interface" "$alias_ip_address"
429     fi
430     if CheckRouterList "$new_routers" ; then
431         AddStaticRouteList "$new_static_routes"
432         UpdateDNS
433         exit 0
434     fi
435   fi
436   DelINETAddr "$interface" "$new_ip_address" "$new_subnet_mask" "$new_broadcast_address" dhcp
437   DelDefaultRoutes "$old_routers"
438   DelStaticRouteList "$old_static_routes"
439   if [ "$alias_ip_address" ]; then
440     AddINETAddr "$interface" "$alias_ip_address" "$alias_subnet_mask" "$alias_broadcast_address" dhcp1
441   fi
442   exit 1
443   ;;
444 esac
445
446 exit 0