Module Name: src
Committed By: roy
Date: Wed Nov 13 10:50:22 UTC 2019
Modified Files:
src/external/bsd/dhcpcd/dist/src: dhcp.c dhcp6.c dhcpcd.c if-bsd.c
ipv6nd.c
Log Message:
Sync
To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 src/external/bsd/dhcpcd/dist/src/dhcp.c
cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/src/dhcp6.c
cvs rdiff -u -r1.28 -r1.29 src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.14 -r1.15 src/external/bsd/dhcpcd/dist/src/if-bsd.c
cvs rdiff -u -r1.12 -r1.13 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.29 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.30
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.29 Wed Oct 16 14:54:39 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c Wed Nov 13 10:50:22 2019
@@ -41,6 +41,10 @@
#include <netinet/udp.h>
#undef __FAVOR_BSD
+#ifdef AF_LINK
+# include <net/if_dl.h>
+#endif
+
#include <assert.h>
#include <ctype.h>
#include <errno.h>
@@ -132,9 +136,7 @@ static void dhcp_arp_found(struct arp_st
#endif
static void dhcp_handledhcp(struct interface *, struct bootp *, size_t,
const struct in_addr *);
-#ifdef IP_PKTINFO
static void dhcp_handleifudp(void *);
-#endif
static int dhcp_initstate(struct interface *);
void
@@ -1550,7 +1552,10 @@ dhcp_openudp(struct interface *ifp)
n = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
goto eexit;
-#ifdef IP_RECVPKTINFO
+#ifdef IP_RECVIF
+ if (setsockopt(s, IPPROTO_IP, IP_RECVIF, &n, sizeof(n)) == -1)
+ goto eexit;
+#else
if (setsockopt(s, IPPROTO_IP, IP_RECVPKTINFO, &n, sizeof(n)) == -1)
goto eexit;
#endif
@@ -1647,39 +1652,36 @@ dhcp_makeudppacket(size_t *sz, const uin
static ssize_t
dhcp_sendudp(struct interface *ifp, struct in_addr *to, void *data, size_t len)
{
- int s;
- struct msghdr msg;
- struct sockaddr_in sin;
- struct iovec iov[1];
- struct dhcp_state *state = D_STATE(ifp);
- ssize_t r;
-
- iov[0].iov_base = data;
- iov[0].iov_len = len;
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr = *to;
- sin.sin_port = htons(BOOTPS);
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ .sin_addr = *to,
+ .sin_port = htons(BOOTPS),
#ifdef HAVE_SA_LEN
- sin.sin_len = sizeof(sin);
+ .sin_len = sizeof(sin),
#endif
+ };
+ struct iovec iov[] = {
+ { .iov_base = data, .iov_len = len }
+ };
+ struct msghdr msg = {
+ .msg_name = (void *)&sin,
+ .msg_namelen = sizeof(sin),
+ .msg_iov = iov,
+ .msg_iovlen = 1,
+ };
+ struct dhcp_state *state = D_STATE(ifp);
+ ssize_t r;
+ int fd;
- memset(&msg, 0, sizeof(msg));
- msg.msg_name = (void *)&sin;
- msg.msg_namelen = sizeof(sin);
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
-
- s = state->udp_fd;
- if (s == -1) {
- s = dhcp_openudp(ifp);
- if (s == -1)
+ fd = state->udp_fd;
+ if (fd == -1) {
+ fd = dhcp_openudp(ifp);
+ if (fd == -1)
return -1;
}
- r = sendmsg(s, &msg, 0);
+ r = sendmsg(fd, &msg, 0);
if (state->udp_fd == -1)
- close(s);
+ close(fd);
return r;
}
@@ -1780,7 +1782,7 @@ send_message(struct interface *ifp, uint
* As such we remove it from consideration without actually
* stopping the interface. */
if (r == -1) {
- logerr("%s: if_sendraw", ifp->name);
+ logerr("%s: bpf_send", ifp->name);
switch(errno) {
case ENETDOWN:
case ENETRESET:
@@ -2257,30 +2259,27 @@ dhcp_bind(struct interface *ifp)
ipv4_applyaddr(ifp);
-#ifdef IP_PKTINFO
/* 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))
- {
- dhcp_close(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) {
- logerr(__func__);
- /* 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);
- }
+ if (!(state->udp_fd == -1 ||
+ (state->old != NULL && state->old->yiaddr != state->new->yiaddr)))
+ return;
+ dhcp_close(ifp);
+
+ /* If not in master mode, open an address specific socket. */
+ if (ctx->udp_fd != -1)
+ return;
+ state->udp_fd = dhcp_openudp(ifp);
+ if (state->udp_fd == -1) {
+ logerr(__func__);
+ /* 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);
+ return;
}
-#endif
+ eloop_event_add(ctx->eloop, state->udp_fd, dhcp_handleifudp, ifp);
}
static void
@@ -2609,6 +2608,11 @@ dhcp_reboot(struct interface *ifp)
ifp->name, inet_ntoa(state->lease.addr));
#ifdef ARP
+#ifndef KERNEL_RFC5227
+ /* Create the DHCP ARP state so we can defend it. */
+ (void)dhcp_arp_new(ifp, &state->lease.addr);
+#endif
+
/* If the address exists on the interface and no other interface
* is currently using it then announce it to ensure this
* interface gets the reply. */
@@ -3315,7 +3319,7 @@ checksums_valid(void *packet,
struct ip *ip = packet;
union pip {
struct ip ip;
- uint16_t w[sizeof(struct ip)];
+ uint16_t w[sizeof(struct ip) / 2];
} pip = {
.ip.ip_p = IPPROTO_UDP,
.ip.ip_src = ip->ip_src,
@@ -3350,7 +3354,7 @@ checksums_valid(void *packet,
uh_sump = udpp + offsetof(struct udphdr, uh_sum);
memset(uh_sump, 0, sizeof(udp.uh_sum));
- /* Checksum psuedo header and then UDP + payload. */
+ /* Checksum pseudo header and then UDP + payload. */
in_cksum(pip.w, sizeof(pip.w), &csum);
csum = in_cksum(udpp, ntohs(udp.uh_ulen), &csum);
@@ -3451,6 +3455,35 @@ dhcp_readbpf(void *arg)
}
static void
+dhcp_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg)
+{
+ struct sockaddr_in *from = (struct sockaddr_in *)msg->msg_name;
+ struct iovec *iov = &msg->msg_iov[0];
+ struct interface *ifp;
+ const struct dhcp_state *state;
+
+ ifp = if_findifpfromcmsg(ctx, msg, NULL);
+ if (ifp == NULL) {
+ logerr(__func__);
+ return;
+ }
+ state = D_CSTATE(ifp);
+ if (state == NULL) {
+ logdebugx("%s: received BOOTP for inactive interface",
+ ifp->name);
+ return;
+ }
+
+ if (state->bpf_fd != -1) {
+ /* Avoid a duplicate read if BPF is open for the interface. */
+ return;
+ }
+
+ dhcp_handlebootp(ifp, (struct bootp *)iov->iov_base, iov->iov_len,
+ &from->sin_addr);
+}
+
+static void
dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp)
{
const struct dhcp_state *state;
@@ -3460,16 +3493,15 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, str
.iov_base = buf,
.iov_len = sizeof(buf),
};
-#ifdef IP_PKTINFO
+#ifdef IP_RECVIF
+ unsigned char ctl[CMSG_SPACE(sizeof(struct sockaddr_dl))] = { 0 };
+#else
unsigned char ctl[CMSG_SPACE(sizeof(struct in_pktinfo))] = { 0 };
- char sfrom[INET_ADDRSTRLEN];
#endif
struct msghdr msg = {
.msg_name = &from, .msg_namelen = sizeof(from),
.msg_iov = &iov, .msg_iovlen = 1,
-#ifdef IP_PKTINFO
.msg_control = ctl, .msg_controllen = sizeof(ctl),
-#endif
};
int s;
ssize_t bytes;
@@ -3486,31 +3518,8 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, str
return;
}
-#ifdef IP_PKTINFO
- inet_ntop(AF_INET, &from.sin_addr, sfrom, sizeof(sfrom));
-
- if (ifp == NULL) {
- ifp = if_findifpfromcmsg(ctx, &msg, NULL);
- if (ifp == NULL) {
- logerr(__func__);
- return;
- }
- state = D_CSTATE(ifp);
- if (state == NULL) {
- logdebugx("%s: received BOOTP for inactive interface",
- ifp->name);
- return;
- }
- }
-
- if (state->bpf_fd != -1) {
- /* Avoid a duplicate read if BPF is open for the interface. */
- return;
- }
-
- dhcp_handlebootp(ifp, (struct bootp *)(void *)buf, (size_t)bytes,
- &from.sin_addr);
-#endif
+ iov.iov_len = (size_t)bytes;
+ dhcp_recvmsg(ctx, &msg);
}
static void
@@ -3521,16 +3530,24 @@ dhcp_handleudp(void *arg)
dhcp_readudp(ctx, NULL);
}
-#ifdef IP_PKTINFO
static void
dhcp_handleifudp(void *arg)
{
struct interface *ifp = arg;
dhcp_readudp(ifp->ctx, ifp);
+}
+
+static int
+dhcp_open(struct dhcpcd_ctx *ctx)
+{
+ if (ctx->udp_fd != -1 || (ctx->udp_fd = dhcp_openudp(NULL)) == -1)
+ return ctx->udp_fd;
+
+ eloop_event_add(ctx->eloop, ctx->udp_fd, dhcp_handleudp, ctx);
+ return ctx->udp_fd;
}
-#endif
static int
dhcp_openbpf(struct interface *ifp)
@@ -3740,16 +3757,13 @@ dhcp_start1(void *arg)
* 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) {
+ if (ctx->options & DHCPCD_MASTER) {
+ if (dhcp_open(ctx) == -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(ctx->eloop,
- ctx->udp_fd, dhcp_handleudp, ctx);
+ logerr("%s: dhcp_open", __func__);
+ }
}
if (dhcp_init(ifp) == -1) {
@@ -4008,7 +4022,7 @@ dhcp_handleifa(int cmd, struct ipv4_addr
* to drop the lease. */
dhcp_drop(ifp, "EXPIRE");
dhcp_start1(ifp);
- return NULL;
+ return ia;
}
}
Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.13 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.14
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.13 Fri Oct 11 11:03:59 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c Wed Nov 13 10:50:22 2019
@@ -3465,23 +3465,10 @@ dhcp6_recvif(struct interface *ifp, cons
}
static void
-dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
+dhcp6_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, struct ipv6_addr *ia)
{
- struct sockaddr_in6 from;
- unsigned char buf[64 * 1024]; /* Maximum UDP message size */
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = sizeof(buf),
- };
- unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
- struct msghdr msg = {
- .msg_name = &from, .msg_namelen = sizeof(from),
- .msg_iov = &iov, .msg_iovlen = 1,
- .msg_control = ctl, .msg_controllen = sizeof(ctl),
- };
- int s;
- size_t len;
- ssize_t bytes;
+ struct sockaddr_in6 *from = msg->msg_name;
+ size_t len = msg->msg_iov[0].iov_len;
char sfrom[INET6_ADDRSTRLEN];
struct interface *ifp;
struct dhcp6_message *r;
@@ -3489,14 +3476,7 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struc
uint8_t *o;
uint16_t ol;
- s = ia != NULL ? ia->dhcp6_fd : ctx->dhcp6_fd;
- bytes = recvmsg(s, &msg, 0);
- if (bytes == -1) {
- logerr(__func__);
- return;
- }
- len = (size_t)bytes;
- inet_ntop(AF_INET6, &from.sin6_addr, sfrom, sizeof(sfrom));
+ inet_ntop(AF_INET6, &from->sin6_addr, sfrom, sizeof(sfrom));
if (len < sizeof(struct dhcp6_message)) {
logerrx("DHCPv6 packet too short from %s", sfrom);
return;
@@ -3505,14 +3485,14 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struc
if (ia != NULL)
ifp = ia->iface;
else {
- ifp = if_findifpfromcmsg(ctx, &msg, NULL);
+ ifp = if_findifpfromcmsg(ctx, msg, NULL);
if (ifp == NULL) {
logerr(__func__);
return;
}
}
- r = (struct dhcp6_message *)buf;
+ r = (struct dhcp6_message *)msg->msg_iov[0].iov_base;
o = dhcp6_findmoption(r, len, D6_OPTION_CLIENTID, &ol);
if (o == NULL || ol != ctx->duid_len ||
memcmp(o, ctx->duid, ol) != 0)
@@ -3581,6 +3561,35 @@ dhcp6_recv(struct dhcpcd_ctx *ctx, struc
}
static void
+dhcp6_recv(struct dhcpcd_ctx *ctx, struct ipv6_addr *ia)
+{
+ struct sockaddr_in6 from;
+ unsigned char buf[64 * 1024]; /* Maximum UDP message size */
+ struct iovec iov = {
+ .iov_base = buf,
+ .iov_len = sizeof(buf),
+ };
+ unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
+ struct msghdr msg = {
+ .msg_name = &from, .msg_namelen = sizeof(from),
+ .msg_iov = &iov, .msg_iovlen = 1,
+ .msg_control = ctl, .msg_controllen = sizeof(ctl),
+ };
+ int s;
+ ssize_t bytes;
+
+ s = ia != NULL ? ia->dhcp6_fd : ctx->dhcp6_fd;
+ bytes = recvmsg(s, &msg, 0);
+ if (bytes == -1) {
+ logerr(__func__);
+ return;
+ }
+
+ iov.iov_len = (size_t)bytes;
+ dhcp6_recvmsg(ctx, &msg, ia);
+}
+
+static void
dhcp6_recvaddr(void *arg)
{
struct ipv6_addr *ia = arg;
@@ -3677,6 +3686,18 @@ dhcp6_activateinterfaces(struct interfac
}
#endif
+static int
+dhcp6_open(struct dhcpcd_ctx *ctx)
+{
+
+ if (ctx->dhcp6_fd != -1 ||
+ (ctx->dhcp6_fd = dhcp6_listen(ctx, NULL)) == -1)
+ return ctx->dhcp6_fd;
+
+ eloop_event_add(ctx->eloop, ctx->dhcp6_fd, dhcp6_recvctx, ctx);
+ return ctx->dhcp6_fd;
+}
+
static void
dhcp6_start1(void *arg)
{
@@ -3687,11 +3708,9 @@ dhcp6_start1(void *arg)
size_t i;
const struct dhcp_compat *dhc;
- if (ctx->dhcp6_fd == -1 && ctx->options & DHCPCD_MASTER) {
- ctx->dhcp6_fd = dhcp6_listen(ctx, NULL);
- if (ctx->dhcp6_fd == -1)
+ if (ctx->options & DHCPCD_MASTER) {
+ if (dhcp6_open(ctx) == -1)
return;
- eloop_event_add(ctx->eloop, ctx->dhcp6_fd, dhcp6_recvctx, ctx);
}
state = D6_STATE(ifp);
Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.28 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.29
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.28 Wed Oct 16 14:54:39 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c Wed Nov 13 10:50:22 2019
@@ -186,6 +186,12 @@ handle_exit_timeout(void *arg)
ctx = arg;
logerrx("timed out");
if (!(ctx->options & DHCPCD_MASTER)) {
+ struct interface *ifp;
+
+ TAILQ_FOREACH(ifp, ctx->ifaces, next) {
+ if (ifp->active == IF_ACTIVE_USER)
+ script_runreason(ifp, "STOPPED");
+ }
eloop_exit(ctx->eloop, EXIT_FAILURE);
return;
}
@@ -702,6 +708,21 @@ dhcpcd_initstate(struct interface *ifp,
dhcpcd_initstate1(ifp, ifp->ctx->argc, ifp->ctx->argv, options);
}
+static void
+dhcpcd_reportssid(struct interface *ifp)
+{
+ char pssid[IF_SSIDLEN * 4];
+
+ if (print_string(pssid, sizeof(pssid), OT_ESCSTRING,
+ ifp->ssid, ifp->ssid_len) == -1)
+ {
+ logerr(__func__);
+ return;
+ }
+
+ loginfox("%s: connected to Access Point `%s'", ifp->name, pssid);
+}
+
void
dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
const char *ifname)
@@ -773,6 +794,7 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
if (ifp->ssid_len != olen ||
memcmp(ifp->ssid, ossid, ifp->ssid_len))
{
+ dhcpcd_reportssid(ifp);
#ifdef NOCARRIER_PRESERVE_IP
dhcpcd_drop(ifp, 0);
#endif
@@ -970,7 +992,8 @@ run_preinit(struct interface *ifp)
return;
script_runreason(ifp, "PREINIT");
-
+ if (ifp->wireless)
+ dhcpcd_reportssid(ifp);
if (ifp->options->options & DHCPCD_LINK && ifp->carrier != LINK_UNKNOWN)
script_runreason(ifp,
ifp->carrier == LINK_UP ? "CARRIER" : "NOCARRIER");
@@ -1989,6 +2012,12 @@ printpidfile:
ctx.options & DHCPCD_IPV4 ? " [ip4]" : "",
ctx.options & DHCPCD_IPV6 ? " [ip6]" : "");
+#ifdef BSD
+ /* Disable the kernel RTADV sysctl as early as possible. */
+ if (ctx.options & DHCPCD_IPV6 && ctx.options & DHCPCD_IPV6RS)
+ if_disable_rtadv();
+#endif
+
if (if_opensockets(&ctx) == -1) {
logerr("%s: if_opensockets", __func__);
goto exit_failure;
@@ -2127,6 +2156,7 @@ exit1:
if_free(ifp);
}
free(ctx.ifaces);
+ ctx.ifaces = NULL;
}
free_options(&ctx, ifo);
#ifdef HAVE_OPEN_MEMSTREAM
Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.14 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.15
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.14 Fri Oct 11 11:03:59 2019
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c Wed Nov 13 10:50:22 2019
@@ -1130,6 +1130,10 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const
case LINK_STATE_UNKNOWN:
link_state = LINK_UNKNOWN;
break;
+#ifdef LINK_STATE_FULL_DUPLEX
+ case LINK_STATE_HALF_DUPLEX: /* FALLTHROUGH */
+ case LINK_STATE_FULL_DUPLEX: /* FALLTHROUGH */
+#endif
case LINK_STATE_UP:
link_state = LINK_UP;
break;
@@ -1484,6 +1488,42 @@ inet6_sysctl(int code, int val, int acti
}
#endif
+int
+if_applyra(const struct ra *rap)
+{
+#ifdef SIOCSIFINFO_IN6
+ struct in6_ndireq ndi = { .ndi.chlim = 0 };
+ struct priv *priv = rap->iface->ctx->priv;
+ int error;
+
+ strlcpy(ndi.ifname, rap->iface->name, sizeof(ndi.ifname));
+ if (ioctl(priv->pf_inet6_fd, SIOCGIFINFO_IN6, &ndi) == -1)
+ return -1;
+
+ ndi.ndi.linkmtu = rap->mtu;
+ ndi.ndi.chlim = rap->hoplimit;
+ ndi.ndi.retrans = rap->retrans;
+ ndi.ndi.basereachable = rap->reachable;
+ error = ioctl(priv->pf_inet6_fd, SIOCSIFINFO_IN6, &ndi);
+ if (error == -1 && errno == EINVAL) {
+ /*
+ * Very likely that this is caused by a dodgy MTU
+ * setting specific to the interface.
+ * Let's set it to "unspecified" and try again.
+ * Doesn't really matter as we fix the MTU against the
+ * routes we add as not all OS support SIOCSIFINFO_IN6.
+ */
+ ndi.ndi.linkmtu = 0;
+ error = ioctl(priv->pf_inet6_fd, SIOCSIFINFO_IN6, &ndi);
+ }
+ return error;
+#else
+#warning OS does not allow setting of RA bits hoplimit, retrans or reachable
+ UNUSED(rap);
+ return 0;
+#endif
+}
+
#ifdef IPV6_MANAGETEMPADDR
#ifndef IPV6CTL_TEMPVLTIME
#define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0)
@@ -1620,6 +1660,22 @@ set_ifxflags(int s, const struct interfa
#endif
void
+if_disable_rtadv(void)
+{
+#if defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV)
+ int ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV);
+
+ if (ra == -1) {
+ if (errno != ENOENT)
+ logerr("IPV6CTL_ACCEPT_RTADV");
+ else if (ra != 0)
+ if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1)
+ logerr("IPV6CTL_ACCEPT_RTADV");
+ }
+#endif
+}
+
+void
if_setup_inet6(const struct interface *ifp)
{
struct priv *priv;
@@ -1690,21 +1746,6 @@ if_setup_inet6(const struct interface *i
logerr("%s: set_ifxflags", ifp->name);
#endif
-#if defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV)
- /* If we cannot control ra per interface, disable it globally. */
- if (ifp->options->options & DHCPCD_IPV6RS) {
- int ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV);
-
- if (ra == -1) {
- if (errno != ENOENT)
- logerr("IPV6CTL_ACCEPT_RTADV");
- else if (ra != 0)
- if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1)
- logerr("IPV6CTL_ACCEPT_RTADV");
- }
- }
-#endif
-
#if defined(IPV6CTL_ACCEPT_RTADV) || defined(ND6_IFF_ACCEPT_RTADV)
/* Flush the kernel knowledge of advertised routers
* and prefixes so the kernel does not expire prefixes
Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.12 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.13
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.12 Fri Sep 13 11:01:50 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c Wed Nov 13 10:50:22 2019
@@ -196,36 +196,41 @@ ipv6nd_printoptions(const struct dhcpcd_
static int
ipv6nd_open0(void)
{
- int s, on;
+ int fd, on;
struct icmp6_filter filt;
#define SOCK_FLAGS SOCK_CLOEXEC | SOCK_NONBLOCK
- s = xsocket(PF_INET6, SOCK_RAW | SOCK_FLAGS, IPPROTO_ICMPV6);
+ fd = xsocket(PF_INET6, SOCK_RAW | SOCK_FLAGS, IPPROTO_ICMPV6);
#undef SOCK_FLAGS
- if (s == -1)
+ if (fd == -1)
return -1;
/* RFC4861 4.1 */
on = 255;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
&on, sizeof(on)) == -1)
goto eexit;
on = 1;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+ &on, sizeof(on)) == -1)
+ goto eexit;
+
+ on = 1;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
&on, sizeof(on)) == -1)
goto eexit;
ICMP6_FILTER_SETBLOCKALL(&filt);
ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
- if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
+ if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER,
&filt, sizeof(filt)) == -1)
goto eexit;
- return s;
+ return fd;
eexit:
- close(s);
+ close(fd);
return -1;
}
@@ -233,7 +238,7 @@ eexit:
static int
ipv6nd_open(struct interface *ifp)
{
- int s;
+ int fd;
struct ipv6_mreq mreq = {
.ipv6mr_multiaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
.ipv6mr_interface = ifp->index
@@ -244,52 +249,44 @@ ipv6nd_open(struct interface *ifp)
if (state->nd_fd != -1)
return state->nd_fd;
- s = ipv6nd_open0();
- if (s == -1)
+ fd = ipv6nd_open0();
+ if (fd == -1)
return -1;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_BOUND_IF,
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF,
&ifindex, sizeof(ifindex)) == -1)
{
- close(s);
+ close(fd);
return -1;
}
- if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
&mreq, sizeof(mreq)) == -1)
{
- close(s);
+ close(fd);
return -1;
}
- state->nd_fd = s;
- eloop_event_add(ifp->ctx->eloop, s, ipv6nd_handledata, ifp);
- return s;
+ state->nd_fd = fd;
+ eloop_event_add(ifp->ctx->eloop, fd, ipv6nd_handledata, ifp);
+ return fd;
}
#else
static int
ipv6nd_open(struct dhcpcd_ctx *ctx)
{
- int s, on;
+ int fd;
if (ctx->nd_fd != -1)
return ctx->nd_fd;
- s = ipv6nd_open0();
- if (s == -1)
- return -1;
-
- on = 1;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
- &on, sizeof(on)) == -1)
- {
- close(s);
+ fd = ipv6nd_open0();
+ if (fd == -1)
return -1;
- }
- ctx->nd_fd = s;
- eloop_event_add(ctx->eloop, s, ipv6nd_handledata, ctx);
- return s;
+ ctx->nd_fd = fd;
+ eloop_event_add(ctx->eloop, fd, ipv6nd_handledata, ctx);
+ return fd;
}
#endif
@@ -559,6 +556,76 @@ ipv6nd_startexpire(struct interface *ifp
ipv6nd_expire, ifp);
}
+static int
+ipv6nd_rtpref(struct ra *rap)
+{
+
+ switch (rap->flags & ND_RA_FLAG_RTPREF_MASK) {
+ case ND_RA_FLAG_RTPREF_HIGH:
+ return RTPREF_HIGH;
+ case ND_RA_FLAG_RTPREF_MEDIUM:
+ case ND_RA_FLAG_RTPREF_RSV:
+ return RTPREF_MEDIUM;
+ case ND_RA_FLAG_RTPREF_LOW:
+ return RTPREF_LOW;
+ default:
+ logerrx("%s: impossible RA flag %x", __func__, rap->flags);
+ return RTPREF_INVALID;
+ }
+ /* NOTREACHED */
+}
+
+static void
+ipv6nd_sortrouters(struct dhcpcd_ctx *ctx)
+{
+ struct ra_head sorted_routers = TAILQ_HEAD_INITIALIZER(sorted_routers);
+ struct ra *ra1, *ra2;
+
+ while ((ra1 = TAILQ_FIRST(ctx->ra_routers)) != NULL) {
+ TAILQ_REMOVE(ctx->ra_routers, ra1, next);
+ TAILQ_FOREACH(ra2, &sorted_routers, next) {
+ if (ra1->iface->metric < ra2->iface->metric)
+ continue;
+ if (ra1->expired && !ra2->expired)
+ continue;
+ if (ra1->lifetime == 0 && ra2->lifetime != 0)
+ continue;
+ if (!ra1->isreachable && ra2->reachable)
+ continue;
+ if (ipv6nd_rtpref(ra1) < ipv6nd_rtpref(ra2))
+ continue;
+ /* All things being equal, prefer older routers. */
+ if (timespeccmp(&ra1->acquired, &ra2->acquired, >=))
+ continue;
+ TAILQ_INSERT_BEFORE(ra2, ra1, next);
+ break;
+ }
+ if (ra2 == NULL)
+ TAILQ_INSERT_TAIL(&sorted_routers, ra1, next);
+ }
+
+ TAILQ_CONCAT(ctx->ra_routers, &sorted_routers, next);
+}
+
+static void
+ipv6nd_applyra(struct dhcpcd_ctx *ctx, struct interface *ifp)
+{
+ struct ra *rap;
+ struct rs_state *state = RS_STATE(ifp);
+
+ TAILQ_FOREACH(rap, ctx->ra_routers, next) {
+ if (rap->iface == ifp)
+ break;
+ }
+
+ if (rap == NULL)
+ return;
+
+ state->retrans = rap->retrans;
+ if (if_applyra(rap) == -1)
+ logerr(__func__);
+}
+
/*
* Neighbour reachability.
*
@@ -585,23 +652,20 @@ ipv6nd_neighbour(struct dhcpcd_ctx *ctx,
break;
}
- if (rap == NULL || rap->expired)
+ if (rap == NULL || rap->expired || rap->reachable == reachable)
return;
- if (reachable) {
- if (rap->isreachable)
- return;
- loginfox("%s: %s is reachable again",
- rap->iface->name, rap->sfrom);
- rap->isreachable = true;
+ rap->isreachable = reachable;
+ loginfox("%s: %s is %s", rap->iface->name, rap->sfrom,
+ reachable ? "reachable again" : "unreachable");
+
+ /* See if we can install a reachable default router. */
+ ipv6nd_sortrouters(ctx);
+ ipv6nd_applyra(ctx, rap->iface);
+ rt_build(ctx, AF_INET6);
+
+ if (reachable)
return;
- } else {
- if (!rap->isreachable)
- return;
- logwarnx("%s: %s is unreachable",
- rap->iface->name, rap->sfrom);
- rap->isreachable = false;
- }
/* If we have no reachable default routers, try and solicit one. */
TAILQ_FOREACH(rapr, ctx->ra_routers, next) {
@@ -723,42 +787,6 @@ ipv6nd_free(struct interface *ifp)
}
static int
-rtpref(struct ra *rap)
-{
-
- switch (rap->flags & ND_RA_FLAG_RTPREF_MASK) {
- case ND_RA_FLAG_RTPREF_HIGH:
- return (RTPREF_HIGH);
- case ND_RA_FLAG_RTPREF_MEDIUM:
- case ND_RA_FLAG_RTPREF_RSV:
- return (RTPREF_MEDIUM);
- case ND_RA_FLAG_RTPREF_LOW:
- return (RTPREF_LOW);
- default:
- logerrx("rtpref: impossible RA flag %x", rap->flags);
- return (RTPREF_INVALID);
- }
- /* NOTREACHED */
-}
-
-static void
-add_router(struct dhcpcd_ctx *ctx, struct ra *router)
-{
- struct ra *rap;
-
- TAILQ_FOREACH(rap, ctx->ra_routers, next) {
- if (router->iface->metric < rap->iface->metric ||
- (router->iface->metric == rap->iface->metric &&
- rtpref(router) > rtpref(rap)))
- {
- TAILQ_INSERT_BEFORE(rap, router, next);
- return;
- }
- }
- TAILQ_INSERT_TAIL(ctx->ra_routers, router, next);
-}
-
-static int
ipv6nd_scriptrun(struct ra *rap)
{
int hasdns, hasaddress, pid;
@@ -965,6 +993,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
struct dhcp_opt *dho;
bool new_rap, new_data, has_address;
uint32_t old_lifetime;
+ int ifmtu;
__printflike(1, 2) void (*logfunc)(const char *, ...);
#ifdef IPV6_MANAGETEMPADDR
uint8_t new_ap;
@@ -1074,20 +1103,25 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
if (!new_rap && rap->lifetime == 0 && old_lifetime != 0)
logwarnx("%s: %s: no longer a default router",
ifp->name, rap->sfrom);
- if (nd_ra->nd_ra_reachable) {
+ if (nd_ra->nd_ra_curhoplimit != 0)
+ rap->hoplimit = nd_ra->nd_ra_curhoplimit;
+ else
+ rap->hoplimit = IPV6_DEFHLIM;
+ if (nd_ra->nd_ra_reachable != 0) {
rap->reachable = ntohl(nd_ra->nd_ra_reachable);
if (rap->reachable > MAX_REACHABLE_TIME)
rap->reachable = 0;
- }
- if (nd_ra->nd_ra_retransmit) {
- struct rs_state *state = RS_STATE(ifp);
-
- state->retrans = rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
- }
+ } else
+ rap->reachable = REACHABLE_TIME;
+ if (nd_ra->nd_ra_retransmit != 0)
+ rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
+ else
+ rap->retrans = RETRANS_TIMER;
rap->expired = false;
rap->hasdns = false;
rap->isreachable = true;
has_address = false;
+ rap->mtu = 0;
#ifdef IPV6_AF_TEMPORARY
ipv6_markaddrsstale(ifp, IPV6_AF_TEMPORARY);
@@ -1245,22 +1279,30 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
case ND_OPT_MTU:
if (len < sizeof(mtu)) {
- logerrx("%s: short MTU option", ifp->name);
+ logfunc("%s: short MTU option", ifp->name);
break;
}
memcpy(&mtu, p, sizeof(mtu));
mtu.nd_opt_mtu_mtu = ntohl(mtu.nd_opt_mtu_mtu);
if (mtu.nd_opt_mtu_mtu < IPV6_MMTU) {
- logerrx("%s: invalid MTU %d",
+ logfunc("%s: invalid MTU %d",
ifp->name, mtu.nd_opt_mtu_mtu);
break;
}
- rap->mtu = mtu.nd_opt_mtu_mtu;
+ ifmtu = if_getmtu(ifp);
+ if (ifmtu == -1)
+ logerr("if_getmtu");
+ else if (mtu.nd_opt_mtu_mtu > (uint32_t)ifmtu) {
+ logfunc("%s: advertised MTU %d"
+ " is greater than link MTU %d",
+ ifp->name, mtu.nd_opt_mtu_mtu, ifmtu);
+ rap->mtu = (uint32_t)ifmtu;
+ } else
+ rap->mtu = mtu.nd_opt_mtu_mtu;
break;
-
case ND_OPT_RDNSS:
if (len < sizeof(rdnss)) {
- logerrx("%s: short RDNSS option", ifp->name);
+ logfunc("%s: short RDNSS option", ifp->name);
break;
}
memcpy(&rdnss, p, sizeof(rdnss));
@@ -1295,12 +1337,15 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
ifp->name);
if (new_rap)
- add_router(ifp->ctx, rap);
+ TAILQ_INSERT_TAIL(ctx->ra_routers, rap, next);
+ if (new_data)
+ ipv6nd_sortrouters(ifp->ctx);
if (ifp->ctx->options & DHCPCD_TEST) {
script_runreason(ifp, "TEST");
goto handle_flag;
}
+ ipv6nd_applyra(ifp->ctx, ifp);
ipv6_addaddrs(&rap->addrs);
#ifdef IPV6_MANAGETEMPADDR
ipv6_addtempaddrs(ifp, &rap->acquired);
@@ -1719,70 +1764,37 @@ ipv6nd_drop(struct interface *ifp)
}
static void
-ipv6nd_handledata(void *arg)
+ipv6nd_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg)
{
- struct dhcpcd_ctx *ctx;
- int s;
- struct sockaddr_in6 from;
- unsigned char buf[64 * 1024]; /* Maximum ICMPv6 size */
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = sizeof(buf),
- };
- unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))] = { 0 };
- struct msghdr msg = {
- .msg_name = &from, .msg_namelen = sizeof(from),
- .msg_iov = &iov, .msg_iovlen = 1,
- .msg_control = ctl, .msg_controllen = sizeof(ctl),
- };
- ssize_t len;
+ struct sockaddr_in6 *from = (struct sockaddr_in6 *)msg->msg_name;
char sfrom[INET6_ADDRSTRLEN];
int hoplimit = 0;
struct icmp6_hdr *icp;
struct interface *ifp;
+ size_t len = msg->msg_iov[0].iov_len;
-#ifdef __sun
- struct rs_state *state;
-
- ifp = arg;
- state = RS_STATE(ifp);
- ctx = ifp->ctx;
- s = state->nd_fd;
-#else
- ctx = arg;
- s = ctx->nd_fd;
-#endif
- len = recvmsg(s, &msg, 0);
- if (len == -1) {
- logerr(__func__);
- return;
- }
- inet_ntop(AF_INET6, &from.sin6_addr, sfrom, sizeof(sfrom));
+ inet_ntop(AF_INET6, &from->sin6_addr, sfrom, sizeof(sfrom));
if ((size_t)len < sizeof(struct icmp6_hdr)) {
logerrx("IPv6 ICMP packet too short from %s", sfrom);
return;
}
-#ifdef __sun
- if_findifpfromcmsg(ctx, &msg, &hoplimit);
-#else
- ifp = if_findifpfromcmsg(ctx, &msg, &hoplimit);
+ ifp = if_findifpfromcmsg(ctx, msg, &hoplimit);
if (ifp == NULL) {
logerr(__func__);
return;
}
-#endif
/* Don't do anything if the user hasn't configured it. */
if (ifp->active != IF_ACTIVE_USER ||
!(ifp->options->options & DHCPCD_IPV6))
return;
- icp = (struct icmp6_hdr *)buf;
+ icp = (struct icmp6_hdr *)msg->msg_iov[0].iov_base;
if (icp->icmp6_code == 0) {
switch(icp->icmp6_type) {
case ND_ROUTER_ADVERT:
- ipv6nd_handlera(ctx, &from, sfrom,
+ ipv6nd_handlera(ctx, from, sfrom,
ifp, icp, (size_t)len, hoplimit);
return;
}
@@ -1793,6 +1805,47 @@ ipv6nd_handledata(void *arg)
}
static void
+ipv6nd_handledata(void *arg)
+{
+ struct dhcpcd_ctx *ctx;
+ int fd;
+ struct sockaddr_in6 from;
+ unsigned char buf[64 * 1024]; /* Maximum ICMPv6 size */
+ struct iovec iov = {
+ .iov_base = buf,
+ .iov_len = sizeof(buf),
+ };
+ unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))] = { 0 };
+ struct msghdr msg = {
+ .msg_name = &from, .msg_namelen = sizeof(from),
+ .msg_iov = &iov, .msg_iovlen = 1,
+ .msg_control = ctl, .msg_controllen = sizeof(ctl),
+ };
+ ssize_t len;
+
+#ifdef __sun
+ struct interface *ifp;
+ struct rs_state *state;
+
+ ifp = arg;
+ state = RS_STATE(ifp);
+ ctx = ifp->ctx;
+ fd = state->nd_fd;
+#else
+ ctx = arg;
+ fd = ctx->nd_fd;
+#endif
+ len = recvmsg(fd, &msg, 0);
+ if (len == -1) {
+ logerr(__func__);
+ return;
+ }
+
+ iov.iov_len = (size_t)len;
+ ipv6nd_recvmsg(ctx, &msg);
+}
+
+static void
ipv6nd_startrs1(void *arg)
{
struct interface *ifp = arg;