Module Name: src
Committed By: roy
Date: Tue Jan 22 15:20:21 UTC 2019
Modified Files:
src/external/bsd/dhcpcd/dist/src: bpf.c dhcp.c dhcp6.c dhcpcd.c
if-bsd.c if-options.c ipv6nd.c
Log Message:
Sync
To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/external/bsd/dhcpcd/dist/src/bpf.c
cvs rdiff -u -r1.14 -r1.15 src/external/bsd/dhcpcd/dist/src/dhcp.c \
src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/dhcpcd/dist/src/dhcp6.c \
src/external/bsd/dhcpcd/dist/src/if-bsd.c \
src/external/bsd/dhcpcd/dist/src/ipv6nd.c
cvs rdiff -u -r1.10 -r1.11 src/external/bsd/dhcpcd/dist/src/if-options.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/bpf.c
diff -u src/external/bsd/dhcpcd/dist/src/bpf.c:1.7 src/external/bsd/dhcpcd/dist/src/bpf.c:1.8
--- src/external/bsd/dhcpcd/dist/src/bpf.c:1.7 Sat Jun 2 09:44:27 2018
+++ src/external/bsd/dhcpcd/dist/src/bpf.c Tue Jan 22 15:20:21 2019
@@ -1,6 +1,6 @@
/*
* dhcpcd: BPF arp and bootp filtering
- * Copyright (c) 2006-2018 Roy Marples <[email protected]>
+ * Copyright (c) 2006-2019 Roy Marples <[email protected]>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
Index: src/external/bsd/dhcpcd/dist/src/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.14 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.15
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.14 Sun Nov 4 16:30:28 2018
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c Tue Jan 22 15:20:21 2019
@@ -1,6 +1,6 @@
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2018 Roy Marples <[email protected]>
+ * Copyright (c) 2006-2019 Roy Marples <[email protected]>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -1604,11 +1604,6 @@ dhcp_openudp(struct interface *ifp)
n = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
goto eexit;
-#ifdef SO_RERROR
- n = 1;
- if (setsockopt(s, SOL_SOCKET, SO_RERROR, &n, sizeof(n)) == -1)
- goto eexit;
-#endif
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(BOOTPC);
@@ -2636,6 +2631,7 @@ dhcp_reboot(struct interface *ifp)
* interface gets the reply. */
ia = ipv4_iffindaddr(ifp, &state->lease.addr, NULL);
if (ia != NULL &&
+ !(ifp->ctx->options & DHCPCD_TEST) &&
#ifdef IN_IFF_NOTUSEABLE
!(ia->addr_flags & IN_IFF_NOTUSEABLE) &&
#endif
Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.14 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.15
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.14 Mon Aug 27 13:43:05 2018
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c Tue Jan 22 15:20:21 2019
@@ -1,6 +1,6 @@
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2018 Roy Marples <[email protected]>
+ * Copyright (c) 2006-2019 Roy Marples <[email protected]>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
* SUCH DAMAGE.
*/
-const char dhcpcd_copyright[] = "Copyright (c) 2006-2018 Roy Marples";
+const char dhcpcd_copyright[] = "Copyright (c) 2006-2019 Roy Marples";
#include <sys/file.h>
#include <sys/socket.h>
@@ -314,13 +314,6 @@ dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
return 0;
}
- /* Store the pid and routing message seq number so we can identify
- * the last message successfully sent to the kernel.
- * This allows us to ignore all messages we sent after forking
- * and detaching. */
- ctx->ppid = getpid();
- ctx->pseq = ctx->sseq;
-
switch (pid = fork()) {
case -1:
logerr("%s: fork", __func__);
@@ -451,6 +444,10 @@ configure_interface1(struct interface *i
ifo->options &=
~(DHCPCD_IPV6RS | DHCPCD_DHCP6 | DHCPCD_WAITIP6);
+ if (!(ifo->options & DHCPCD_IPV6RS))
+ ifo->options &=
+ ~(DHCPCD_IPV6RA_AUTOCONF | DHCPCD_IPV6RA_REQRDNSS);
+
/* We want to setup INET6 on the interface as soon as possible. */
if (ifp->active == IF_ACTIVE_USER &&
ifo->options & DHCPCD_IPV6 &&
@@ -738,6 +735,7 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
#endif
dhcp_abort(ifp);
ipv6nd_expire(ifp, 0);
+ dhcp6_abort(ifp);
#else
dhcpcd_drop(ifp, 0);
#endif
@@ -754,19 +752,21 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
#endif
if (ifp->wireless) {
uint8_t ossid[IF_SSIDLEN];
-#ifdef NOCARRIER_PRESERVE_IP
size_t olen;
olen = ifp->ssid_len;
-#endif
memcpy(ossid, ifp->ssid, ifp->ssid_len);
if_getssid(ifp);
-#ifdef NOCARRIER_PRESERVE_IP
+
/* If we changed SSID network, drop leases */
if (ifp->ssid_len != olen ||
memcmp(ifp->ssid, ossid, ifp->ssid_len))
+ {
+#ifdef NOCARRIER_PRESERVE_IP
dhcpcd_drop(ifp, 0);
#endif
+ ipv4ll_reset(ifp);
+ }
}
dhcpcd_initstate(ifp, 0);
script_runreason(ifp, "CARRIER");
Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.2 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.3
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.2 Sun Nov 4 16:30:28 2018
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c Tue Jan 22 15:20:21 2019
@@ -1,6 +1,6 @@
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2018 Roy Marples <[email protected]>
+ * Copyright (c) 2006-2019 Roy Marples <[email protected]>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -1516,6 +1516,7 @@ dhcp6_dadcallback(void *arg)
if (valid)
dhcpcd_daemonise(ifp->ctx);
}
+ ipv6nd_advertise(ia);
}
}
}
@@ -3194,7 +3195,7 @@ dhcp6_recvif(struct interface *ifp, stru
ctx = ifp->ctx;
state = D6_STATE(ifp);
if (state == NULL || state->send == NULL) {
- logdebug("%s: DHCPv6 reply received but not running",
+ logdebugx("%s: DHCPv6 reply received but not running",
ifp->name);
return;
}
@@ -3299,14 +3300,24 @@ dhcp6_recvif(struct interface *ifp, stru
if (dhcp6_validatelease(ifp, r, len,
ctx->sfrom, NULL) == -1)
{
-#ifndef SMALL
- /* PD doesn't use CONFIRM, so REBIND could
- * throw up an invalid prefix if we
- * changed link */
- if (state->state == DH6S_REBIND &&
- dhcp6_hasprefixdelegation(ifp))
+ /*
+ * If we can't use the lease, fallback to
+ * DISCOVER and try and get a new one.
+ *
+ * This is needed become some servers
+ * renumber the prefix or address
+ * and deny the current one before it expires
+ * rather than sending it back with a zero
+ * lifetime along with the new prefix or
+ * address to use.
+ * This behavior is wrong, but moving to the
+ * DISCOVER phase works around it.
+ *
+ * The currently held lease is still valid
+ * until a new one is found.
+ */
+ if (state->state != DH6S_DISCOVER)
dhcp6_startdiscover(ifp);
-#endif
return;
}
if (state->state == DH6S_DISCOVER)
@@ -3538,11 +3549,12 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struc
}
if (r->type == DHCP6_RECONFIGURE) {
- logdebugx("%s: RECONFIGURE recv from %s,"
+ logdebugx("%s: RECONFIGURE6 recv from %s,"
" sending to all interfaces",
ifp->name, ctx->sfrom);
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
- if (D6_CSTATE(ifp) != NULL)
+ state = D6_CSTATE(ifp);
+ if (state != NULL && state->send != NULL)
dhcp6_recvif(ifp, r, len);
}
return;
@@ -3620,11 +3632,6 @@ dhcp6_listen(struct dhcpcd_ctx *ctx, str
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &n, sizeof(n)) == -1)
goto errexit;
-#ifdef SO_RERROR
- n = 1;
- if (setsockopt(s, SOL_SOCKET, SO_RERROR, &n, sizeof(n)) == -1)
- goto errexit;
-#endif
memset(&sa, 0, sizeof(sa));
sa.sin6_family = AF_INET6;
sa.sin6_port = htons(DHCP6_CLIENT_PORT);
@@ -3947,6 +3954,21 @@ dhcp6_dropnondelegates(struct interface
}
void
+dhcp6_abort(struct interface *ifp)
+{
+ struct dhcp6_state *state;
+ struct ipv6_addr *ia;
+
+ eloop_timeout_delete(ifp->ctx->eloop, dhcp6_start1, ifp);
+ state = D6_STATE(ifp);
+ if (state == NULL)
+ return;
+ TAILQ_FOREACH(ia, &state->addrs, next) {
+ ipv6nd_advertise(ia);
+ }
+}
+
+void
dhcp6_handleifa(int cmd, struct ipv6_addr *ia, pid_t pid)
{
struct dhcp6_state *state;
Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.2 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.3
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.2 Sun Nov 4 16:30:28 2018
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c Tue Jan 22 15:20:21 2019
@@ -1,6 +1,6 @@
/*
* BSD interface driver for dhcpcd
- * Copyright (c) 2006-2018 Roy Marples <[email protected]>
+ * Copyright (c) 2006-2019 Roy Marples <[email protected]>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -125,6 +125,7 @@ int
if_opensockets_os(struct dhcpcd_ctx *ctx)
{
struct priv *priv;
+ int n;
#if defined(RO_MSGFILTER) || defined(ROUTE_MSGFILTER)
unsigned char msgfilter[] = {
RTM_IFINFO,
@@ -161,12 +162,14 @@ if_opensockets_os(struct dhcpcd_ctx *ctx
if (ctx->link_fd == -1)
return -1;
-#ifdef SO_RERROR
- int n = 1;
- if (setsockopt(ctx->link_fd, SOL_SOCKET, SO_RERROR,
+ /* Ignore our own route(4) messages.
+ * Sadly there is no way of doing this for route(4) messages
+ * generated from addresses we add/delete. */
+ n = 0;
+ if (setsockopt(ctx->link_fd, SOL_SOCKET, SO_USELOOPBACK,
&n, sizeof(n)) == -1)
- logerr(__func__);
-#endif
+ logerr("%s: SO_USELOOPBACK", __func__);
+
#if defined(RO_MSGFILTER)
if (setsockopt(ctx->link_fd, PF_ROUTE, RO_MSGFILTER,
&msgfilter, sizeof(msgfilter)) == -1)
@@ -471,11 +474,6 @@ if_route(unsigned char cmd, const struct
assert(rt != NULL);
ctx = rt->rt_ifp->ctx;
- if ((cmd == RTM_ADD || cmd == RTM_DELETE || cmd == RTM_CHANGE) &&
- ctx->options & DHCPCD_DAEMONISE &&
- !(ctx->options & DHCPCD_DAEMONISED))
- ctx->options |= DHCPCD_RTM_PPID;
-
#define ADDSA(sa) do { \
memcpy(bp, (sa), (sa)->sa_len); \
bp += RT_ROUNDUP((sa)->sa_len); \
@@ -506,8 +504,10 @@ if_route(unsigned char cmd, const struct
!sa_is_loopback(&rt->rt_gateway))
{
rtm->rtm_index = (unsigned short)rt->rt_ifp->index;
- if (!gateway_unspec)
- rtm->rtm_addrs |= RTA_IFP;
+#ifdef __OpenBSD__
+ if (!gateway_unspec || rt->rt_dest.sa_family!=AF_INET6)
+#endif
+ rtm->rtm_addrs |= RTA_IFP;
if (!sa_is_unspecified(&rt->rt_ifa))
rtm->rtm_addrs |= RTA_IFA;
}
@@ -590,7 +590,6 @@ if_route(unsigned char cmd, const struct
rtm->rtm_msglen = (unsigned short)(bp - (char *)rtm);
if (write(ctx->link_fd, rtm, rtm->rtm_msglen) == -1)
return -1;
- ctx->sseq = ctx->seq;
return 0;
}
@@ -790,6 +789,10 @@ if_address6(unsigned char cmd, const str
if (ia->autoconf)
ifa.ifra_flags |= IN6_IFF_AUTOCONF;
#endif
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+ if (ia->addr_flags & IN6_IFF_TENTATIVE)
+ ifa.ifra_flags |= IN6_IFF_TENTATIVE;
+#endif
#ifdef IPV6_MANGETEMPADDR
if (ia->flags & IPV6_AF_TEMPORARY)
ifa.ifra_flags |= IN6_IFF_TEMPORARY;
@@ -867,7 +870,6 @@ if_address6(unsigned char cmd, const str
cmd == RTM_DELADDR ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
}
-#if !(defined(HAVE_IFADDRS_ADDRFLAGS) && defined(HAVE_IFAM_ADDRFLAGS))
int
if_addrflags6(const struct interface *ifp, const struct in6_addr *addr,
__unused const char *alias)
@@ -888,7 +890,6 @@ if_addrflags6(const struct interface *if
flags = -1;
return flags;
}
-#endif
int
if_getlifetime6(struct ipv6_addr *ia)
@@ -949,63 +950,27 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const
if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
return;
- switch (ifm->ifm_data.ifi_link_state) {
- case LINK_STATE_DOWN:
+
+ /* If we get LINK_STATE_UNKNOWN here, it means the interface
+ * doesn't support reporting carrier state.
+ * As such, we need to rely on IFF_UP.
+ * Even if LINK_STATE_UP is reported, we also need IFF_UP as well
+ * so for dhcpcd they are equivalent and we only need to check
+ * LINK_STATE_DOWN. */
+ if (ifm->ifm_data.ifi_link_state == LINK_STATE_DOWN)
link_state = LINK_DOWN;
- break;
- case LINK_STATE_UP:
- /* dhcpcd considers the link down if IFF_UP is not set. */
+ else
link_state = ifm->ifm_flags & IFF_UP ? LINK_UP : LINK_DOWN;
- break;
- default:
- /* handle_carrier will re-load the interface flags and check for
- * IFF_RUNNING as some drivers that don't handle link state also
- * don't set IFF_RUNNING when this routing message is generated.
- * As such, it is a race ...*/
- link_state = LINK_UNKNOWN;
- break;
- }
+
dhcpcd_handlecarrier(ctx, link_state,
(unsigned int)ifm->ifm_flags, ifp->name);
}
-static int
-if_ownmsgpid(struct dhcpcd_ctx *ctx, pid_t pid, int seq)
-{
-
- /* Ignore messages generated by us */
- if (getpid() == pid) {
- ctx->options &= ~DHCPCD_RTM_PPID;
- return 1;
- }
-
- /* Ignore messages sent by the parent after forking */
- if ((ctx->options &
- (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED)) ==
- (DHCPCD_RTM_PPID | DHCPCD_DAEMONISED) &&
- ctx->ppid == pid)
- {
- /* If this is the last successful message sent,
- * clear the check flag as it's possible another
- * process could re-use the same pid and also
- * manipulate the routing table. */
- if (ctx->pseq == seq)
- ctx->options &= ~DHCPCD_RTM_PPID;
- return 1;
- }
-
- /* Not a message we made. */
- return 0;
-}
-
static void
if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
{
struct rt rt;
- if (if_ownmsgpid(ctx, rtm->rtm_pid, rtm->rtm_seq))
- return;
-
/* Ignore errors. */
if (rtm->rtm_errno != 0)
return;
@@ -1052,26 +1017,6 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
return;
#ifdef HAVE_IFAM_PID
- if (if_ownmsgpid(ctx, ifam->ifam_pid, 0)) {
-#ifdef HAVE_IFAM_ADDRFLAGS
- /* If the kernel isn't doing DAD for the newly added
- * address we need to let it through. */
- if (ifam->ifam_type != RTM_NEWADDR)
- return;
- switch (rti_info[RTAX_IFA]->sa_family) {
- case AF_INET:
- if (ifam->ifam_addrflags & IN_IFF_TENTATIVE)
- return;
- break;
- case AF_INET6:
- if (ifam->ifam_addrflags & IN6_IFF_TENTATIVE)
- return;
- break;
- default:
- return;
- }
-#endif
- }
pid = ifam->ifam_pid;
#else
pid = 0;
@@ -1109,12 +1054,27 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
sin = (const void *)rti_info[RTAX_NETMASK];
mask.s_addr = sin != NULL && sin->sin_family == AF_INET ?
sin->sin_addr.s_addr : INADDR_ANY;
+ sin = (const void *)rti_info[RTAX_BRD];
+ bcast.s_addr = sin != NULL && sin->sin_family == AF_INET ?
+ sin->sin_addr.s_addr : INADDR_ANY;
#if defined(__NetBSD_Version__) && __NetBSD_Version__ < 800000000
- /* NetBSD-7 and older send an invalid broadcast address.
+ /*
+ * NetBSD-7 and older send an invalid broadcast address.
* So we need to query the actual address to get
- * the right one. */
+ * the right one.
+ */
{
+#else
+ /*
+ * If the address was deleted, lets check if it's
+ * a late message and it still exists (maybe modified).
+ * If so, ignore it as deleting an address causes
+ * dhcpcd to drop any lease to which it belongs.
+ */
+ if (ifam->ifam_type == RTM_DELADDR) {
+#endif
+#ifdef SIOCGIFALIAS
struct in_aliasreq ifra;
memset(&ifra, 0, sizeof(ifra));
@@ -1126,38 +1086,37 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
if (ioctl(ctx->pf_inet_fd, SIOCGIFALIAS, &ifra) == -1) {
if (errno != EADDRNOTAVAIL)
logerr("%s: SIOCGIFALIAS", __func__);
- break;
+ if (ifam->ifam_type != RTM_DELADDR)
+ break;
}
- bcast = ifra.ifra_broadaddr.sin_addr;
- }
-#else
- sin = (const void *)rti_info[RTAX_BRD];
- bcast.s_addr = sin != NULL && sin->sin_family == AF_INET ?
- sin->sin_addr.s_addr : INADDR_ANY;
+#if defined(__NetBSD_Version__) && __NetBSD_Version__ < 800000000
+ else
+ bcast = ifra.ifra_broadaddr.sin_addr;
#endif
-
-#if defined(__FreeBSD__) || defined(__DragonFly__)
- /* FreeBSD sends RTM_DELADDR for each assigned address
- * to an interface just brought down.
- * This is wrong, because the address still exists.
- * So we need to ignore it.
- * Oddly enough this only happens for INET addresses. */
- if (ifam->ifam_type == RTM_DELADDR) {
- struct ifreq ifr;
- struct sockaddr_in *ifr_sin;
-
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
- ifr_sin = (void *)&ifr.ifr_addr;
- ifr_sin->sin_family = AF_INET;
- ifr_sin->sin_addr = addr;
- if (ioctl(ctx->pf_inet_fd, SIOCGIFADDR, &ifr) == 0) {
- logwarnx("%s: ignored false RTM_DELADDR for %s",
- ifp->name, inet_ntoa(addr));
- break;
+#else
+#warning No SIOCGIFALIAS support
+ /*
+ * No SIOCGIFALIAS? That sucks!
+ * This makes this call very heavy weight, but we
+ * really need to know if the message is late or not.
+ */
+ const struct sockaddr *sa;
+ struct ifaddrs *ifaddrs = NULL, *ifa;
+
+ sa = rti_info[RTAX_IFA];
+ getifaddrs(&ifaddrs);
+ for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr == NULL)
+ continue;
+ if (sa_cmp(ifa->ifa_addr, sa) == 0 &&
+ strcmp(ifa->ifa_name, ifp->name) == 0)
+ break;
}
- }
+ freeifaddrs(ifaddrs);
+ if (ifa != NULL)
+ return;
#endif
+ }
#ifndef HAVE_IFAM_ADDRFLAGS
if (ifam->ifam_type == RTM_DELADDR)
@@ -1179,15 +1138,26 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
{
struct in6_addr addr6, mask6;
const struct sockaddr_in6 *sin6;
+ int flags;
sin6 = (const void *)rti_info[RTAX_IFA];
addr6 = sin6->sin6_addr;
sin6 = (const void *)rti_info[RTAX_NETMASK];
mask6 = sin6->sin6_addr;
+ /*
+ * If the address was deleted, lets check if it's
+ * a late message and it still exists (maybe modified).
+ * If so, ignore it as deleting an address causes
+ * dhcpcd to drop any lease to which it belongs.
+ */
+ if (ifam->ifam_type == RTM_DELADDR) {
+ flags = if_addrflags6(ifp, &addr6, NULL);
+ if (flags != -1)
+ break;
+ addrflags = 0;
+ }
#ifndef HAVE_IFAM_ADDRFLAGS
- if (ifam->ifam_type == RTM_DELADDR)
- addrflags = 0;
else if ((addrflags = if_addrflags6(ifp, &addr6, NULL)) == -1) {
if (errno != EADDRNOTAVAIL)
logerr("%s: if_addrflags6", __func__);
@@ -1286,7 +1256,8 @@ if_machinearch(char *str, size_t len)
#ifdef INET6
#if (defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV)) || \
- defined(IPV6CTL_USETEMPADDR) || defined(IPV6CTL_TEMPVLTIME)
+ defined(IPV6CTL_USETEMPADDR) || defined(IPV6CTL_TEMPVLTIME) || \
+ defined(IPV6CTL_FORWARDING)
#define get_inet6_sysctl(code) inet6_sysctl(code, 0, 0)
#define set_inet6_sysctl(code, val) inet6_sysctl(code, val, 1)
static int
@@ -1370,6 +1341,19 @@ ip6_temp_valid_lifetime(__unused const c
}
#endif
+int
+ip6_forwarding(__unused const char *ifname)
+{
+ int val;
+
+#ifdef IPV6CTL_FORWARDING
+ val = get_inet6_sysctl(IPV6CTL_FORWARDING);
+#else
+ val = get_inet6_sysctlbyname("net.inet6.ip6.forwarding");
+#endif
+ return val < 0 ? 0 : val;
+}
+
#ifdef SIOCIFAFATTACH
static int
af_attach(int s, const struct interface *ifp, int af)
@@ -1399,8 +1383,20 @@ set_ifxflags(int s, const struct interfa
/*
* If not doing autoconf, don't disable the kernel from doing it.
* If we need to, we should have another option actively disable it.
+ *
+ * OpenBSD moved from kernel based SLAAC to userland via slaacd(8).
+ * It has a similar featureset to dhcpcd such as stable private
+ * addresses, but lacks the ability to handle DNS inside the RA
+ * which is a serious shortfall in this day and age.
+ * Appease their user base by working alongside slaacd(8) if
+ * dhcpcd is instructed not to do auto configuration of addresses.
*/
- if (ifp->options->options & DHCPCD_IPV6RS)
+#if defined(ND6_IFF_ACCEPT_RTADV)
+#define BSD_AUTOCONF DHCPCD_IPV6RS
+#else
+#define BSD_AUTOCONF DHCPCD_IPV6RA_AUTOCONF
+#endif
+ if (ifp->options->options & BSD_AUTOCONF)
flags &= ~IFXF_AUTOCONF6;
if (ifr.ifr_flags == flags)
return 0;
@@ -1510,13 +1506,14 @@ if_setup_inet6(const struct interface *i
* and prefixes so the kernel does not expire prefixes
* and default routes we are trying to own. */
if (ifp->options->options & DHCPCD_IPV6RS) {
- char ifname[IFNAMSIZ + 8];
+ struct in6_ifreq ifr;
- strlcpy(ifname, ifp->name, sizeof(ifname));
- if (ioctl(s, SIOCSRTRFLUSH_IN6, (void *)&ifname) == -1 &&
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCSRTRFLUSH_IN6, &ifr) == -1 &&
errno != ENOTSUP)
logwarn("SIOCSRTRFLUSH_IN6");
- if (ioctl(s, SIOCSPFXFLUSH_IN6, (void *)&ifname) == -1 &&
+ if (ioctl(s, SIOCSPFXFLUSH_IN6, &ifr) == -1 &&
errno != ENOTSUP)
logwarn("SIOCSPFXFLUSH_IN6");
}
Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.2 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.3
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.2 Sun Nov 4 16:30:28 2018
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c Tue Jan 22 15:20:21 2019
@@ -1,6 +1,6 @@
/*
* dhcpcd - IPv6 ND handling
- * Copyright (c) 2006-2018 Roy Marples <[email protected]>
+ * Copyright (c) 2006-2019 Roy Marples <[email protected]>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
+#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
@@ -217,13 +218,6 @@ ipv6nd_open(struct dhcpcd_ctx *ctx)
&on, sizeof(on)) == -1)
goto eexit;
-#ifdef SO_RERROR
- on = 1;
- if (setsockopt(ctx->nd_fd, SOL_SOCKET, SO_RERROR,
- &on, sizeof(on)) == -1)
- goto eexit;
-#endif
-
ICMP6_FILTER_SETBLOCKALL(&filt);
ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt);
ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
@@ -338,6 +332,135 @@ ipv6nd_sendrsprobe(void *arg)
}
}
+static void
+ipv6nd_sendadvertisement(void *arg)
+{
+ struct ipv6_addr *ia = arg;
+ struct interface *ifp = ia->iface;
+ struct dhcpcd_ctx *ctx = ifp->ctx;
+ struct sockaddr_in6 dst;
+ struct cmsghdr *cm;
+ struct in6_pktinfo pi;
+ const struct rs_state *state = RS_CSTATE(ifp);
+
+ if (state == NULL || ifp->carrier == LINK_DOWN)
+ goto freeit;
+
+ memset(&dst, 0, sizeof(dst));
+ dst.sin6_family = AF_INET6;
+#ifdef SIN6_LEN
+ dst.sin6_len = sizeof(dst);
+#endif
+ dst.sin6_scope_id = ifp->index;
+ if (inet_pton(AF_INET6, ALLNODES, &dst.sin6_addr) != 1) {
+ logerr(__func__);
+ return;
+ }
+
+ ctx->sndhdr.msg_name = (void *)&dst;
+ ctx->sndhdr.msg_iov[0].iov_base = ia->na;
+ ctx->sndhdr.msg_iov[0].iov_len = ia->na_len;
+
+ /* Set the outbound interface. */
+ cm = CMSG_FIRSTHDR(&ctx->sndhdr);
+ assert(cm != NULL);
+ cm->cmsg_level = IPPROTO_IPV6;
+ cm->cmsg_type = IPV6_PKTINFO;
+ cm->cmsg_len = CMSG_LEN(sizeof(pi));
+ memset(&pi, 0, sizeof(pi));
+ pi.ipi6_ifindex = ifp->index;
+ memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
+
+ logdebugx("%s: sending NA for %s", ifp->name, ia->saddr);
+ if (sendmsg(ctx->nd_fd, &ctx->sndhdr, 0) == -1)
+ logerr(__func__);
+
+ if (++ia->na_count < MAX_NEIGHBOR_ADVERTISEMENT) {
+ eloop_timeout_add_sec(ctx->eloop,
+ state->retrans / 1000, ipv6nd_sendadvertisement, ia);
+ return;
+ }
+
+freeit:
+ free(ia->na);
+ ia->na = NULL;
+ ia->na_count = 0;
+}
+
+void
+ipv6nd_advertise(struct ipv6_addr *ia)
+{
+ struct dhcpcd_ctx *ctx;
+ struct interface *ifp;
+ struct ipv6_state *state;
+ struct ipv6_addr *iap, *iaf;
+ struct nd_neighbor_advert *na;
+
+ if (IN6_IS_ADDR_MULTICAST(&ia->addr))
+ return;
+
+ ctx = ia->iface->ctx;
+ if_sortinterfaces(ctx);
+ /* Find the most preferred address to advertise. */
+ iaf = NULL;
+ TAILQ_FOREACH(ifp, ctx->ifaces, next) {
+ state = IPV6_STATE(ifp);
+ if (state == NULL || ifp->carrier == LINK_DOWN)
+ continue;
+
+ TAILQ_FOREACH(iap, &state->addrs, next) {
+ if (!IN6_ARE_ADDR_EQUAL(&iap->addr, &ia->addr))
+ continue;
+
+ /* Cancel any current advertisement. */
+ eloop_timeout_delete(ctx->eloop,
+ ipv6nd_sendadvertisement, iap);
+
+ /* Don't advertise what we can't use. */
+ if (iap->prefix_vltime == 0 ||
+ iap->addr_flags & IN6_IFF_NOTUSEABLE)
+ continue;
+
+ if (iaf == NULL)
+ iaf = iap;
+ }
+ }
+ if (iaf == NULL)
+ return;
+
+ /* Make the packet. */
+ ifp = iaf->iface;
+ iaf->na_len = sizeof(*na);
+ if (ifp->hwlen != 0)
+ iaf->na_len += (size_t)ROUNDUP8(ifp->hwlen + 2);
+ na = calloc(1, iaf->na_len);
+ if (na == NULL) {
+ logerr(__func__);
+ return;
+ }
+
+ na->nd_na_type = ND_NEIGHBOR_ADVERT;
+ na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE;
+ if (ip6_forwarding(ifp->name) == 1)
+ na->nd_na_flags_reserved |= ND_NA_FLAG_ROUTER;
+ na->nd_na_target = ia->addr;
+
+ if (ifp->hwlen != 0) {
+ struct nd_opt_hdr *opt;
+
+ opt = (struct nd_opt_hdr *)(na + 1);
+ opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
+ opt->nd_opt_len = (uint8_t)((ROUNDUP8(ifp->hwlen + 2)) >> 3);
+ memcpy(opt + 1, ifp->hwaddr, ifp->hwlen);
+ }
+
+ iaf->na_count = 0;
+ free(iaf->na);
+ iaf->na = na;
+ eloop_timeout_delete(ctx->eloop, ipv6nd_sendadvertisement, iaf);
+ ipv6nd_sendadvertisement(iaf);
+}
+
void
ipv6nd_expire(struct interface *ifp, uint32_t seconds)
{
@@ -725,6 +848,7 @@ try_script:
return;
}
}
+ ipv6nd_advertise(ia);
}
}
@@ -876,8 +1000,11 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
if (rap->reachable > MAX_REACHABLE_TIME)
rap->reachable = 0;
}
- if (nd_ra->nd_ra_retransmit)
- rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
+ if (nd_ra->nd_ra_retransmit) {
+ struct rs_state *state = RS_STATE(ifp);
+
+ state->retrans = rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
+ }
if (rap->lifetime)
rap->expired = 0;
rap->hasdns = 0;
@@ -969,12 +1096,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
if (ap == NULL) {
unsigned int flags;
- if (!(pi.nd_opt_pi_flags_reserved &
- ND_OPT_PI_FLAG_AUTO) &&
- !(pi.nd_opt_pi_flags_reserved &
- ND_OPT_PI_FLAG_ONLINK))
- continue;
-
flags = IPV6_AF_RAPFX;
if (pi.nd_opt_pi_flags_reserved &
ND_OPT_PI_FLAG_AUTO &&
@@ -987,7 +1108,8 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
if (ap == NULL)
break;
ap->prefix = pi_prefix;
- ap->dadcallback = ipv6nd_dadcallback;
+ if (flags & IPV6_AF_AUTOCONF)
+ ap->dadcallback = ipv6nd_dadcallback;
ap->created = ap->acquired = rap->acquired;
TAILQ_INSERT_TAIL(&rap->addrs, ap, next);
@@ -997,7 +1119,8 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
* temporary address also exists then
* extend the existing one rather than
* create a new one */
- if (ipv6_iffindaddr(ifp, &ap->addr,
+ if (flags & IPV6_AF_AUTOCONF &&
+ ipv6_iffindaddr(ifp, &ap->addr,
IN6_IFF_NOTUSEABLE) &&
ipv6_settemptime(ap, 0))
new_ap = 0;
@@ -1635,6 +1758,7 @@ ipv6nd_startrs1(void *arg)
return;
}
+ state->retrans = RETRANS_TIMER;
state->rsprobes = 0;
ipv6nd_sendrsprobe(ifp);
}
Index: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.10 src/external/bsd/dhcpcd/dist/src/if-options.c:1.11
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.10 Sat Jun 2 09:44:27 2018
+++ src/external/bsd/dhcpcd/dist/src/if-options.c Tue Jan 22 15:20:21 2019
@@ -1,6 +1,6 @@
/*
* dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2018 Roy Marples <[email protected]>
+ * Copyright (c) 2006-2019 Roy Marples <[email protected]>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -2010,7 +2010,7 @@ err_sla:
arg = fp;
fp = strend(arg);
if (fp == NULL) {
- logerrx("authtoken requies an an expiry date");
+ logerrx("authtoken requies an expiry date");
free(token->realm);
free(token);
return -1;