return -1;
}
+static void
+dhcp6_start1(void *arg)
+{
+ struct interface *ifp = arg;
+ struct dhcp6_state *state;
+
+ state = D6_STATE(ifp);
+ syslog(LOG_INFO, "%s: %s", ifp->name,
+ state->state == DH6S_INFORM ?
+ "requesting DHCPv6 information" :
+ "soliciting a DHCPv6 address");
+ if (state->state == DH6S_INFORM)
+ dhcp6_startinform(ifp);
+ else
+ dhcp6_startinit(ifp);
+}
+
int
-dhcp6_start(struct interface *ifp, int manage)
+dhcp6_start(struct interface *ifp, int init_state)
{
struct dhcp6_state *state;
if (dhcp6_find_delegates(ifp))
return 0;
- syslog(LOG_INFO, "%s: %s", ifp->name,
- manage ? "soliciting a DHCPv6 address" :
- "requesting DHCPv6 information");
-
- state->state = manage ? DH6S_INIT : DH6S_INFORM;
+ state->state = init_state;
snprintf(state->leasefile, sizeof(state->leasefile),
LEASEFILE6, ifp->name);
- if (state->state == DH6S_INFORM)
- dhcp6_startinform(ifp);
- else
- dhcp6_startinit(ifp);
+ if (ipv6_linklocal(ifp) == NULL) {
+ syslog(LOG_DEBUG,
+ "%s: delaying DHCPv6 soliciation for LL address",
+ ifp->name);
+ ipv6_addlinklocalcallback(ifp, dhcp6_start1, ifp);
+ return 0;
+ }
- return 1;
+ dhcp6_start1(ifp);
+ return 0;
}
static void
if (!(ifo->options & DHCPCD_IPV6RS)) {
if (ifo->options & DHCPCD_IA_FORCED)
- nolease = dhcp6_start(ifp, 1);
+ nolease = dhcp6_start(ifp, DH6S_INIT);
else {
nolease = dhcp6_find_delegates(ifp);
/* Enabling the below doesn't really make
/* With no RS or delegates we might
* as well try and solicit a DHCPv6 address */
if (nolease == 0)
- nolease = dhcp6_start(ifp, 1);
+ nolease = dhcp6_start(ifp, DH6S_INIT);
#endif
}
if (nolease == -1)
handle_flag:
if (rap->flags & ND_RA_FLAG_MANAGED) {
- if (dhcp6_start(ifp, 1) == -1)
+ if (dhcp6_start(ifp, DH6S_INIT) == -1)
syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
} else if (rap->flags & ND_RA_FLAG_OTHER) {
- if (dhcp6_start(ifp, 0) == -1)
+ if (dhcp6_start(ifp, DH6S_INFORM) == -1)
syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
} else {
if (new_data)