From: Roy Marples Date: Wed, 4 Jun 2014 23:54:15 +0000 (+0000) Subject: Add an IPv6 link-local address before upping the interface if needed. X-Git-Tag: v6.4.0~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d05215aa288607dbf55c879b00d2c0d115764644;p=thirdparty%2Fdhcpcd.git Add an IPv6 link-local address before upping the interface if needed. Bring an interface up when we start it and not during discovery. As such, stop waiting on carrier for a second if we did. --- diff --git a/dhcpcd.c b/dhcpcd.c index c89922a3..51607657 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -569,6 +569,19 @@ dhcpcd_startinterface(void *arg) size_t i; char buf[DUID_LEN * 3]; + /* Add our link-local address before upping the interface + * so our RFC7217 address beats the hwaddr based one */ + if (ifo->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) { + syslog(LOG_ERR, "%s: ipv6_start: %m", ifp->name); + ifo->options &= DHCPCD_IPV6; + } + + if (!(ifp->flags & IFF_UP) && if_carrier(ifp) != LINK_UNKNOWN) { + if (if_up(ifp) == -1) + syslog(LOG_ERR, "%s: if_up: %m", + ifp->name); + } + if (ifp->carrier == LINK_UNKNOWN) dhcpcd_handlecarrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name); if (ifp->carrier == LINK_DOWN) { @@ -604,10 +617,6 @@ dhcpcd_startinterface(void *arg) } } - if (ifo->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) { - syslog(LOG_ERR, "%s: ipv6_start: %m", ifp->name); - ifo->options &= DHCPCD_IPV6; - } if (ifo->options & DHCPCD_IPV6) { if (ifo->options & DHCPCD_IPV6RS && !(ifo->options & DHCPCD_INFORM)) @@ -1536,25 +1545,6 @@ main(int argc, char **argv) } if (!(ctx.options & DHCPCD_BACKGROUND)) { - /* If we don't have a carrier, we may have to wait for a second - * before one becomes available if we brought an interface up */ - if (opt == 0 && - ctx.options & DHCPCD_LINK && - ctx.options & DHCPCD_WAITUP && - !(ctx.options & DHCPCD_WAITIP)) - { - ts.tv_sec = 1; - ts.tv_nsec = 0; - nanosleep(&ts, NULL); - TAILQ_FOREACH(ifp, ctx.ifaces, next) { - dhcpcd_handlecarrier(&ctx, LINK_UNKNOWN, 0, - ifp->name); - if (ifp->carrier != LINK_DOWN) { - opt = 1; - break; - } - } - } if (ctx.options & DHCPCD_MASTER) t = ifo->timeout; else if ((ifp = TAILQ_FIRST(ctx.ifaces))) diff --git a/if-options.h b/if-options.h index b5cf156a..f90e428e 100644 --- a/if-options.h +++ b/if-options.h @@ -77,7 +77,7 @@ #define DHCPCD_VENDORRAW (1ULL << 23) #define DHCPCD_TIMEOUT_IPV4LL (1ULL << 24) #define DHCPCD_WAITIP (1ULL << 25) -#define DHCPCD_WAITUP (1ULL << 26) +#define DHCPCD_SLAACPRIVATE (1ULL << 26) #define DHCPCD_CSR_WARNED (1ULL << 27) #define DHCPCD_XID_HWADDR (1ULL << 28) #define DHCPCD_BROADCAST (1ULL << 29) @@ -102,7 +102,6 @@ #define DHCPCD_IAID (1ULL << 48) #define DHCPCD_DHCP (1ULL << 49) #define DHCPCD_DHCP6 (1ULL << 50) -#define DHCPCD_SLAACPRIVATE (1ULL << 51) extern const struct option cf_options[]; diff --git a/if.c b/if.c index f4b8c7a9..7d5f3896 100644 --- a/if.c +++ b/if.c @@ -132,8 +132,8 @@ if_carrier(struct interface *iface) return r; } -static int -up_interface(struct interface *iface) +int +if_up(struct interface *ifp) { struct ifreq ifr; int s, r; @@ -144,7 +144,7 @@ up_interface(struct interface *iface) if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) return -1; memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); #ifdef __linux__ /* We can only bring the real interface up */ if ((p = strchr(ifr.ifr_name, ':'))) @@ -159,7 +159,7 @@ up_interface(struct interface *iface) if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0) r = 0; } - iface->flags = (unsigned int)ifr.ifr_flags; + ifp->flags = (unsigned int)ifr.ifr_flags; } close(s); return r; @@ -296,20 +296,6 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) strlcpy(ifp->name, p, sizeof(ifp->name)); ifp->flags = ifa->ifa_flags; - /* Bring the interface up if not already */ - if (!(ifp->flags & IFF_UP) -#ifdef SIOCGIFMEDIA - && if_carrier(ifp) != LINK_UNKNOWN -#endif - ) - { - if (up_interface(ifp) == 0) - ctx->options |= DHCPCD_WAITUP; - else - syslog(LOG_ERR, "%s: up_interface: %m", - ifp->name); - } - sdl_type = 0; /* Don't allow loopback unless explicit */ if (ifp->flags & IFF_LOOPBACK) { diff --git a/if.h b/if.h index d8e8304b..080ea07f 100644 --- a/if.h +++ b/if.h @@ -90,6 +90,7 @@ #define RAW_EOF 1 << 0 #define RAW_PARTIALCSUM 2 << 0 +int if_up(struct interface *ifp); struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *); struct interface *if_find(struct dhcpcd_ctx *, const char *); void if_free(struct interface *); diff --git a/ipv6.c b/ipv6.c index f9a79ae8..1b2300ec 100644 --- a/ipv6.c +++ b/ipv6.c @@ -31,6 +31,7 @@ #include #include +#include #include #ifdef __linux__ @@ -917,7 +918,7 @@ ipv6_addlinklocal(struct interface *ifp) switch (ifp->family) { case ARPHRD_ETHER: /* Check for a valid hardware address */ - if (ifp->hwlen != 6 & ifp->hwlen != 8) { + if (ifp->hwlen != 6 && ifp->hwlen != 8) { errno = ENOTSUP; return -1; } @@ -988,8 +989,20 @@ ipv6_addlinklocal(struct interface *ifp) int ipv6_start(struct interface *ifp) { + const struct ipv6_state *state; + const struct ipv6_addr *ap; + + state = IPV6_CSTATE(ifp); + if (state) { + TAILQ_FOREACH(ap, &state->addrs, next) { + if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) && + !(ap->addr_flags & IN6_IFF_DUPLICATED)) + break; + } + } else + ap = NULL; - if (ipv6_linklocal(ifp) == NULL && ipv6_addlinklocal(ifp) == -1) + if (ap == NULL && ipv6_addlinklocal(ifp) == -1) return -1; return 0; }