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
9 # 0. This script is based on the netbsd script supplied with dhcp-970306.
11 # 1. ifconfig down apparently deletes all relevant routes and flushes
12 # the arp cache, so this doesn't need to be done explicitly.
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.
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.
22 # 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious
23 # of the $1 in its args.
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.
31 # Remove hooks and dependency on ifconfig.
32 # Resolve every paths against the $ROOTFS environment variable.
34 # 'ip' just looks too weird. Also, we now have unit-tests! Those unit-tests
35 # override this line to use a fake ip-echo tool. It's also convenient
36 # if your system holds ip tool in a non-standard location.
39 # update /etc/resolv.conf based on received values
40 # This updated version mostly follows Debian script by Andrew Pollock et al.
42 local resolv_conf
="${ROOTFS}/etc/resolv.conf"
43 local new_resolv_conf
="${ROOTFS}/etc/resolv.conf.dhclient-new"
46 if [ -n "$new_domain_search" ] ||
[ -n "$new_domain_name" ] ||
47 [ -n "$new_domain_name_servers" ]; then
48 rm -f $new_resolv_conf
50 if [ -n "$new_domain_name" ]; then
51 echo domain
${new_domain_name%% *} >>$new_resolv_conf
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"
63 if [ -z "$domain_in_search_list" ]; then
64 new_domain_search
="$new_domain_name $new_domain_search"
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
72 if [ -n "$new_domain_name_servers" ]; then
73 for nameserver
in $new_domain_name_servers; do
74 echo nameserver
$nameserver >>$new_resolv_conf
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
80 if [ -f "$resolv_conf" ]; then
81 chown
--reference=$resolv_conf $new_resolv_conf
82 chmod --reference=$resolv_conf $new_resolv_conf
84 mv -f $new_resolv_conf $resolv_conf
86 elif [ -n "$new_dhcp6_domain_search" ] ||
[ -n "$new_dhcp6_name_servers" ]; then
87 rm -f $new_resolv_conf
89 if [ -n "$new_dhcp6_domain_search" ]; then
90 echo "search ${new_dhcp6_domain_search}" >> $new_resolv_conf
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}"
100 echo nameserver
$nameserver >>$new_resolv_conf
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
106 if [ -f "$resolv_conf" ]; then
107 chown
--reference=$resolv_conf $new_resolv_conf
108 chmod --reference=$resolv_conf $new_resolv_conf
110 mv -f $new_resolv_conf $resolv_conf
116 local current_hostname
118 if [ -n "$new_host_name" ]; then
119 current_hostname
=$
(hostname
)
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"
133 # Execute the operation
138 MEDIUM|ARPCHECK|ARPSEND
)
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)
146 # ensure interface is up
147 ${ip} link
set dev
${interface} up
149 if [ -n "$alias_ip_address" ]; then
150 # flush alias IP from interface
151 ${ip} -4 addr flush dev ${interface} label ${interface}:0
156 BOUND|RENEW|REBIND|REBOOT
)
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
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}
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}
179 if [ -n "$new_interface_mtu" ]; then
181 ${ip} link set dev ${interface} mtu ${new_interface_mtu}
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}
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
200 ${ip} -4 route add default via ${router} dev ${interface} \
201 ${if_metric:+metric $if_metric} >/dev
/null
2>&1
203 if [ -n "$if_metric" ]; then
204 if_metric
=$
((if_metric
+1))
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
220 # update /etc/resolv.conf
225 EXPIRE|FAIL|RELEASE|STOP
)
226 if [ -n "$alias_ip_address" ]; then
228 ${ip} -4 addr flush dev ${interface} label ${interface}:0
231 if [ -n "$old_ip_address" ]; then
233 ${ip} -4 addr flush dev ${interface} label ${interface}
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
246 if [ -n "$alias_ip_address" ]; then
248 ${ip} -4 addr flush dev ${interface} label ${interface}:0
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}
256 if [ -n "$new_interface_mtu" ]; then
258 ${ip} link set dev ${interface} mtu ${new_interface_mtu}
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
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
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}
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
286 if [ -n "$if_metric" ]; then
287 if_metric
=$
((if_metric
+1))
292 # update /etc/resolv.conf
295 # flush all IPs from interface
296 ${ip} -4 addr flush dev
${interface}
303 # TODO handle prefix change: ?based on ${old_ip6_prefix} and ${new_ip6_prefix}?
306 # ensure interface is up
307 ${ip} link
set ${interface} up
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})
313 ${ip} addr show
${interface} |
grep NO-CARRIER
>/dev
/null
2>&1
314 if [ $?
-ne 0 ]; then
320 # flush any stale global permanent IPs from interface
321 ${ip} -6 addr flush dev
${interface} scope global permanent
323 # Wait for duplicate address detection for this interface if the
324 # --dad-wait-time parameter has been specified and is greater than
326 if [ ${dad_wait_time} -gt 0 ]; then
327 # Check if any IPv6 address on this interface is marked as
329 ${ip} addr show
${interface} |
grep inet6 |
grep tentative \
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)
336 # We're going to poll for the tentative flag every second.
338 ${ip} addr show
${interface} |
grep inet6 |
grep tentative \
340 if [ $?
-ne 0 ]; then
349 BOUND6|RENEW6|REBIND6
)
350 if [ "${new_ip6_address}" ] && [ "${new_ip6_prefixlen}" ]; then
352 ${ip} -6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \
353 dev
${interface} scope global
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
366 if [ -z "${cur_ip6_prefixlen}" ]; then
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
376 EXPIRE6|RELEASE6|STOP6
)
377 if [ -z "${old_ip6_address}" ] ||
[ -z "${old_ip6_prefixlen}" ]; then
382 ${ip} -6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \