]> git.ipfire.org Git - thirdparty/dhcp.git/blob - client/scripts/linux
7d77fd39e33d52122e898cf78af0012ceee0e9b6
[thirdparty/dhcp.git] / client / scripts / linux
1 #!/bin/bash
2 # dhclient-script for Linux. Dan Halbert, March, 1997.
3 # Updated for Linux 2.[12] by Brian J. Murrell, January 1999.
4 # No guarantees about this. I'm a novice at the details of Linux
5 # networking.
6
7 # Notes:
8
9 # 0. This script is based on the netbsd script supplied with dhcp-970306.
10
11 # 1. ifconfig down apparently deletes all relevant routes and flushes
12 # the arp cache, so this doesn't need to be done explicitly.
13
14 # 2. The alias address handling here has not been tested AT ALL.
15 # I'm just going by the doc of modern Linux ip aliasing, which uses
16 # notations like eth0:0, eth0:1, for each alias.
17
18 # 3. I have to calculate the network address, and calculate the broadcast
19 # address if it is not supplied. This might be much more easily done
20 # by the dhclient C code, and passed on.
21
22 # 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious
23 # of the $1 in its args.
24
25 # 'ip' just looks too weird. /sbin/ip looks less weird.
26 ip=/sbin/ip
27
28 make_resolv_conf() {
29 if [ x"$new_domain_name_servers" != x ]; then
30 cat /dev/null > /etc/resolv.conf.dhclient
31 chmod 644 /etc/resolv.conf.dhclient
32 if [ x"$new_domain_search" != x ]; then
33 echo search $new_domain_search >> /etc/resolv.conf.dhclient
34 elif [ x"$new_domain_name" != x ]; then
35 # Note that the DHCP 'Domain Name Option' is really just a domain
36 # name, and that this practice of using the domain name option as
37 # a search path is both nonstandard and deprecated.
38 echo search $new_domain_name >> /etc/resolv.conf.dhclient
39 fi
40 for nameserver in $new_domain_name_servers; do
41 echo nameserver $nameserver >>/etc/resolv.conf.dhclient
42 done
43
44 mv /etc/resolv.conf.dhclient /etc/resolv.conf
45 elif [ "x${new_dhcp6_name_servers}" != x ] ; then
46 cat /dev/null > /etc/resolv.conf.dhclient6
47 chmod 644 /etc/resolv.conf.dhclient6
48
49 if [ "x${new_dhcp6_domain_search}" != x ] ; then
50 echo search ${new_dhcp6_domain_search} >> /etc/resolv.conf.dhclient6
51 fi
52 shopt -s nocasematch
53 for nameserver in ${new_dhcp6_name_servers} ; do
54 # If the nameserver has a link-local address
55 # add a <zone_id> (interface name) to it.
56 if [[ "$nameserver" =~ ^fe80:: ]]
57 then
58 zone_id="%$interface"
59 else
60 zone_id=
61 fi
62 echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6
63 done
64 shopt -u nocasematch
65
66 mv /etc/resolv.conf.dhclient6 /etc/resolv.conf
67 fi
68 }
69
70 # Must be used on exit. Invokes the local dhcp client exit hooks, if any.
71 exit_with_hooks() {
72 exit_status=$1
73 if [ -f /etc/dhclient-exit-hooks ]; then
74 . /etc/dhclient-exit-hooks
75 fi
76 # probably should do something with exit status of the local script
77 exit $exit_status
78 }
79
80 # Invoke the local dhcp client enter hooks, if they exist.
81 if [ -f /etc/dhclient-enter-hooks ]; then
82 exit_status=0
83 . /etc/dhclient-enter-hooks
84 # allow the local script to abort processing of this state
85 # local script must set exit_status variable to nonzero.
86 if [ $exit_status -ne 0 ]; then
87 exit $exit_status
88 fi
89 fi
90
91 ###
92 ### DHCPv4 Handlers
93 ###
94
95 if [ x$new_broadcast_address != x ]; then
96 new_broadcast_arg="broadcast $new_broadcast_address"
97 fi
98 if [ x$old_broadcast_address != x ]; then
99 old_broadcast_arg="broadcast $old_broadcast_address"
100 fi
101 if [ x$new_subnet_mask != x ]; then
102 new_subnet_arg="netmask $new_subnet_mask"
103 fi
104 if [ x$old_subnet_mask != x ]; then
105 old_subnet_arg="netmask $old_subnet_mask"
106 fi
107 if [ x$alias_subnet_mask != x ]; then
108 alias_subnet_arg="netmask $alias_subnet_mask"
109 fi
110 if [ x$new_interface_mtu != x ]; then
111 mtu_arg="mtu $new_interface_mtu"
112 fi
113 if [ x$IF_METRIC != x ]; then
114 metric_arg="metric $IF_METRIC"
115 fi
116
117 if [ x$reason = xMEDIUM ]; then
118 # Linux doesn't do mediums (ok, ok, media).
119 exit_with_hooks 0
120 fi
121
122 if [ x$reason = xPREINIT ]; then
123 if [ x$alias_ip_address != x ]; then
124 # Bring down alias interface. Its routes will disappear too.
125 ifconfig $interface:0- inet 0
126 fi
127 ifconfig $interface 0 up
128
129 # We need to give the kernel some time to get the interface up.
130 sleep 1
131
132 exit_with_hooks 0
133 fi
134
135 if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then
136 exit_with_hooks 0
137 fi
138
139 if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
140 [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
141 current_hostname=`hostname`
142 if [ x$current_hostname = x ] || \
143 [ x$current_hostname = "x(none)" ] || \
144 [ x$current_hostname = xlocalhost ] || \
145 [ x$current_hostname = x$old_host_name ]; then
146 if [ x$new_host_name != x$old_host_name ]; then
147 hostname "$new_host_name"
148 fi
149 fi
150
151 if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
152 [ x$alias_ip_address != x$old_ip_address ]; then
153 # Possible new alias. Remove old alias.
154 ifconfig $interface:0- inet 0
155 fi
156 if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then
157 # IP address changed. Bringing down the interface will delete all routes,
158 # and clear the ARP cache.
159 ifconfig $interface inet 0 down
160
161 fi
162 if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
163 [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
164
165 ifconfig $interface inet $new_ip_address $new_subnet_arg \
166 $new_broadcast_arg $mtu_arg
167 # Add a network route to the computed network address.
168 for router in $new_routers; do
169 if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then
170 route add -host $router dev $interface
171 fi
172 route add default gw $router $metric_arg dev $interface
173 done
174 else
175 # we haven't changed the address, have we changed other options
176 # that we wish to update?
177 if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then
178 # if we've changed routers delete the old and add the new.
179 for router in $old_routers; do
180 route del default gw $router
181 done
182 for router in $new_routers; do
183 if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then
184 route add -host $router dev $interface
185 fi
186 route add default gw $router $metric_arg dev $interface
187 done
188 fi
189 fi
190 if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
191 then
192 ifconfig $interface:0- inet 0
193 ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
194 route add -host $alias_ip_address $interface:0
195 fi
196 make_resolv_conf
197 exit_with_hooks 0
198 fi
199
200 if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \
201 || [ x$reason = xSTOP ]; then
202 if [ x$alias_ip_address != x ]; then
203 # Turn off alias interface.
204 ifconfig $interface:0- inet 0
205 fi
206 if [ x$old_ip_address != x ]; then
207 # Shut down interface, which will delete routes and clear arp cache.
208 ifconfig $interface inet 0 down
209 fi
210 if [ x$alias_ip_address != x ]; then
211 ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
212 route add -host $alias_ip_address $interface:0
213 fi
214 exit_with_hooks 0
215 fi
216
217 if [ x$reason = xTIMEOUT ]; then
218 if [ x$alias_ip_address != x ]; then
219 ifconfig $interface:0- inet 0
220 fi
221 ifconfig $interface inet $new_ip_address $new_subnet_arg \
222 $new_broadcast_arg $mtu_arg
223 set $new_routers
224 if ping -q -c 1 $1; then
225 if [ x$new_ip_address != x$alias_ip_address ] && \
226 [ x$alias_ip_address != x ]; then
227 ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
228 route add -host $alias_ip_address dev $interface:0
229 fi
230 for router in $new_routers; do
231 if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then
232 route add -host $router dev $interface
233 fi
234 route add default gw $router $metric_arg dev $interface
235 done
236 make_resolv_conf
237 exit_with_hooks 0
238 fi
239 ifconfig $interface inet 0 down
240 exit_with_hooks 1
241 fi
242
243 ###
244 ### DHCPv6 Handlers
245 ###
246
247 if [ x$reason = xPREINIT6 ] ; then
248 # Ensure interface is up.
249 ${ip} link set ${interface} up
250
251 # We need to give the kernel some time to active interface
252 interface_up_wait_time=5
253 for i in $(seq 0 ${interface_up_wait_time})
254 do
255 ifconfig ${interface} | grep RUNNING >/dev/null 2>&1
256 if [ $? -eq 0 ]; then
257 break;
258 fi
259 sleep 1
260 done
261
262 # Remove any stale addresses from aborted clients.
263 ${ip} -f inet6 addr flush dev ${interface} scope global permanent
264
265 # Wait for duplicate address detection for this interface if the
266 # --dad-wait-time parameter has been specified and is greater than
267 # zero.
268 if [ ${dad_wait_time} -gt 0 ]; then
269 # Check if any IPv6 address on this interface is marked as
270 # tentative.
271 ${ip} addr show ${interface} | grep inet6 | grep tentative \
272 &> /dev/null
273 if [ $? -eq 0 ]; then
274 # Wait for duplicate address detection to complete or for
275 # the timeout specified as --dad-wait-time.
276 for i in $(seq 0 $dad_wait_time)
277 do
278 # We're going to poll for the tentative flag every second.
279 sleep 1
280 ${ip} addr show ${interface} | grep inet6 | grep tentative \
281 &> /dev/null
282 if [ $? -ne 0 ]; then
283 break;
284 fi
285 done
286 fi
287 fi
288
289 exit_with_hooks 0
290 fi
291
292 if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then
293 echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix}
294
295 exit_with_hooks 0
296 fi
297
298 if [ x$reason = xBOUND6 ] ; then
299 if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then
300 exit_with_hooks 2;
301 fi
302
303 ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \
304 dev ${interface} scope global
305
306 # Check for nameserver options.
307 make_resolv_conf
308
309 exit_with_hooks 0
310 fi
311
312 if [ x$reason = xRENEW6 ] || [ x$reason = xREBIND6 ] ; then
313 if [ x${new_ip6_address} != x ] && [ x${new_ip6_prefixlen} != x ] ; then
314 ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \
315 dev ${interface} scope global
316 fi
317
318 # Make sure nothing has moved around on us.
319
320 # Nameservers/domains/etc.
321 if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] ||
322 [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ] ; then
323 make_resolv_conf
324 fi
325
326 exit_with_hooks 0
327 fi
328
329 if [ x$reason = xDEPREF6 ] ; then
330 if [ x${new_ip6_prefixlen} = x ] ; then
331 exit_with_hooks 2;
332 fi
333
334 ${ip} -f inet6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \
335 dev ${interface} scope global preferred_lft 0
336
337 exit_with_hooks 0
338 fi
339
340 if [ x$reason = xEXPIRE6 -o x$reason = xRELEASE6 -o x$reason = xSTOP6 ] ; then
341 if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then
342 exit_with_hooks 2;
343 fi
344
345 ${ip} -f inet6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \
346 dev ${interface}
347
348 exit_with_hooks 0
349 fi
350
351 exit_with_hooks 0