2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
5 PATH
=/usr
/sbin
:/usr
/bin
:/sbin
:/bin
7 # File to start dhclient requests on different interfaces in parallel
16 # Run dhclient in parallel
21 _timeout
=$
(getarg rd.net.timeout.dhcp
=)
22 _DHCPRETRY
=$
(getargnum
1 1 1000000000 rd.net.dhcp.retry
=)
24 if [ -n "$_timeout" ]; then
25 if ! (dhclient
--help 2>&1 |
grep -q -F -- '--timeout' 2> /dev
/null
); then
26 warn
"rd.net.timeout.dhcp has no effect because dhclient does not implement the --timeout option"
31 while [ $_COUNT -lt "$_DHCPRETRY" ]; do
32 info
"Starting dhcp for interface $netif"
34 ${_timeout:+--timeout "$_timeout"} \
37 -cf /etc
/dhclient.conf \
38 -pf /tmp
/dhclient.
"$netif".pid \
39 -lf /tmp
/dhclient.
"$netif".lease \
43 # wait will return the return value of dhclient
46 # dhclient and hence wait returned success, 0.
47 if [ $retv -eq 0 ]; then
51 # If dhclient exited before wait was called, or it was killed by
52 # another thread for interface whose DHCP succeeded, then it will not
53 # find the process with that pid and return error code 127. In that
54 # case we need to check if /tmp/dhclient.$netif.lease exists. If it
55 # does, it means dhclient finished executing before wait was called,
56 # and it was successful (return 0). If /tmp/dhclient.$netif.lease
57 # does not exist, then it means dhclient was killed by another thread
58 # or it finished execution but failed dhcp on that interface.
60 if [ $retv -eq 127 ]; then
61 read -r pid
< /tmp
/dhclient.
"$netif".pid
62 info
"PID $pid was not found by wait for $netif"
63 if [ -e /tmp
/dhclient.
"$netif".lease
]; then
64 info
"PID $pid not found but DHCP successful on $netif"
69 _COUNT
=$
((_COUNT
+ 1))
70 [ $_COUNT -lt "$_DHCPRETRY" ] && sleep 1
72 warn
"dhcp for interface $netif failed"
73 # nuke those files since we failed; we might retry dhcp again if it's e.g.
74 # `ip=dhcp,dhcp6` and we check for the PID file earlier
75 rm -f /tmp
/dhclient.
"$netif".pid
/tmp
/dhclient.
"$netif".lease
83 for s
in "$dns1" "$dns2" $
(getargs nameserver
); do
84 [ -n "$s" ] ||
continue
85 echo nameserver
"$s" >> /tmp
/net.
"$netif".resolv.conf
88 if [ $ret -eq 0 ]; then
89 : > /tmp
/net.
"${netif}".up
91 if [ -z "$do_vlan" ] && [ -e /sys
/class
/net
/"${netif}"/address
]; then
92 : > "/tmp/net.$(cat /sys/class/net/"${netif}"/address).up"
95 # Check if DHCP also suceeded on another interface before this one.
96 # We will always use the first one on which DHCP succeeded, by using
97 # a commom file $IFNETFILE, to synchronize between threads.
98 # Consider the race condition in which multiple threads
99 # corresponding to different interfaces may try to read $IFNETFILE
100 # and find it does not exist; they may all end up thinking they are the
101 # first to succeed (hence more than one thread may end up writing to
102 # $IFNETFILE). To take care of this, instead of checking if $IFNETFILE
103 # exists to determine if we are the first, we create a symbolic link
104 # in $IFNETFILE, pointing to the interface name ($netif), thus storing
105 # the interface name in the link pointer.
106 # Creating a link will fail, if the link already exists, hence kernel
107 # will take care of allowing only first thread to create link, which
108 # takes care of the race condition for us. Subsequent threads will fail.
109 # Also, the link points to the interface name, which will tell us which
110 # interface succeeded.
112 if ln -s "$netif" "$IFNETFILE" 2> /dev
/null
; then
113 intf
=$
(readlink
"$IFNETFILE")
114 if [ -e /tmp
/dhclient.
"$intf".lease
]; then
115 info
"DHCP successful on interface $intf"
116 # Kill all existing dhclient calls for other interfaces, since we
117 # already got one successful interface
119 read -r npid
< /tmp
/dhclient.
"$netif".pid
120 pidlist
=$
(pgrep dhclient
)
121 for pid
in $pidlist; do
122 [ "$pid" -eq "$npid" ] && continue
123 kill -9 "$pid" > /dev
/null
2>&1
126 echo "ERROR! $IFNETFILE exists but /tmp/dhclient.$intf.lease does not exist!!!"
129 info
"DHCP success on $netif, and also on $intf"