Module Name: src Committed By: roy Date: Wed Sep 4 13:28:57 UTC 2019
Modified Files: src/external/bsd/dhcpcd/dist/src: dhcp.c dhcp6.c dhcpcd.8.in dhcpcd.c if-bsd.c ipv6.c ipv6.h ipv6nd.c Log Message: Sync To generate a diff of this commit: cvs rdiff -u -r1.24 -r1.25 src/external/bsd/dhcpcd/dist/src/dhcp.c \ src/external/bsd/dhcpcd/dist/src/dhcpcd.c cvs rdiff -u -r1.11 -r1.12 src/external/bsd/dhcpcd/dist/src/dhcp6.c \ src/external/bsd/dhcpcd/dist/src/if-bsd.c cvs rdiff -u -r1.2 -r1.3 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in cvs rdiff -u -r1.3 -r1.4 src/external/bsd/dhcpcd/dist/src/ipv6.c cvs rdiff -u -r1.4 -r1.5 src/external/bsd/dhcpcd/dist/src/ipv6.h cvs rdiff -u -r1.10 -r1.11 src/external/bsd/dhcpcd/dist/src/ipv6nd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/dhcpcd/dist/src/dhcp.c diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.24 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.25 --- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.24 Wed Aug 21 17:12:19 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcp.c Wed Sep 4 13:28:56 2019 @@ -1176,11 +1176,8 @@ read_lease(struct interface *ifp, struct bytes = dhcp_read_lease_fd(fd, (void **)&lease); if (fd_opened) close(fd); - if (bytes == 0) { - free(lease); - logerr("%s: dhcp_read_lease_fd", __func__); + if (bytes == 0) return 0; - } /* Ensure the packet is at lease BOOTP sized * with a vendor area of 4 octets @@ -1584,7 +1581,7 @@ eexit: } static uint16_t -in_cksum(void *data, size_t len, uint32_t *isum) +in_cksum(const void *data, size_t len, uint32_t *isum) { const uint16_t *word = data; uint32_t sum = isum != NULL ? *isum : 0; @@ -1593,7 +1590,7 @@ in_cksum(void *data, size_t len, uint32_ sum += *word++; if (len == 1) - sum += *(const uint8_t *)word; + sum += htons((uint16_t)(*(const uint8_t *)word << 8)); if (isum != NULL) *isum = sum; @@ -2237,7 +2234,7 @@ dhcp_bind(struct interface *ifp) ipv4_applyaddr(ifp); #ifdef IP_PKTINFO - /* Close the BPF filter as we can now receive the DHCP renew messages + /* Close the BPF filter as we can now receive DHCP messages * on a UDP socket. */ if (state->udp_fd == -1 || (state->old != NULL && state->old->yiaddr != state->new->yiaddr)) @@ -2246,9 +2243,15 @@ dhcp_bind(struct interface *ifp) /* If not in master mode, open an address specific socket. */ if (ctx->udp_fd == -1) { state->udp_fd = dhcp_openudp(ifp); - if (state->udp_fd == -1) + if (state->udp_fd == -1) { logerr(__func__); - else + /* Address sharing without master mode is + * not supported. It's also possible another + * DHCP client could be running which is + * even worse. + * We still need to work, so re-open BPF. */ + dhcp_openbpf(ifp); + } else eloop_event_add(ctx->eloop, state->udp_fd, dhcp_handleifudp, ifp); } @@ -3293,7 +3296,8 @@ valid_udp_packet(void *packet, size_t pl pseudo_ip.ip_len = udp->uh_ulen; csum = 0; in_cksum(&pseudo_ip, sizeof(pseudo_ip), &csum); - if (in_cksum(udp, ntohs(udp->uh_ulen), &csum) != uh_sum) { + csum = in_cksum(udp, ntohs(udp->uh_ulen), &csum); + if (csum != uh_sum) { errno = EINVAL; return -1; } @@ -3662,6 +3666,7 @@ static void dhcp_start1(void *arg) { struct interface *ifp = arg; + struct dhcpcd_ctx *ctx = ifp->ctx; struct if_options *ifo = ifp->options; struct dhcp_state *state; struct stat st; @@ -3672,17 +3677,19 @@ dhcp_start1(void *arg) return; /* Listen on *.*.*.*:bootpc so that the kernel never sends an - * ICMP port unreachable message back to the DHCP server */ - if (ifp->ctx->udp_fd == -1) { - ifp->ctx->udp_fd = dhcp_openudp(NULL); - if (ifp->ctx->udp_fd == -1) { + * ICMP port unreachable message back to the DHCP server. + * Only do this in master mode so we don't swallow messages + * for dhcpcd running on another interface. */ + if (ctx->udp_fd == -1 && ctx->options & DHCPCD_MASTER) { + ctx->udp_fd = dhcp_openudp(NULL); + if (ctx->udp_fd == -1) { /* Don't log an error if some other process * is handling this. */ if (errno != EADDRINUSE) logerr("%s: dhcp_openudp", __func__); } else - eloop_event_add(ifp->ctx->eloop, - ifp->ctx->udp_fd, dhcp_handleudp, ifp->ctx); + eloop_event_add(ctx->eloop, + ctx->udp_fd, dhcp_handleudp, ctx); } if (dhcp_init(ifp) == -1) { Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.24 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.25 --- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.24 Wed Aug 21 17:12:19 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c Wed Sep 4 13:28:56 2019 @@ -950,12 +950,7 @@ dhcpcd_prestartinterface(void *arg) if ((!(ifp->ctx->options & DHCPCD_MASTER) || ifp->options->options & DHCPCD_IF_UP) && - if_up(ifp) == -1 -#ifdef __sun - /* Interface could not yet be plumbed. */ - && errno != ENXIO -#endif - ) + if_up(ifp) == -1) logerr("%s: %s", __func__, ifp->name); dhcpcd_startinterface(ifp); Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.11 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.12 --- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.11 Tue Jul 30 10:25:03 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcp6.c Wed Sep 4 13:28:56 2019 @@ -2488,22 +2488,22 @@ dhcp6_readlease(struct interface *ifp, i struct dhcp6_state *state; struct stat st; int fd; - struct dhcp6_message *lease; time_t now; int retval; - bool fd_opened; + bool read_stdin, fd_opened; #ifdef AUTH uint8_t *o; uint16_t ol; #endif state = D6_STATE(ifp); - if (state->leasefile[0] == '\0') { + read_stdin = state->leasefile[0] == '\0'; + if (read_stdin) { logdebugx("reading standard input"); fd = fileno(stdin); fd_opened = false; } else { - logdebugx("%s: reading lease `%s'", ifp->name, state->leasefile); + logdebugx("%s: reading lease `%s'", ifp->name,state->leasefile); fd = open(state->leasefile, O_RDONLY); if (fd != -1 && fstat(fd, &st) == -1) { close(fd); @@ -2514,19 +2514,19 @@ dhcp6_readlease(struct interface *ifp, i if (fd == -1) return -1; retval = -1; - lease = NULL; free(state->new); - state->new_len = dhcp_read_lease_fd(fd, (void **)&lease); - state->new = lease; + state->new_len = dhcp_read_lease_fd(fd, (void **)&state->new); if (fd_opened) close(fd); - if (state->new_len == 0) - goto ex; - if (ifp->ctx->options & DHCPCD_DUMPLEASE || - state->leasefile[0] == '\0') + if (ifp->ctx->options & DHCPCD_DUMPLEASE || read_stdin) return 0; + if (state->new_len == 0) { + retval = 0; + goto ex; + } + /* If not validating IA's and if they have expired, * skip to the auth check. */ if (!validate) { @@ -2546,14 +2546,12 @@ dhcp6_readlease(struct interface *ifp, i goto ex; if (state->expire != ND6_INFINITE_LIFETIME && - state->leasefile[0] != '\0') + (time_t)state->expire < now - st.st_mtime && + !(ifp->options->options & DHCPCD_LASTLEASE_EXTEND)) { - if ((time_t)state->expire < now - st.st_mtime && - !(ifp->options->options & DHCPCD_LASTLEASE_EXTEND)) { - logdebugx("%s: discarding expired lease", ifp->name); - retval = 0; - goto ex; - } + logdebugx("%s: discarding expired lease", ifp->name); + retval = 0; + goto ex; } auth: @@ -2586,12 +2584,10 @@ auth: ex: dhcp6_freedrop_addrs(ifp, 0, NULL); + unlink(state->leasefile); free(state->new); state->new = NULL; state->new_len = 0; - if (!(ifp->ctx->options & DHCPCD_DUMPLEASE) && - state->leasefile[0] != '\0') - unlink(state->leasefile); return retval; } Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.11 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.12 --- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.11 Wed Aug 21 17:12:19 2019 +++ src/external/bsd/dhcpcd/dist/src/if-bsd.c Wed Sep 4 13:28:56 2019 @@ -141,7 +141,7 @@ if_opensockets_os(struct dhcpcd_ctx *ctx #ifdef RTM_IFANNOUNCE RTM_IFANNOUNCE, #endif - RTM_ADD, RTM_CHANGE, RTM_DELETE, + RTM_ADD, RTM_CHANGE, RTM_DELETE, RTM_MISS, #ifdef RTM_CHGADDR RTM_CHGADDR, #endif @@ -639,7 +639,11 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct { const struct sockaddr *rti_info[RTAX_MAX]; - if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) { + if (!(rtm->rtm_addrs & RTA_DST)) { + errno = EINVAL; + return -1; + } + if (rtm->rtm_type != RTM_MISS && !(rtm->rtm_addrs & RTA_GATEWAY)) { errno = EINVAL; return -1; } @@ -674,12 +678,24 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct if (rt->rt_netmask.sa_family == 255) /* Why? */ rt->rt_netmask.sa_family = rt->rt_dest.sa_family; } - /* dhcpcd likes an unspecified gateway to indicate via the link. */ - if (rt->rt_flags & RTF_GATEWAY && - rti_info[RTAX_GATEWAY]->sa_family != AF_LINK) - if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]); + + /* dhcpcd likes an unspecified gateway to indicate via the link. + * However we need to know if gateway was a link with an address. */ + if (rtm->rtm_addrs & RTA_GATEWAY) { + if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) { + const struct sockaddr_dl *sdl; + + sdl = (const struct sockaddr_dl*) + (const void *)rti_info[RTAX_GATEWAY]; + if (sdl->sdl_alen != 0) + rt->rt_dflags |= RTDF_GATELINK; + } else if (rtm->rtm_flags & RTF_GATEWAY) + if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]); + } + if (rtm->rtm_addrs & RTA_IFA) if_copysa(&rt->rt_ifa, rti_info[RTAX_IFA]); + rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu; if (rtm->rtm_index) @@ -691,6 +707,9 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct else rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_DST]); + if (rt->rt_ifp == NULL && rtm->rtm_type == RTM_MISS) + rt->rt_ifp = if_find(ctx->ifaces, "lo0"); + if (rt->rt_ifp == NULL) { errno = ESRCH; return -1; @@ -1070,30 +1089,30 @@ if_rtm(struct dhcpcd_ctx *ctx, const str return 0; if (if_copyrt(ctx, &rt, rtm) == -1) - return -1; + return errno == ENOTSUP ? 0 : -1; #ifdef INET6 /* * BSD announces host routes. * As such, we should be notified of reachability by its * existance with a hardware address. + * Ensure we don't call this for a newly incomplete state. */ - if (rt.rt_dest.sa_family == AF_INET6 && rt.rt_flags & RTF_HOST) { - struct sockaddr_in6 dest; - struct sockaddr_dl sdl; + if (rt.rt_dest.sa_family == AF_INET6 && + (rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) && + !(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK))) + { + bool reachable; - memcpy(&dest, &rt.rt_dest, rt.rt_dest.sa_len); - if (rt.rt_gateway.sa_family == AF_LINK) - memcpy(&sdl, &rt.rt_gateway, rt.rt_gateway.sa_len); - else - sdl.sdl_alen = 0; - ipv6nd_neighbour(ctx, &dest.sin6_addr, - rtm->rtm_type != RTM_DELETE && sdl.sdl_alen ? - IPV6ND_REACHABLE : 0); + reachable = (rtm->rtm_type == RTM_ADD || + rtm->rtm_type == RTM_CHANGE) && + rt.rt_dflags & RTDF_GATELINK; + ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable); } #endif - rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid); + if (rtm->rtm_type != RTM_MISS) + rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid); return 0; } @@ -1299,7 +1318,8 @@ if_dispatch(struct dhcpcd_ctx *ctx, cons return if_ifinfo(ctx, (const void *)rtm); case RTM_ADD: /* FALLTHROUGH */ case RTM_CHANGE: /* FALLTHROUGH */ - case RTM_DELETE: + case RTM_DELETE: /* FALLTHROUGH */ + case RTM_MISS: return if_rtm(ctx, (const void *)rtm); #ifdef RTM_CHGADDR case RTM_CHGADDR: /* FALLTHROUGH */ Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.2 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.3 --- src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.2 Fri Jul 26 10:39:29 2019 +++ src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in Wed Sep 4 13:28:56 2019 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 25, 2019 +.Dd August 28, 2019 .Dt DHCPCD 8 .Os .Sh NAME @@ -71,7 +71,7 @@ .Fl k , Fl Fl release .Op interface .Nm -.Fl U, Fl Fl dumplease +.Fl U , Fl Fl dumplease .Ar interface .Nm .Fl Fl version @@ -260,7 +260,7 @@ otheriwse if persistent storage is avail (link local address + time) is generated, otherwise DUID-LL is generated (link local address). This, plus the IAID will be used as the -.Fl I, Fl Fl clientid . +.Fl I , Fl Fl clientid . The DUID generated will be held in .Pa @DBDIR@/duid and should not be copied to other hosts. @@ -470,7 +470,7 @@ This option is only needed when .Nm is not processing IPv6RA messages and the need for DHCPv6 Information Request exists. -.It Fl S, Fl Fl static Ar value +.It Fl S , Fl Fl static Ar value Configures a static DHCP .Ar value . If you set @@ -660,7 +660,7 @@ Quiet .Nm on the command line, only warnings and errors will be displayed. The messages are still logged though. -.It Fl T, Fl Fl test +.It Fl T , Fl Fl test On receipt of DHCP messages just call .Pa @SCRIPT@ with the reason of TEST which echos the DHCP variables found in the message @@ -673,7 +673,7 @@ option is not sent in TEST mode so that To test INFORM the interface needs to be configured with the desired address before starting .Nm . -.It Fl U, Fl Fl dumplease Ar interface +.It Fl U , Fl Fl dumplease Ar interface Dumps the last lease for the .Ar interface to stdout. @@ -683,20 +683,20 @@ Use the or .Fl 6 flags to specify an address family. -.It Fl V, Fl Fl variables +.It Fl V , Fl Fl variables Display a list of option codes, the associated variable and encoding for use in .Xr dhcpcd-run-hooks 8 . Variables are prefixed with new_ and old_ unless the option number is -. Variables without an option are part of the DHCP message and cannot be directly requested. -.It Fl W, Fl Fl whitelist Ar address Ns Op /cidr +.It Fl W , Fl Fl whitelist Ar address Ns Op /cidr Only accept packets from .Ar address Ns Op /cidr . -.Fl X, Fl Fl blacklist +.Fl X , Fl Fl blacklist is ignored if -.Fl W, Fl Fl whitelist +.Fl W , Fl Fl whitelist is set. -.It Fl X, Fl Fl blacklist Ar address Ns Op Ar /cidr +.It Fl X , Fl Fl blacklist Ar address Ns Op Ar /cidr Ignore all packets from .Ar address Ns Op Ar /cidr . .It Fl Z , Fl Fl denyinterfaces Ar pattern @@ -771,6 +771,7 @@ If you always use the same options, put .It Pa @SCRIPT@ Bourne shell script that is run to configure or de-configure an interface. .It Pa @LIBDIR@/dhcpcd/dev +Linux .Pa /dev management modules. .It Pa @HOOKDIR@ @@ -818,7 +819,7 @@ Control socket to per interface daemon. .Xr dhcpcd-run-hooks 8 , .Xr resolvconf 8 .Sh STANDARDS -RFC\ 951, RFC\ 1534, RFC\ 2104, RFC\ 2131, RFC\ 2132, RFC\ 2563, RFC\ 2855, +RFC\ 951, RFC\ 1534, RFC\ 2104, RFC\ 2131, RFC\ 2132, RFC\ 2563, RFC\ 2855, RFC\ 3004, RFC\ 3118, RFC\ 3203, RFC\ 3315, RFC\ 3361, RFC\ 3633, RFC\ 3396, RFC\ 3397, RFC\ 3442, RFC\ 3495, RFC\ 3925, RFC\ 3927, RFC\ 4039, RFC\ 4075, RFC\ 4242, RFC\ 4361, RFC\ 4390, RFC\ 4702, RFC\ 4074, RFC\ 4861, RFC\ 4833, Index: src/external/bsd/dhcpcd/dist/src/ipv6.c diff -u src/external/bsd/dhcpcd/dist/src/ipv6.c:1.3 src/external/bsd/dhcpcd/dist/src/ipv6.c:1.4 --- src/external/bsd/dhcpcd/dist/src/ipv6.c:1.3 Tue Jul 30 10:25:03 2019 +++ src/external/bsd/dhcpcd/dist/src/ipv6.c Wed Sep 4 13:28:56 2019 @@ -629,7 +629,7 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons uint32_t pltime, vltime; __printflike(1, 2) void (*logfunc)(const char *, ...); #ifdef ND6_ADVERTISE - bool vltime_was_zero; + bool vltime_was_zero = ia->prefix_vltime == 0; #endif #ifdef __sun struct ipv6_state *state; @@ -641,7 +641,11 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons if (ia->flags & IPV6_AF_DADCOMPLETED) { logdebugx("%s: IP address %s already exists", ia->iface->name, ia->saddr); +#ifdef ND6_ADVERTISE + goto advertise; +#else return 0; +#endif } #endif @@ -707,9 +711,6 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons " seconds", ifp->name, ia->prefix_pltime, ia->prefix_vltime); -#ifdef ND6_ADVERTISE - vltime_was_zero = ia->prefix_vltime == 0; -#endif if (if_address6(RTM_NEWADDR, ia) == -1) { logerr(__func__); /* Restore real pltime and vltime */ @@ -774,6 +775,9 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons #endif #ifdef ND6_ADVERTISE +#ifdef __sun +advertise: +#endif /* Re-advertise the preferred address to be safe. */ if (!vltime_was_zero) ipv6nd_advertise(ia); @@ -1060,6 +1064,31 @@ ipv6_getstate(struct interface *ifp) return state; } +struct ipv6_addr * +ipv6_ifanyglobal(struct interface *ifp) +{ + struct ipv6_state *state; + struct ipv6_addr *ia; + + if (ifp->carrier == LINK_DOWN) + return NULL; + + state = IPV6_STATE(ifp); + if (state == NULL) + return NULL; + + TAILQ_FOREACH(ia, &state->addrs, next) { + if (IN6_IS_ADDR_LINKLOCAL(&ia->addr)) + continue; + /* Let's be optimistic. + * Any decent OS won't forward or accept traffic + * from/to tentative or detached addresses. */ + if (!(ia->addr_flags & IN6_IFF_DUPLICATED)) + break; + } + return ia; +} + void ipv6_handleifa(struct dhcpcd_ctx *ctx, int cmd, struct if_head *ifs, const char *ifname, @@ -1069,6 +1098,22 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx, struct ipv6_state *state; struct ipv6_addr *ia; struct ll_callback *cb; + bool anyglobal; + +#ifdef __sun + struct sockaddr_in6 subnet; + + /* Solaris on-link route is an unspecified address! */ + if (IN6_IS_ADDR_UNSPECIFIED(addr)) { + if (if_getsubnet(ctx, ifname, AF_INET6, + &subnet, sizeof(subnet)) == -1) + { + logerr(__func__); + return; + } + addr = &subnet.sin6_addr; + } +#endif #if 0 char dbuf[INET6_ADDRSTRLEN]; @@ -1076,8 +1121,8 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx, dbp = inet_ntop(AF_INET6, &addr->s6_addr, dbuf, INET6_ADDRSTRLEN); - loginfox("%s: cmd %d addr %s", - ifname, cmd, dbp); + loginfox("%s: cmd %d addr %s addrflags %d", + ifname, cmd, dbp, addrflags); #endif if (ifs == NULL) @@ -1088,6 +1133,7 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx, return; if ((state = ipv6_getstate(ifp)) == NULL) return; + anyglobal = ipv6_ifanyglobal(ifp) != NULL; TAILQ_FOREACH(ia, &state->addrs, next) { if (IN6_ARE_ADDR_EQUAL(&ia->addr, addr)) @@ -1187,6 +1233,7 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx, if (ia == NULL) return; + ctx->options &= ~DHCPCD_RTBUILD; ipv6nd_handleifa(cmd, ia, pid); #ifdef DHCP6 dhcp6_handleifa(cmd, ia, pid); @@ -1198,6 +1245,15 @@ out: ipv6_freeaddr(ia); else if (!(ia->addr_flags & IN6_IFF_NOTUSEABLE)) ia->flags |= IPV6_AF_DADCOMPLETED; + + /* If we've not already called rt_build via the IPv6ND + * or DHCP6 handlers and the existance of any useable + * global address on the interface has changed, + * call rt_build to add/remove the default route. */ + if (ifp->active && ifp->options->options & DHCPCD_IPV6 && + !(ctx->options & DHCPCD_RTBUILD) && + (ipv6_ifanyglobal(ifp) != NULL) != anyglobal) + rt_build(ctx, AF_INET6); } int @@ -1498,7 +1554,13 @@ ipv6_newaddr(struct interface *ifp, cons goto err; } else if (ia->flags & IPV6_AF_RAPFX) { ia->prefix = *addr; +#ifdef __sun + ia->addr = *addr; + cbp = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf)); + goto paddr; +#else return ia; +#endif } else if (ia->flags & (IPV6_AF_REQUEST | IPV6_AF_DELEGATEDPFX) && prefix_len != 128) { @@ -2273,6 +2335,8 @@ inet6_raroutes(rb_tree_t *routes, struct } if (rap->lifetime == 0) continue; + if (ipv6_ifanyglobal(rap->iface) == NULL) + continue; rt = inet6_makerouter(rap); if (rt == NULL) continue; Index: src/external/bsd/dhcpcd/dist/src/ipv6.h diff -u src/external/bsd/dhcpcd/dist/src/ipv6.h:1.4 src/external/bsd/dhcpcd/dist/src/ipv6.h:1.5 --- src/external/bsd/dhcpcd/dist/src/ipv6.h:1.4 Wed Aug 21 17:12:19 2019 +++ src/external/bsd/dhcpcd/dist/src/ipv6.h Wed Sep 4 13:28:56 2019 @@ -110,9 +110,9 @@ * While it supports DaD, to seems to only expose IFF_DUPLICATE * so we have no way of knowing if it's tentative or not. * I don't even know if Solaris has any special treatment for tentative. */ -# define IN6_IFF_TENTATIVE 0 +# define IN6_IFF_TENTATIVE 0x02 # define IN6_IFF_DUPLICATED 0x04 -# define IN6_IFF_DETACHED 0 +# define IN6_IFF_DETACHED 0x00 #endif #define IN6_IFF_NOTUSEABLE \ @@ -159,7 +159,7 @@ #if !defined(SMALL) && \ ((defined(__DragonFly_version) && __DragonFly_version >= 500703) || \ (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 899002800) || \ - defined(__linux__)) + defined(__linux__) || defined(__sun)) # define ND6_ADVERTISE #endif @@ -273,6 +273,7 @@ int ipv6_handleifa_addrs(int, struct ipv struct ipv6_addr *ipv6_iffindaddr(struct interface *, const struct in6_addr *, int); int ipv6_hasaddr(const struct interface *); +struct ipv6_addr *ipv6_ifanyglobal(struct interface *); int ipv6_findaddrmatch(const struct ipv6_addr *, const struct in6_addr *, unsigned int); struct ipv6_addr *ipv6_findaddr(struct dhcpcd_ctx *, Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.10 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.11 --- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.10 Tue Jul 30 10:25:03 2019 +++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c Wed Sep 4 13:28:56 2019 @@ -217,7 +217,6 @@ ipv6nd_open0(void) goto eexit; ICMP6_FILTER_SETBLOCKALL(&filt); - ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt); ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt); if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt)) == -1) @@ -460,6 +459,11 @@ ipv6nd_advertise(struct ipv6_addr *ia) if (IN6_IS_ADDR_MULTICAST(&ia->addr)) return; +#ifdef __sun + if (!(ia->flags & IPV6_AF_AUTOCONF) && ia->flags & IPV6_AF_RAPFX) + return; +#endif + ctx = ia->iface->ctx; /* Find the most preferred address to advertise. */ iaf = NULL; @@ -555,45 +559,60 @@ ipv6nd_startexpire(struct interface *ifp ipv6nd_expire, ifp); } -static void -ipv6nd_reachable(struct ra *rap, int flags) +/* + * Neighbour reachability. + * + * RFC 4681 6.2.5 says when a node is no longer a router it MUST + * send a RA with a zero lifetime. + * All OS's I know of set the NA router flag if they are a router + * or not and disregard that they are actively advertising or + * shutting down. If the interface is disabled, it cant't send a NA at all. + * + * As such we CANNOT rely on the NA Router flag and MUST use + * unreachability or receive a RA with a lifetime of zero to remove + * the node as a default router. + */ +void +ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, bool reachable) { + struct ra *rap, *rapr; + + if (ctx->ra_routers == NULL) + return; + + TAILQ_FOREACH(rap, ctx->ra_routers, next) { + if (IN6_ARE_ADDR_EQUAL(&rap->from, addr)) + break; + } - if (rap->lifetime == 0) + if (rap == NULL || rap->expired) return; - if (flags & IPV6ND_REACHABLE) { - if (rap->expired == 0) + if (reachable) { + if (rap->isreachable) return; loginfox("%s: %s is reachable again", rap->iface->name, rap->sfrom); - rap->expired = 0; + rap->isreachable = true; + return; } else { - if (rap->expired != 0) + if (!rap->isreachable) return; - logwarnx("%s: %s is unreachable, expiring it", + logwarnx("%s: %s is unreachable", rap->iface->name, rap->sfrom); - rap->expired = 1; + rap->isreachable = false; } - rt_build(rap->iface->ctx, AF_INET6); - /* XXX Not really an RA */ - script_runreason(rap->iface, "ROUTERADVERT"); -} - -void -ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, int flags) -{ - struct ra *rap; - - if (ctx->ra_routers) { - TAILQ_FOREACH(rap, ctx->ra_routers, next) { - if (IN6_ARE_ADDR_EQUAL(&rap->from, addr)) { - ipv6nd_reachable(rap, flags); - break; - } - } + /* If we have no reachable default routers, try and solicit one. */ + TAILQ_FOREACH(rapr, ctx->ra_routers, next) { + if (rap == rapr || rap->iface != rapr->iface) + continue; + if (rapr->isreachable && !rapr->expired && rapr->lifetime) + break; } + + if (rapr == NULL) + ipv6nd_startrs(rap->iface); } const struct ipv6_addr * @@ -944,7 +963,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct in6_addr pi_prefix; struct ipv6_addr *ap; struct dhcp_opt *dho; - bool new_rap, new_data; + bool new_rap, new_data, has_address; uint32_t old_lifetime; __printflike(1, 2) void (*logfunc)(const char *, ...); #ifdef IPV6_MANAGETEMPADDR @@ -1026,6 +1045,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, strlcpy(rap->sfrom, sfrom, sizeof(rap->sfrom)); TAILQ_INIT(&rap->addrs); new_rap = true; + rap->isreachable = true; } else new_rap = false; if (rap->data_len == 0) { @@ -1044,7 +1064,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, * routers like to decrease the advertised valid and preferred times * in accordance with the own prefix times which would result in too * much needless log spam. */ - logfunc = new_rap ? loginfox : logdebugx, + logfunc = new_data || !rap->isreachable ? loginfox : logdebugx, logfunc("%s: Router Advertisement from %s", ifp->name, rap->sfrom); clock_gettime(CLOCK_MONOTONIC, &rap->acquired); @@ -1064,9 +1084,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, state->retrans = rap->retrans = ntohl(nd_ra->nd_ra_retransmit); } - if (rap->lifetime) - rap->expired = 0; - rap->hasdns = 0; + rap->expired = false; + rap->hasdns = false; + rap->isreachable = true; + has_address = false; #ifdef IPV6_AF_TEMPORARY ipv6_markaddrsstale(ifp, IPV6_AF_TEMPORARY); @@ -1200,6 +1221,9 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, ntohl(pi.nd_opt_pi_valid_time); ap->prefix_pltime = ntohl(pi.nd_opt_pi_preferred_time); + if (ap->prefix_vltime != 0 && + ap->flags & IPV6_AF_AUTOCONF) + has_address = true; #ifdef IPV6_MANAGETEMPADDR /* RFC4941 Section 3.3.3 */ @@ -1266,6 +1290,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, } } + if (new_data && !has_address && rap->lifetime && !ipv6_ifanyglobal(ifp)) + logwarnx("%s: no global addresses for default route", + ifp->name); + if (new_rap) add_router(ifp->ctx, rap); @@ -1316,20 +1344,21 @@ nodhcp6: ipv6nd_expirera(ifp); } -int -ipv6nd_hasra(const struct interface *ifp) +bool +ipv6nd_hasralifetime(const struct interface *ifp, bool lifetime) { const struct ra *rap; if (ifp->ctx->ra_routers) { TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) - if (rap->iface == ifp && !rap->expired) - return 1; + if (rap->iface == ifp && !rap->expired && + (!lifetime ||rap->lifetime)) + return true; } - return 0; + return false; } -int +bool ipv6nd_hasradhcp(const struct interface *ifp) { const struct ra *rap; @@ -1338,11 +1367,11 @@ ipv6nd_hasradhcp(const struct interface TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) { if (rap->iface == ifp && !rap->expired && - (rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))) - return 1; + (rap->flags &(ND_RA_FLAG_MANAGED|ND_RA_FLAG_OTHER))) + return true; } } - return 0; + return false; } static const uint8_t * @@ -1399,7 +1428,7 @@ ipv6nd_env(FILE *fp, const struct interf clock_gettime(CLOCK_MONOTONIC, &now); i = n = 0; TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) { - if (rap->iface != ifp) + if (rap->iface != ifp || rap->expired) continue; i++; snprintf(ndprefix, sizeof(ndprefix), "nd%zu", i); @@ -1503,7 +1532,7 @@ ipv6nd_expirera(void *arg) struct interface *ifp; struct ra *rap, *ran; struct timespec now, lt, expire, next; - bool expired, valid, validone; + bool expired, valid; struct ipv6_addr *ia; size_t len, olen; uint8_t *p; @@ -1522,9 +1551,9 @@ ipv6nd_expirera(void *arg) timespecclear(&next); TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) { - if (rap->iface != ifp) + if (rap->iface != ifp || rap->expired) continue; - valid = validone = false; + valid = false; if (rap->lifetime) { lt.tv_sec = (time_t)rap->lifetime; lt.tv_nsec = 0; @@ -1533,8 +1562,8 @@ ipv6nd_expirera(void *arg) if (!rap->expired) { logwarnx("%s: %s: router expired", ifp->name, rap->sfrom); - rap->expired = expired = 1; rap->lifetime = 0; + expired = true; } } else { valid = true; @@ -1552,7 +1581,7 @@ ipv6nd_expirera(void *arg) if (ia->prefix_vltime == 0) continue; if (ia->prefix_vltime == ND6_INFINITE_LIFETIME) { - validone = true; + valid = true; continue; } lt.tv_sec = (time_t)ia->prefix_vltime; @@ -1576,7 +1605,7 @@ ipv6nd_expirera(void *arg) if (!timespecisset(&next) || timespeccmp(&next, <, >)) next = lt; - validone = true; + valid = true; } } @@ -1626,7 +1655,7 @@ ipv6nd_expirera(void *arg) if (ltime == 0) continue; if (ltime == ND6_INFINITE_LIFETIME) { - validone = true; + valid = true; continue; } @@ -1643,15 +1672,15 @@ ipv6nd_expirera(void *arg) timespeccmp(&next, <, >)) { next = lt; - validone = true; + valid = true; } } - if (valid || validone) + if (valid) continue; - /* Router has expired. Let's not keep a lot of them. - * We should work out if all the options have expired .... */ + /* Router has expired. Let's not keep a lot of them. */ + rap->expired = true; if (++nexpired > EXPIRED_MAX) ipv6nd_free_ra(rap); } @@ -1670,7 +1699,7 @@ void ipv6nd_drop(struct interface *ifp) { struct ra *rap, *ran; - uint8_t expired = 0; + bool expired = false; if (ifp->ctx->ra_routers == NULL) return; @@ -1678,7 +1707,7 @@ ipv6nd_drop(struct interface *ifp) eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) { if (rap->iface == ifp) { - rap->expired = expired = 1; + rap->expired = expired = true; ipv6nd_drop_ra(rap); } } @@ -1690,82 +1719,6 @@ ipv6nd_drop(struct interface *ifp) } static void -ipv6nd_handlena(struct dhcpcd_ctx *ctx, const char *sfrom, - struct interface *ifp, struct icmp6_hdr *icp, size_t len, int hoplimit) -{ - struct nd_neighbor_advert *nd_na; - struct in6_addr nd_na_target; - struct ra *rap; - uint32_t is_router, is_solicited; - char buf[INET6_ADDRSTRLEN]; - const char *taddr; - - if (ifp == NULL) { -#ifdef DEBUG_NS - logdebugx("NA for unexpected interface from %s", sfrom); -#endif - return; - } - - if ((size_t)len < sizeof(struct nd_neighbor_advert)) { - logerrx("%s: IPv6 NA too short from %s", ifp->name, sfrom); - return; - } - - /* RFC 4861 7.1.2 */ - if (hoplimit != 255) { - logerrx("invalid hoplimit(%d) in NA from %s", - hoplimit, sfrom); - return; - } - - nd_na = (struct nd_neighbor_advert *)icp; - is_router = nd_na->nd_na_flags_reserved & ND_NA_FLAG_ROUTER; - is_solicited = nd_na->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED; - taddr = inet_ntop(AF_INET6, &nd_na->nd_na_target, - buf, INET6_ADDRSTRLEN); - - /* nd_na->nd_na_target is not aligned. */ - memcpy(&nd_na_target, &nd_na->nd_na_target, sizeof(nd_na_target)); - if (IN6_IS_ADDR_MULTICAST(&nd_na_target)) { - logerrx("%s: NA multicast address %s (%s)", - ifp->name, taddr, sfrom); - return; - } - - TAILQ_FOREACH(rap, ctx->ra_routers, next) { - if (rap->iface == ifp && - IN6_ARE_ADDR_EQUAL(&rap->from, &nd_na_target)) - break; - } - if (rap == NULL) { -#ifdef DEBUG_NS - logdebugx("%s: unexpected NA from %s for %s", - ifp->name, sfrom, taddr); -#endif - return; - } - -#ifdef DEBUG_NS - logdebugx("%s: %sNA for %s from %s", - ifp->name, is_solicited ? "solicited " : "", taddr, sfrom); -#endif - - /* Node is no longer a router, so remove it from consideration */ - if (!is_router && !rap->expired) { - loginfox("%s: %s not a router (%s)", - ifp->name, taddr, sfrom); - rap->expired = 1; - rt_build(ifp->ctx, AF_INET6); - script_runreason(ifp, "ROUTERADVERT"); - return; - } - - if (is_solicited && is_router && rap->lifetime) - ipv6nd_reachable(rap, IPV6ND_REACHABLE); -} - -static void ipv6nd_handledata(void *arg) { struct dhcpcd_ctx *ctx; @@ -1828,10 +1781,6 @@ ipv6nd_handledata(void *arg) icp = (struct icmp6_hdr *)buf; if (icp->icmp6_code == 0) { switch(icp->icmp6_type) { - case ND_NEIGHBOR_ADVERT: - ipv6nd_handlena(ctx, sfrom, - ifp, icp, (size_t)len, hoplimit); - return; case ND_ROUTER_ADVERT: ipv6nd_handlera(ctx, &from, sfrom, ifp, icp, (size_t)len, hoplimit);