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);