If a interface does not have a link-local address, dhclient -6 <ifname> will fail. The built-in "wait for link-local address" loop does not function properly, causing DHCP failure.
Discussion:
===========
In trying to configure isc-dhcp-client 4.3.5-3ubuntu1 for IPv6 on Ubuntu 17.04, I was finding that on boot I was getting failures with the logged message "no link-local IPv6 address for <ifname>"
I found that it took several seconds for the link-local address to be assigned when the interface came up (in this case, the ISP/modem-facing interface), and worked around it with a script that looks at
Summary:
========
If a interface does not have a link-local address, dhclient -6 <ifname> will fail. The built-in "wait for link-local address" loop does not function properly, causing DHCP failure.
Discussion:
===========
In trying to configure isc-dhcp-client 4.3.5-3ubuntu1 for IPv6 on Ubuntu 17.04, I was finding that on boot I was getting failures with the logged message "no link-local IPv6 address for <ifname>"
I found that it took several seconds for the link-local address to be assigned when the interface came up (in this case, the ISP/modem-facing interface), and worked around it with a script that looks at
/sbin/ifconfig $IFACE | /bin/fgrep -q 'scopeid 0x20'
and loops for a fixed number of times for that to be successful.
On looking at /sbin/dhclient- script it appears that it *tries* to do the same thing in
# set the link up and wait for ipv6 link local dad to finish link_up_ and_dad( )
ipv6_
this code sets
out=$(ip -6 -o address show dev "$dev" scope link)
then checks it with a case statement inside of a loop for
case " $out " in
error "$dev: ipv6 dad failed."
return 1;;
*\ dadfailed\ *)
*\ tentative\ *) :;;
*) return 0;;
esac
If there is no link-local address, $out will be empty. The default case is taken, and the loop exits immediately:
$ echo "'$out'" ; case " $out " in
> *\ dadfailed\ *)
> echo "dadfailed"
> ;;
> *\ tentative\ *)
> echo "tentative"
> ;;
> *)
> echo "default"
> esac
''
default
As a result, there is no "wait for link-local address" and when there is no link-local address, dhclient fails later on.
Possible Fix:
=============
Adding "the missing case" for "no address" case that continues the loop is one possible solution.
case " $out " in
error "$dev: ipv6 dad failed."
return 1;;
*\ dadfailed\ *)
*\ tentative\ *) :;;
" ")
:
;;
*) return 0;;
esac
At least in my situation, this prevents the failure of dhclient due to the link-local address not being "ready" yet.