Comment 0 for bug 1718568

Revision history for this message
Jeff (jeffsf) wrote :

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
  ipv6_link_up_and_dad()

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
            *\ dadfailed\ *)
                error "$dev: ipv6 dad failed."
                return 1;;
            *\ 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
            *\ dadfailed\ *)
                error "$dev: ipv6 dad failed."
                return 1;;
            *\ 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.