]> git.proxmox.com Git - mirror_lxc.git/blame - hooks/dhclient-script
spelling: override
[mirror_lxc.git] / hooks / dhclient-script
CommitLineData
27234deb
JC
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# 5. Script refresh in 2017. The aliasing code was too convoluted and needs
26# to go away. Migrated DHCPv4 script to ip command from iproute2 suite.
27# This is based on Debian script with some tweaks. ifconfig is no longer
28# used. Everything is done using ip tool from ip-route2.
29
30# 6. LXC Fork
31# Remove hooks and dependency on ifconfig.
32# Resolve every paths against the $ROOTFS environment variable.
33
34# 'ip' just looks too weird. Also, we now have unit-tests! Those unit-tests
768f183c 35# override this line to use a fake ip-echo tool. It's also convenient
27234deb
JC
36# if your system holds ip tool in a non-standard location.
37ip=/sbin/ip
38
39# update /etc/resolv.conf based on received values
40# This updated version mostly follows Debian script by Andrew Pollock et al.
41make_resolv_conf() {
42 local resolv_conf="${ROOTFS}/etc/resolv.conf"
43 local new_resolv_conf="${ROOTFS}/etc/resolv.conf.dhclient-new"
44
45 # DHCPv4
46 if [ -n "$new_domain_search" ] || [ -n "$new_domain_name" ] ||
47 [ -n "$new_domain_name_servers" ]; then
48 rm -f $new_resolv_conf
49
50 if [ -n "$new_domain_name" ]; then
51 echo domain ${new_domain_name%% *} >>$new_resolv_conf
52 fi
53
54 if [ -n "$new_domain_search" ]; then
55 if [ -n "$new_domain_name" ]; then
56 domain_in_search_list=""
57 for domain in $new_domain_search; do
58 if [ "$domain" = "${new_domain_name}" ] ||
59 [ "$domain" = "${new_domain_name}." ]; then
60 domain_in_search_list="Yes"
61 fi
62 done
63 if [ -z "$domain_in_search_list" ]; then
64 new_domain_search="$new_domain_name $new_domain_search"
65 fi
66 fi
67 echo "search ${new_domain_search}" >> $new_resolv_conf
68 elif [ -n "$new_domain_name" ]; then
69 echo "search ${new_domain_name}" >> $new_resolv_conf
70 fi
71
72 if [ -n "$new_domain_name_servers" ]; then
73 for nameserver in $new_domain_name_servers; do
74 echo nameserver $nameserver >>$new_resolv_conf
75 done
76 else # keep 'old' nameservers
77 sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p $resolv_conf >>$new_resolv_conf
78 fi
79
80 if [ -f "$resolv_conf" ]; then
81 chown --reference=$resolv_conf $new_resolv_conf
82 chmod --reference=$resolv_conf $new_resolv_conf
83 fi
84 mv -f $new_resolv_conf $resolv_conf
85 # DHCPv6
86 elif [ -n "$new_dhcp6_domain_search" ] || [ -n "$new_dhcp6_name_servers" ]; then
87 rm -f $new_resolv_conf
88
89 if [ -n "$new_dhcp6_domain_search" ]; then
90 echo "search ${new_dhcp6_domain_search}" >> $new_resolv_conf
91 fi
92
93 if [ -n "$new_dhcp6_name_servers" ]; then
94 for nameserver in $new_dhcp6_name_servers; do
95 # append %interface to link-local-address nameservers
96 if [ "${nameserver##fe80::}" != "$nameserver" ] ||
97 [ "${nameserver##FE80::}" != "$nameserver" ]; then
98 nameserver="${nameserver}%${interface}"
99 fi
100 echo nameserver $nameserver >>$new_resolv_conf
101 done
102 else # keep 'old' nameservers
103 sed -n /^\w*[Nn][Aa][Mm][Ee][Ss][Ee][Rr][Vv][Ee][Rr]/p $resolv_conf >>$new_resolv_conf
104 fi
105
106 if [ -f "$resolv_conf" ]; then
107 chown --reference=$resolv_conf $new_resolv_conf
108 chmod --reference=$resolv_conf $new_resolv_conf
109 fi
110 mv -f $new_resolv_conf $resolv_conf
111 fi
112}
113
114# set host name
115set_hostname() {
116 local current_hostname
117
118 if [ -n "$new_host_name" ]; then
119 current_hostname=$(hostname)
120
121 # current host name is empty, '(none)' or 'localhost' or differs from new one from DHCP
122 if [ -z "$current_hostname" ] ||
123 [ "$current_hostname" = '(none)' ] ||
124 [ "$current_hostname" = 'localhost' ] ||
125 [ "$current_hostname" = "$old_host_name" ]; then
126 if [ "$new_host_name" != "$old_host_name" ]; then
127 hostname "$new_host_name"
128 fi
129 fi
130 fi
131}
132
133# Execute the operation
134case "$reason" in
135
136 ### DHCPv4 Handlers
137
138 MEDIUM|ARPCHECK|ARPSEND)
139 # Do nothing
140 ;;
141 PREINIT)
142 # The DHCP client is requesting that an interface be
143 # configured as required in order to send packets prior to
144 # receiving an actual address. - dhclient-script(8)
145
146 # ensure interface is up
147 ${ip} link set dev ${interface} up
148
149 if [ -n "$alias_ip_address" ]; then
150 # flush alias IP from interface
151 ${ip} -4 addr flush dev ${interface} label ${interface}:0
152 fi
153
154 ;;
155
156 BOUND|RENEW|REBIND|REBOOT)
157 set_hostname
158
159 if [ -n "$old_ip_address" ] && [ -n "$alias_ip_address" ] &&
160 [ "$alias_ip_address" != "$old_ip_address" ]; then
161 # alias IP may have changed => flush it
162 ${ip} -4 addr flush dev ${interface} label ${interface}:0
163 fi
164
165 if [ -n "$old_ip_address" ] &&
166 [ "$old_ip_address" != "$new_ip_address" ]; then
167 # leased IP has changed => flush it
168 ${ip} -4 addr flush dev ${interface} label ${interface}
169 fi
170
171 if [ -z "$old_ip_address" ] ||
172 [ "$old_ip_address" != "$new_ip_address" ] ||
173 [ "$reason" = "BOUND" ] || [ "$reason" = "REBOOT" ]; then
174 # new IP has been leased or leased IP changed => set it
175 ${ip} -4 addr add ${new_ip_address}${new_subnet_mask:+/$new_subnet_mask} \
176 ${new_broadcast_address:+broadcast $new_broadcast_address} \
177 dev ${interface} label ${interface}
178
179 if [ -n "$new_interface_mtu" ]; then
180 # set MTU
181 ${ip} link set dev ${interface} mtu ${new_interface_mtu}
182 fi
183
184 # if we have $new_rfc3442_classless_static_routes then we have to
185 # ignore $new_routers entirely
186 if [ ! "$new_rfc3442_classless_static_routes" ]; then
187 # set if_metric if IF_METRIC is set or there's more than one router
188 if_metric="$IF_METRIC"
189 if [ "${new_routers%% *}" != "${new_routers}" ]; then
190 if_metric=${if_metric:-1}
191 fi
192
193 for router in $new_routers; do
194 if [ "$new_subnet_mask" = "255.255.255.255" ]; then
195 # point-to-point connection => set explicit route
196 ${ip} -4 route add ${router} dev $interface >/dev/null 2>&1
197 fi
198
199 # set default route
200 ${ip} -4 route add default via ${router} dev ${interface} \
201 ${if_metric:+metric $if_metric} >/dev/null 2>&1
202
203 if [ -n "$if_metric" ]; then
204 if_metric=$((if_metric+1))
205 fi
206 done
207 fi
208 fi
209
210 if [ -n "$alias_ip_address" ] &&
211 [ "$new_ip_address" != "$alias_ip_address" ]; then
212 # separate alias IP given, which may have changed
213 # => flush it, set it & add host route to it
214 ${ip} -4 addr flush dev ${interface} label ${interface}:0
215 ${ip} -4 addr add ${alias_ip_address}${alias_subnet_mask:+/$alias_subnet_mask} \
216 dev ${interface} label ${interface}:0
217 ${ip} -4 route add ${alias_ip_address} dev ${interface} >/dev/null 2>&1
218 fi
219
220 # update /etc/resolv.conf
221 make_resolv_conf
222
223 ;;
224
225 EXPIRE|FAIL|RELEASE|STOP)
226 if [ -n "$alias_ip_address" ]; then
227 # flush alias IP
228 ${ip} -4 addr flush dev ${interface} label ${interface}:0
229 fi
230
231 if [ -n "$old_ip_address" ]; then
232 # flush leased IP
233 ${ip} -4 addr flush dev ${interface} label ${interface}
234 fi
235
236 if [ -n "$alias_ip_address" ]; then
237 # alias IP given => set it & add host route to it
238 ${ip} -4 addr add ${alias_ip_address}${alias_subnet_mask:+/$alias_subnet_mask} \
239 dev ${interface} label ${interface}:0
240 ${ip} -4 route add ${alias_ip_address} dev ${interface} >/dev/null 2>&1
241 fi
242
243 ;;
244
245 TIMEOUT)
246 if [ -n "$alias_ip_address" ]; then
247 # flush alias IP
248 ${ip} -4 addr flush dev ${interface} label ${interface}:0
249 fi
250
251 # set IP from recorded lease
252 ${ip} -4 addr add ${new_ip_address}${new_subnet_mask:+/$new_subnet_mask} \
253 ${new_broadcast_address:+broadcast $new_broadcast_address} \
254 dev ${interface} label ${interface}
255
256 if [ -n "$new_interface_mtu" ]; then
257 # set MTU
258 ${ip} link set dev ${interface} mtu ${new_interface_mtu}
259 fi
260
261 # if there is no router recorded in the lease or the 1st router answers pings
262 if [ -z "$new_routers" ] || ping -q -c 1 "${new_routers%% *}"; then
263 # if we have $new_rfc3442_classless_static_routes then we have to
264 # ignore $new_routers entirely
265 if [ ! "$new_rfc3442_classless_static_routes" ]; then
266 if [ -n "$alias_ip_address" ] &&
267 [ "$new_ip_address" != "$alias_ip_address" ]; then
268 # separate alias IP given => set up the alias IP & add host route to it
269 ${ip} -4 addr add \
270 ${alias_ip_address}${alias_subnet_mask:+/$alias_subnet_mask} \
271 dev ${interface} label ${interface}:0
272 ${ip} -4 route add ${alias_ip_address} dev ${interface} >/dev/null 2>&1
273 fi
274
275 # set if_metric if IF_METRIC is set or there's more than one router
276 if_metric="$IF_METRIC"
277 if [ "${new_routers%% *}" != "${new_routers}" ]; then
278 if_metric=${if_metric:-1}
279 fi
280
281 # set default route
282 for router in $new_routers; do
283 ${ip} -4 route add default via ${router} dev ${interface} \
284 ${if_metric:+metric $if_metric} >/dev/null 2>&1
285
286 if [ -n "$if_metric" ]; then
287 if_metric=$((if_metric+1))
288 fi
289 done
290 fi
291
292 # update /etc/resolv.conf
293 make_resolv_conf
294 else
295 # flush all IPs from interface
296 ${ip} -4 addr flush dev ${interface}
297 exit 2
298 fi
299
300 ;;
301
302 ### DHCPv6 Handlers
303 # TODO handle prefix change: ?based on ${old_ip6_prefix} and ${new_ip6_prefix}?
304
305 PREINIT6)
306 # ensure interface is up
307 ${ip} link set ${interface} up
308
309 # We need to give the kernel some time to active interface
310 interface_up_wait_time=5
311 for i in $(seq 0 ${interface_up_wait_time})
312 do
313 ${ip} addr show ${interface} | grep NO-CARRIER >/dev/null 2>&1
314 if [ $? -ne 0 ]; then
315 break;
316 fi
317 sleep 1
318 done
319
320 # flush any stale global permanent IPs from interface
321 ${ip} -6 addr flush dev ${interface} scope global permanent
322
323 # Wait for duplicate address detection for this interface if the
324 # --dad-wait-time parameter has been specified and is greater than
325 # zero.
326 if [ ${dad_wait_time} -gt 0 ]; then
327 # Check if any IPv6 address on this interface is marked as
328 # tentative.
329 ${ip} addr show ${interface} | grep inet6 | grep tentative \
330 &> /dev/null
331 if [ $? -eq 0 ]; then
332 # Wait for duplicate address detection to complete or for
333 # the timeout specified as --dad-wait-time.
334 for i in $(seq 0 $dad_wait_time)
335 do
336 # We're going to poll for the tentative flag every second.
337 sleep 1
338 ${ip} addr show ${interface} | grep inet6 | grep tentative \
339 &> /dev/null
340 if [ $? -ne 0 ]; then
341 break;
342 fi
343 done
344 fi
345 fi
346
347 ;;
348
349 BOUND6|RENEW6|REBIND6)
350 if [ "${new_ip6_address}" ] && [ "${new_ip6_prefixlen}" ]; then
351 # set leased IP
352 ${ip} -6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \
353 dev ${interface} scope global
354 fi
355
356 # update /etc/resolv.conf
357 if [ "${reason}" = BOUND6 ] ||
358 [ "${new_dhcp6_name_servers}" != "${old_dhcp6_name_servers}" ] ||
359 [ "${new_dhcp6_domain_search}" != "${old_dhcp6_domain_search}" ]; then
360 make_resolv_conf
361 fi
362
363 ;;
364
365 DEPREF6)
366 if [ -z "${cur_ip6_prefixlen}" ]; then
367 exit 2
368 fi
369
370 # set preferred lifetime of leased IP to 0
371 ${ip} -6 addr change ${cur_ip6_address}/${cur_ip6_prefixlen} \
372 dev ${interface} scope global preferred_lft 0
373
374 ;;
375
376 EXPIRE6|RELEASE6|STOP6)
377 if [ -z "${old_ip6_address}" ] || [ -z "${old_ip6_prefixlen}" ]; then
378 exit 2
379 fi
380
381 # delete leased IP
382 ${ip} -6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \
383 dev ${interface}
384
385 ;;
386esac
387
388exit 0