if (!wascompleted) {
ifp = ia->iface;
- /* If not in master mode, we need to listen on each address
- * so we can receive unicast a message. */
- if (ia->dhcp6_fd == -1 && !(ifp->ctx->options & DHCPCD_MASTER))
- dhcp6_listen(ifp->ctx, ia);
-
state = D6_STATE(ifp);
if (state->state == DH6S_BOUND ||
state->state == DH6S_DELEGATED)
}
}
-static void
-dhcp6_addaddrs(struct interface *ifp)
-{
- struct dhcp6_state *state = D6_STATE(ifp);
- struct ipv6_addr *ia;
-
- ipv6_addaddrs(&state->addrs);
-
- /* If not in master mode, we need to listen on each address
- * so we can receive unicast a message. */
- if (ifp->ctx->options & DHCPCD_MASTER)
- return;
-
- state = D6_STATE(ifp);
- TAILQ_FOREACH(ia, &state->addrs, next) {
- if (ia->prefix_vltime == 0 ||
- ia->flags & IPV6_AF_STALE ||
- ia->addr_flags & IN6_IFF_NOTUSEABLE)
- continue;
- if (ia->dhcp6_fd != -1)
- continue;
- ia->dhcp6_fd = dhcp6_listen(ifp->ctx, ia);
- if (ia->dhcp6_fd == -1)
- continue;
- eloop_event_add(ifp->ctx->eloop,
- ia->dhcp6_fd, dhcp6_recvaddr, ia);
- }
-}
-
static void
dhcp6_startexpire(void *arg)
{
break;
}
if (k && !carrier_warned) {
- dhcp6_addaddrs(ifd);
+ struct dhcp6_state *s = D6_STATE(ifd);
+
+ ipv6_addaddrs(&s->addrs);
+
/*
* Can't add routes here because that will trigger
* interface sorting which may break the current
eloop_timeout_add_sec(ifp->ctx->eloop,
(time_t)state->expire, dhcp6_startdiscover, ifp);
- dhcp6_addaddrs(ifp);
+ ipv6_addaddrs(&state->addrs);
dhcp6_deprecateaddrs(&state->addrs);
if (state->state == DH6S_INFORMED)
#ifdef BSD
sa.sin6_len = sizeof(sa);
#endif
+
if (ia != NULL) {
memcpy(&sa.sin6_addr, &ia->addr, sizeof(sa.sin6_addr));
sa.sin6_scope_id = ia->iface->index;
- }
+ } else if (!(ctx->options & DHCPCD_MASTER))
+ /* This socket is only used for sending. */
+ return s;
if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) == -1)
goto errexit;
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
&n, sizeof(n)) == -1)
goto errexit;
- }
-
- if (ia != NULL) {
+ } else {
ia->dhcp6_fd = s;
eloop_event_add(ctx->eloop, s, dhcp6_recvaddr, ia);
}
+
return s;
errexit:
static int
dhcp6_open(struct dhcpcd_ctx *ctx)
{
- struct ipv6_addr *ia = NULL;
- int s;
- if (!(ctx->options & DHCPCD_MASTER)) {
- /* Bind to the link-local address to allow more than one
- * DHCPv6 client to work. */
- struct interface *ifp;
+ /* Open an unbound socket to send from. */
+ ctx->dhcp6_fd = dhcp6_listen(ctx, NULL);
+ if (ctx->dhcp6_fd != -1 && (ctx->options & DHCPCD_MASTER))
+ eloop_event_add(ctx->eloop, ctx->dhcp6_fd, dhcp6_recvctx, ctx);
- TAILQ_FOREACH(ifp, ctx->ifaces, next) {
- if (!ifp->active)
- continue;
- ia = ipv6_linklocal(ifp);
- if (ia != NULL)
- break;
- }
- }
- s = dhcp6_listen(ctx, ia);
- ctx->dhcp6_fd = s;
- if (s != -1 && ia == NULL)
- eloop_event_add(ctx->eloop, s, dhcp6_recvctx, ctx);
-
- return s;
+ return ctx->dhcp6_fd;
}
#ifndef SMALL
{
struct dhcp6_state *state;
+ /* If not running in master mode, listen to this address */
+ if (cmd == RTM_NEWADDR &&
+ !(ia->addr_flags & IN6_IFF_NOTUSEABLE) &&
+ ia->iface->active == IF_ACTIVE_USER &&
+ !(ia->iface->ctx->options & DHCPCD_MASTER) &&
+ ia->dhcp6_fd == -1)
+ dhcp6_listen(ia->iface->ctx, ia);
+
if ((state = D6_STATE(ia->iface)) != NULL)
ipv6_handleifa_addrs(cmd, &state->addrs, ia);
}
break;
case RTM_NEWADDR:
if (ia == NULL) {
- char buf[INET6_ADDRSTRLEN];
- const char *cbp;
-
- if ((ia = calloc(1, sizeof(*ia))) == NULL) {
- logerr(__func__);
- break;
- }
+ ia = ipv6_newaddr(ifp, addr, prefix_len, 0);
#ifdef ALIAS_ADDR
strlcpy(ia->alias, ifname, sizeof(ia->alias));
#endif
- ia->iface = ifp;
- ia->addr = *addr;
- ia->prefix_len = prefix_len;
- ipv6_makeprefix(&ia->prefix, &ia->addr,
- ia->prefix_len);
- cbp = inet_ntop(AF_INET6, &addr->s6_addr,
- buf, sizeof(buf));
- if (cbp)
- snprintf(ia->saddr, sizeof(ia->saddr),
- "%s/%d", cbp, prefix_len);
if (if_getlifetime6(ia) == -1) {
/* No support or address vanished.
* Either way, just set a deprecated
}
if (ia != NULL) {
- if (!IN6_IS_ADDR_LINKLOCAL(&ia->addr)) {
- ipv6nd_handleifa(cmd, ia);
- dhcp6_handleifa(cmd, ia);
- }
+ ipv6nd_handleifa(cmd, ia);
+ dhcp6_handleifa(cmd, ia);
/* Done with the ia now, so free it. */
if (cmd == RTM_DELADDR)
}
struct ipv6_addr *
-ipv6_newaddr(struct interface *ifp, struct in6_addr *addr, uint8_t prefix_len,
- unsigned int flags)
+ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
+ uint8_t prefix_len, unsigned int flags)
{
struct ipv6_addr *ia;
char buf[INET6_ADDRSTRLEN];