Module Name:    src
Committed By:   martin
Date:           Sun Apr 12 08:29:41 UTC 2020

Modified Files:
        src/doc [netbsd-9]: 3RDPARTY
        src/external/bsd/dhcpcd/dist/src [netbsd-9]: arp.c arp.h bpf.c bpf.h
            common.h defs.h dhcp.c dhcp6.c dhcp6.h dhcpcd.c eloop.h if-bsd.c
            if-options.c if.c if.h ipv4ll.c ipv6.c ipv6nd.c ipv6nd.h logerr.c
            logerr.h

Log Message:
Apply patch, requested by roy in ticket #825:

        external/bsd/dhcpcd/dist/src/arp.c              (apply patch)
        external/bsd/dhcpcd/dist/src/arp.h              (apply patch)
        external/bsd/dhcpcd/dist/src/bpf.c              (apply patch)
        external/bsd/dhcpcd/dist/src/bpf.h              (apply patch)
        external/bsd/dhcpcd/dist/src/common.h           (apply patch)
        external/bsd/dhcpcd/dist/src/defs.h             (apply patch)
        external/bsd/dhcpcd/dist/src/dhcp.c             (apply patch)
        external/bsd/dhcpcd/dist/src/dhcp6.c            (apply patch)
        external/bsd/dhcpcd/dist/src/dhcp6.h            (apply patch)
        external/bsd/dhcpcd/dist/src/dhcpcd.c           (apply patch)
        external/bsd/dhcpcd/dist/src/eloop.h            (apply patch)
        external/bsd/dhcpcd/dist/src/if-bsd.c           (apply patch)
        external/bsd/dhcpcd/dist/src/if-options.c       (apply patch)
        external/bsd/dhcpcd/dist/src/if.c               (apply patch)
        external/bsd/dhcpcd/dist/src/if.h               (apply patch)
        external/bsd/dhcpcd/dist/src/ipv4ll.c           (apply patch)
        external/bsd/dhcpcd/dist/src/ipv6.c             (apply patch)
        external/bsd/dhcpcd/dist/src/ipv6nd.c           (apply patch)
        external/bsd/dhcpcd/dist/src/ipv6nd.h           (apply patch)
        external/bsd/dhcpcd/dist/src/logerr.c           (apply patch)
        external/bsd/dhcpcd/dist/src/logerr.h           (apply patch)
        doc/3RDPARTY                                    (apply patch)

Update to dhcpcd-8.1.7 which fixes the following issues:
* Decode interface complex interface names eth0.100:2 eth0i100:2.
  This allows us to ignore some virtual interfaces by default
* ARP: Report L2 header address on conflict for more clarity
* DHCP: Support jumbo frames (untested)
* DHCP6: Clean up old lease on failure to confirm/rebind, etc
* RA: Prefer older routers - fixes PR bin/54997
* INET6: Obscure prefixes are now calculated correctly
* macro logerr commands to allow an alternative logger


To generate a diff of this commit:
cvs rdiff -u -r1.1640.2.12 -r1.1640.2.13 src/doc/3RDPARTY
cvs rdiff -u -r1.1.1.11.2.2 -r1.1.1.11.2.3 \
    src/external/bsd/dhcpcd/dist/src/arp.c
cvs rdiff -u -r1.1.1.8.2.1 -r1.1.1.8.2.2 \
    src/external/bsd/dhcpcd/dist/src/arp.h \
    src/external/bsd/dhcpcd/dist/src/common.h
cvs rdiff -u -r1.11.2.2 -r1.11.2.3 src/external/bsd/dhcpcd/dist/src/bpf.c
cvs rdiff -u -r1.1.1.6.2.1 -r1.1.1.6.2.2 \
    src/external/bsd/dhcpcd/dist/src/bpf.h
cvs rdiff -u -r1.1.1.25.2.6 -r1.1.1.25.2.7 \
    src/external/bsd/dhcpcd/dist/src/defs.h
cvs rdiff -u -r1.23.2.6 -r1.23.2.7 src/external/bsd/dhcpcd/dist/src/dhcp.c
cvs rdiff -u -r1.11.2.4 -r1.11.2.5 src/external/bsd/dhcpcd/dist/src/dhcp6.c
cvs rdiff -u -r1.1.1.12 -r1.1.1.12.2.1 \
    src/external/bsd/dhcpcd/dist/src/dhcp6.h
cvs rdiff -u -r1.23.2.5 -r1.23.2.6 src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.1.1.5.2.1 -r1.1.1.5.2.2 \
    src/external/bsd/dhcpcd/dist/src/eloop.h
cvs rdiff -u -r1.10.2.4 -r1.10.2.5 src/external/bsd/dhcpcd/dist/src/if-bsd.c
cvs rdiff -u -r1.16.2.3 -r1.16.2.4 \
    src/external/bsd/dhcpcd/dist/src/if-options.c
cvs rdiff -u -r1.1.1.14.2.3 -r1.1.1.14.2.4 \
    src/external/bsd/dhcpcd/dist/src/if.c
cvs rdiff -u -r1.1.1.10.2.3 -r1.1.1.10.2.4 \
    src/external/bsd/dhcpcd/dist/src/if.h
cvs rdiff -u -r1.1.1.9.2.1 -r1.1.1.9.2.2 \
    src/external/bsd/dhcpcd/dist/src/ipv4ll.c
cvs rdiff -u -r1.3.2.5 -r1.3.2.6 src/external/bsd/dhcpcd/dist/src/ipv6.c
cvs rdiff -u -r1.10.2.5 -r1.10.2.6 src/external/bsd/dhcpcd/dist/src/ipv6nd.c
cvs rdiff -u -r1.1.1.10.2.2 -r1.1.1.10.2.3 \
    src/external/bsd/dhcpcd/dist/src/ipv6nd.h
cvs rdiff -u -r1.2 -r1.2.2.1 src/external/bsd/dhcpcd/dist/src/logerr.c
cvs rdiff -u -r1.1.1.5 -r1.1.1.5.2.1 \
    src/external/bsd/dhcpcd/dist/src/logerr.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/doc/3RDPARTY
diff -u src/doc/3RDPARTY:1.1640.2.12 src/doc/3RDPARTY:1.1640.2.13
--- src/doc/3RDPARTY:1.1640.2.12	Tue Jan 28 09:48:33 2020
+++ src/doc/3RDPARTY	Sun Apr 12 08:29:40 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: 3RDPARTY,v 1.1640.2.12 2020/01/28 09:48:33 martin Exp $
+#	$NetBSD: 3RDPARTY,v 1.1640.2.13 2020/04/12 08:29:40 martin Exp $
 #
 # This file contains a list of the software that has been integrated into
 # NetBSD where we are not the primary maintainer.
@@ -341,12 +341,12 @@ Notes:
 Use the dhcp2netbsd script.
 
 Package:	dhcpcd
-Version:	8.1.6
-Current Vers:	8.1.6
+Version:	8.1.7
+Current Vers:	8.1.7
 Maintainer:	roy
 Archive Site:	ftp://roy.marples.name/pub/dhcpcd/
 Home Page:	http://roy.marples.name/projects/dhcpcd/
-Date:		2020-01-27
+Date:		2020-04-10
 Mailing List: 	dhcpcd-disc...@marples.name
 License:	BSD (2-clause)
 Location:	external/bsd/dhcpcd/dist

Index: src/external/bsd/dhcpcd/dist/src/arp.c
diff -u src/external/bsd/dhcpcd/dist/src/arp.c:1.1.1.11.2.2 src/external/bsd/dhcpcd/dist/src/arp.c:1.1.1.11.2.3
--- src/external/bsd/dhcpcd/dist/src/arp.c:1.1.1.11.2.2	Fri Nov 22 08:01:49 2019
+++ src/external/bsd/dhcpcd/dist/src/arp.c	Sun Apr 12 08:29:40 2020
@@ -41,7 +41,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#define ELOOP_QUEUE 5
+#define ELOOP_QUEUE	ELOOP_ARP
 #include "config.h"
 #include "arp.h"
 #include "bpf.h"
@@ -55,8 +55,9 @@
 #include "logerr.h"
 
 #if defined(ARP)
-#define ARP_LEN								      \
-	(sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
+#define ARP_LEN								\
+	(FRAMEHDRLEN_MAX +						\
+	 sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
 
 /* ARP debugging can be quite noisy. Enable this for more noise! */
 //#define	ARP_DEBUG
@@ -115,7 +116,8 @@ static void
 arp_report_conflicted(const struct arp_state *astate,
     const struct arp_msg *amsg)
 {
-	char buf[HWADDR_LEN * 3];
+	char abuf[HWADDR_LEN * 3];
+	char fbuf[HWADDR_LEN * 3];
 
 	if (amsg == NULL) {
 		logerrx("%s: DAD detected %s",
@@ -123,9 +125,16 @@ arp_report_conflicted(const struct arp_s
 		return;
 	}
 
-	logerrx("%s: hardware address %s claims %s",
-	    astate->iface->name,
-	    hwaddr_ntoa(amsg->sha, astate->iface->hwlen, buf, sizeof(buf)),
+	hwaddr_ntoa(amsg->sha, astate->iface->hwlen, abuf, sizeof(abuf));
+	if (bpf_frame_header_len(astate->iface) == 0) {
+		logerrx("%s: %s claims %s",
+		    astate->iface->name, abuf, inet_ntoa(astate->addr));
+		return;
+	}
+
+	logerrx("%s: %s(%s) claims %s",
+	    astate->iface->name, abuf,
+	    hwaddr_ntoa(amsg->fsha, astate->iface->hwlen, fbuf, sizeof(fbuf)),
 	    inet_ntoa(astate->addr));
 }
 
@@ -209,6 +218,7 @@ arp_validate(const struct interface *ifp
 static void
 arp_packet(struct interface *ifp, uint8_t *data, size_t len)
 {
+	size_t fl = bpf_frame_header_len(ifp), falen;
 	const struct interface *ifn;
 	struct arphdr ar;
 	struct arp_msg arm;
@@ -216,6 +226,21 @@ arp_packet(struct interface *ifp, uint8_
 	struct arp_state *astate, *astaten;
 	uint8_t *hw_s, *hw_t;
 
+	/* Copy the frame header source and destination out */
+	memset(&arm, 0, sizeof(arm));
+	if (fl != 0) {
+		hw_s = bpf_frame_header_src(ifp, data, &falen);
+		if (hw_s != NULL && falen <= sizeof(arm.fsha))
+			memcpy(arm.fsha, hw_s, falen);
+		hw_t = bpf_frame_header_dst(ifp, data, &falen);
+		if (hw_t != NULL && falen <= sizeof(arm.ftha))
+			memcpy(arm.ftha, hw_t, falen);
+
+		/* Skip past the frame header */
+		data += fl;
+		len -= fl;
+	}
+
 	/* We must have a full ARP header */
 	if (len < sizeof(ar))
 		return;

Index: src/external/bsd/dhcpcd/dist/src/arp.h
diff -u src/external/bsd/dhcpcd/dist/src/arp.h:1.1.1.8.2.1 src/external/bsd/dhcpcd/dist/src/arp.h:1.1.1.8.2.2
--- src/external/bsd/dhcpcd/dist/src/arp.h:1.1.1.8.2.1	Fri Nov 22 08:01:49 2019
+++ src/external/bsd/dhcpcd/dist/src/arp.h	Sun Apr 12 08:29:40 2020
@@ -54,10 +54,13 @@
 
 struct arp_msg {
 	uint16_t op;
-	unsigned char sha[HWADDR_LEN];
+	uint8_t sha[HWADDR_LEN];
 	struct in_addr sip;
-	unsigned char tha[HWADDR_LEN];
+	uint8_t tha[HWADDR_LEN];
 	struct in_addr tip;
+	/* Frame header and sender to diagnose failures */
+	uint8_t fsha[HWADDR_LEN];
+	uint8_t ftha[HWADDR_LEN];
 };
 
 struct arp_state {
Index: src/external/bsd/dhcpcd/dist/src/common.h
diff -u src/external/bsd/dhcpcd/dist/src/common.h:1.1.1.8.2.1 src/external/bsd/dhcpcd/dist/src/common.h:1.1.1.8.2.2
--- src/external/bsd/dhcpcd/dist/src/common.h:1.1.1.8.2.1	Sat Oct 12 14:44:32 2019
+++ src/external/bsd/dhcpcd/dist/src/common.h	Sun Apr 12 08:29:40 2020
@@ -34,6 +34,16 @@
 #include <stdint.h>
 #include <stdio.h>
 
+/* Define eloop queues here, as other apps share eloop.h */
+#define	ELOOP_DHCPCD		1 /* default queue */
+#define	ELOOP_DHCP		2
+#define	ELOOP_ARP		3
+#define	ELOOP_IPV4LL		4
+#define	ELOOP_IPV6		5
+#define	ELOOP_IPV6ND		6
+#define	ELOOP_IPV6RA_EXPIRE	7
+#define	ELOOP_DHCP6		8
+
 #ifndef HOSTNAME_MAX_LEN
 #define HOSTNAME_MAX_LEN	250	/* 255 - 3 (FQDN) - 2 (DNS enc) */
 #endif

Index: src/external/bsd/dhcpcd/dist/src/bpf.c
diff -u src/external/bsd/dhcpcd/dist/src/bpf.c:1.11.2.2 src/external/bsd/dhcpcd/dist/src/bpf.c:1.11.2.3
--- src/external/bsd/dhcpcd/dist/src/bpf.c:1.11.2.2	Sat Oct 12 14:44:32 2019
+++ src/external/bsd/dhcpcd/dist/src/bpf.c	Sun Apr 12 08:29:40 2020
@@ -93,6 +93,38 @@ bpf_frame_header_len(const struct interf
 	}
 }
 
+void *
+bpf_frame_header_src(const struct interface *ifp, void *fh, size_t *len)
+{
+	uint8_t *f = fh;
+
+	switch (ifp->family) {
+	case ARPHRD_ETHER:
+		*len = sizeof(((struct ether_header *)0)->ether_shost);
+		return f + offsetof(struct ether_header, ether_shost);
+	default:
+		*len = 0;
+		errno =	ENOTSUP;
+		return NULL;
+	}
+}
+
+void *
+bpf_frame_header_dst(const struct interface *ifp, void *fh, size_t *len)
+{
+	uint8_t *f = fh;
+
+	switch (ifp->family) {
+	case ARPHRD_ETHER:
+		*len = sizeof(((struct ether_header *)0)->ether_dhost);
+		return f + offsetof(struct ether_header, ether_dhost);
+	default:
+		*len = 0;
+		errno =	ENOTSUP;
+		return NULL;
+	}
+}
+
 static const uint8_t etherbcastaddr[] =
     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
@@ -215,7 +247,6 @@ ssize_t
 bpf_read(struct interface *ifp, int fd, void *data, size_t len,
     unsigned int *flags)
 {
-	ssize_t fl = (ssize_t)bpf_frame_header_len(ifp);
 	ssize_t bytes;
 	struct ipv4_state *state = IPV4_STATE(ifp);
 
@@ -250,10 +281,10 @@ bpf_read(struct interface *ifp, int fd, 
 			*flags |= BPF_BCAST;
 		else
 			*flags &= ~BPF_BCAST;
-		payload += fl;
-		bytes = (ssize_t)packet.bh_caplen - fl;
-		if ((size_t)bytes > len)
+		if (packet.bh_caplen > len)
 			bytes = (ssize_t)len;
+		else
+			bytes = (ssize_t)packet.bh_caplen;
 		memcpy(data, payload, (size_t)bytes);
 next:
 		state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen +

Index: src/external/bsd/dhcpcd/dist/src/bpf.h
diff -u src/external/bsd/dhcpcd/dist/src/bpf.h:1.1.1.6.2.1 src/external/bsd/dhcpcd/dist/src/bpf.h:1.1.1.6.2.2
--- src/external/bsd/dhcpcd/dist/src/bpf.h:1.1.1.6.2.1	Sat Oct 12 14:44:32 2019
+++ src/external/bsd/dhcpcd/dist/src/bpf.h	Sun Apr 12 08:29:40 2020
@@ -57,6 +57,8 @@
 
 extern const char *bpf_name;
 size_t bpf_frame_header_len(const struct interface *);
+void *bpf_frame_header_src(const struct interface *, void *, size_t *);
+void *bpf_frame_header_dst(const struct interface *, void *, size_t *);
 int bpf_frame_bcast(const struct interface *, const char *frame);
 int bpf_open(struct interface *, int (*)(struct interface *, int));
 int bpf_close(struct interface *, int);

Index: src/external/bsd/dhcpcd/dist/src/defs.h
diff -u src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.25.2.6 src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.25.2.7
--- src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.25.2.6	Tue Jan 28 09:48:34 2020
+++ src/external/bsd/dhcpcd/dist/src/defs.h	Sun Apr 12 08:29:40 2020
@@ -29,7 +29,7 @@
 #define CONFIG_H
 
 #define PACKAGE			"dhcpcd"
-#define VERSION			"8.1.6"
+#define VERSION			"8.1.7"
 
 #ifndef CONFIG
 # define CONFIG			SYSCONFDIR "/" PACKAGE ".conf"

Index: src/external/bsd/dhcpcd/dist/src/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.23.2.6 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.23.2.7
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.23.2.6	Tue Jan 28 09:48:34 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c	Sun Apr 12 08:29:40 2020
@@ -56,8 +56,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <syslog.h>
 
-#define ELOOP_QUEUE 2
+#define ELOOP_QUEUE	ELOOP_DHCP
 #include "config.h"
 #include "arp.h"
 #include "bpf.h"
@@ -2758,7 +2759,7 @@ whitelisted_ip(const struct if_options *
 }
 
 static void
-log_dhcp(logfunc_t *logfunc, const char *msg,
+log_dhcp(int loglevel, const char *msg,
     const struct interface *ifp, const struct bootp *bootp, size_t bootp_len,
     const struct in_addr *from, int ad)
 {
@@ -2805,10 +2806,10 @@ log_dhcp(logfunc_t *logfunc, const char 
 		print_string(sname, sizeof(sname), OT_STRING | OT_DOMAIN,
 		    bootp->sname, sizeof(bootp->sname));
 		if (a == NULL)
-			logfunc("%s: %s %s %s `%s'",
+			logmessage(loglevel, "%s: %s %s %s `%s'",
 			    ifp->name, msg, tfrom, inet_ntoa(addr), sname);
 		else
-			logfunc("%s: %s %s %s %s `%s'",
+			logmessage(loglevel, "%s: %s %s %s %s `%s'",
 			    ifp->name, msg, a, tfrom, inet_ntoa(addr), sname);
 	} else {
 		if (r != 0) {
@@ -2816,10 +2817,10 @@ log_dhcp(logfunc_t *logfunc, const char 
 			addr = *from;
 		}
 		if (a == NULL)
-			logfunc("%s: %s %s %s",
+			logmessage(loglevel, "%s: %s %s %s",
 			    ifp->name, msg, tfrom, inet_ntoa(addr));
 		else
-			logfunc("%s: %s %s %s %s",
+			logmessage(loglevel, "%s: %s %s %s %s",
 			    ifp->name, msg, a, tfrom, inet_ntoa(addr));
 	}
 	free(a);
@@ -2949,7 +2950,7 @@ dhcp_handledhcp(struct interface *ifp, s
 		    (uint8_t *)bootp, bootp_len, 4, type,
 		    auth, auth_len) == NULL)
 		{
-			LOGDHCP0(logerrx, "authentication failed");
+			LOGDHCP0(LOG_ERR, "authentication failed");
 			return;
 		}
 		if (state->auth.token)
@@ -2959,10 +2960,10 @@ dhcp_handledhcp(struct interface *ifp, s
 			loginfox("%s: accepted reconfigure key", ifp->name);
 	} else if (ifo->auth.options & DHCPCD_AUTH_SEND) {
 		if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) {
-			LOGDHCP0(logerrx, "no authentication");
+			LOGDHCP0(LOG_ERR, "no authentication");
 			return;
 		}
-		LOGDHCP0(logwarnx, "no authentication");
+		LOGDHCP0(LOG_WARNING, "no authentication");
 	}
 #endif
 
@@ -2971,20 +2972,20 @@ dhcp_handledhcp(struct interface *ifp, s
 		if (from->s_addr == INADDR_ANY ||
 		    from->s_addr == INADDR_BROADCAST)
 		{
-			LOGDHCP(logerrx, "discarding Force Renew");
+			LOGDHCP(LOG_ERR, "discarding Force Renew");
 			return;
 		}
 #ifdef AUTH
 		if (auth == NULL) {
-			LOGDHCP(logerrx, "unauthenticated Force Renew");
+			LOGDHCP(LOG_ERR, "unauthenticated Force Renew");
 			if (ifo->auth.options & DHCPCD_AUTH_REQUIRE)
 				return;
 		}
 		if (state->state != DHS_BOUND && state->state != DHS_INFORM) {
-			LOGDHCP(logdebugx, "not bound, ignoring Force Renew");
+			LOGDHCP(LOG_DEBUG, "not bound, ignoring Force Renew");
 			return;
 		}
-		LOGDHCP(loginfox, "Force Renew from");
+		LOGDHCP(LOG_INFO, "Force Renew from");
 		/* The rebind and expire timings are still the same, we just
 		 * enter the renew state early */
 		if (state->state == DHS_BOUND)
@@ -2995,19 +2996,19 @@ dhcp_handledhcp(struct interface *ifp, s
 			dhcp_inform(ifp);
 		}
 #else
-		LOGDHCP(logerrx, "unauthenticated Force Renew");
+		LOGDHCP(LOG_ERR, "unauthenticated Force Renew");
 #endif
 		return;
 	}
 
 	if (state->state == DHS_BOUND) {
-		LOGDHCP(logdebugx, "bound, ignoring");
+		LOGDHCP(LOG_DEBUG, "bound, ignoring");
 		return;
 	}
 
 	if (state->state == DHS_PROBE) {
 		/* Ignore any DHCP messages whilst probing a lease to bind. */
-		LOGDHCP(logdebugx, "probing, ignoring");
+		LOGDHCP(LOG_DEBUG, "probing, ignoring");
 		return;
 	}
 
@@ -3020,7 +3021,7 @@ dhcp_handledhcp(struct interface *ifp, s
 		    get_option_uint8(ifp->ctx, &tmp,
 		    bootp, bootp_len, (uint8_t)i) == 0)
 		{
-			LOGDHCP(logwarnx, "reject DHCP");
+			LOGDHCP(LOG_WARNING, "reject DHCP");
 			return;
 		}
 	}
@@ -3031,12 +3032,12 @@ dhcp_handledhcp(struct interface *ifp, s
 		    get_option_addr(ifp->ctx, &addr,
 		    bootp, bootp_len, DHO_SERVERID) == -1)
 		{
-			LOGDHCP(logwarnx, "reject NAK");
+			LOGDHCP(LOG_WARNING, "reject NAK");
 			return;
 		}
 
 		/* We should restart on a NAK */
-		LOGDHCP(logwarnx, "NAK:");
+		LOGDHCP(LOG_WARNING, "NAK:");
 		if ((msg = get_option_string(ifp->ctx,
 		    bootp, bootp_len, DHO_MESSAGE)))
 		{
@@ -3076,14 +3077,14 @@ dhcp_handledhcp(struct interface *ifp, s
 			 * always true. */
 			if (type == 0 && i == DHO_SERVERID)
 				continue;
-			LOGDHCP(logwarnx, "reject DHCP");
+			LOGDHCP(LOG_WARNING, "reject DHCP");
 			return;
 		}
 	}
 
 	/* DHCP Auto-Configure, RFC 2563 */
 	if (type == DHCP_OFFER && bootp->yiaddr == 0) {
-		LOGDHCP(logwarnx, "no address given");
+		LOGDHCP(LOG_WARNING, "no address given");
 		if ((msg = get_option_string(ifp->ctx,
 		    bootp, bootp_len, DHO_MESSAGE)))
 		{
@@ -3097,14 +3098,14 @@ dhcp_handledhcp(struct interface *ifp, s
 		{
 			switch (tmp) {
 			case 0:
-				LOGDHCP(logwarnx, "IPv4LL disabled from");
+				LOGDHCP(LOG_WARNING, "IPv4LL disabled from");
 				ipv4ll_drop(ifp);
 #ifdef ARP
 				arp_drop(ifp);
 #endif
 				break;
 			case 1:
-				LOGDHCP(logwarnx, "IPv4LL enabled from");
+				LOGDHCP(LOG_WARNING, "IPv4LL enabled from");
 				ipv4ll_start(ifp);
 				break;
 			default:
@@ -3127,14 +3128,14 @@ dhcp_handledhcp(struct interface *ifp, s
 	    &&
 	    (bootp->yiaddr == INADDR_ANY || bootp->yiaddr == INADDR_BROADCAST))
 	{
-		LOGDHCP(logwarnx, "reject invalid address");
+		LOGDHCP(LOG_WARNING, "reject invalid address");
 		return;
 	}
 
 #ifdef IN_IFF_DUPLICATED
 	ia = ipv4_iffindaddr(ifp, &lease->addr, NULL);
 	if (ia && ia->addr_flags & IN_IFF_DUPLICATED) {
-		LOGDHCP(logwarnx, "declined duplicate address");
+		LOGDHCP(LOG_WARNING, "declined duplicate address");
 		if (type)
 			dhcp_decline(ifp);
 		ipv4_deladdr(ia, 0);
@@ -3165,7 +3166,7 @@ dhcp_handledhcp(struct interface *ifp, s
 			goto rapidcommit;
 		}
 
-		LOGDHCP(loginfox, "offered");
+		LOGDHCP(LOG_INFO, "offered");
 		if (state->offer_len < bootp_len) {
 			free(state->offer);
 			if ((state->offer = malloc(bootp_len)) == NULL) {
@@ -3207,13 +3208,13 @@ dhcp_handledhcp(struct interface *ifp, s
 
 	if (type) {
 		if (type == DHCP_OFFER) {
-			LOGDHCP(logwarnx, "ignoring offer of");
+			LOGDHCP(LOG_WARNING, "ignoring offer of");
 			return;
 		}
 
 		/* We should only be dealing with acks */
 		if (type != DHCP_ACK) {
-			LOGDHCP(logerr, "not ACK or OFFER");
+			LOGDHCP(LOG_ERR, "not ACK or OFFER");
 			return;
 		}
 
@@ -3225,14 +3226,14 @@ dhcp_handledhcp(struct interface *ifp, s
 			    DHO_RAPIDCOMMIT, NULL))
 				state->state = DHS_REQUEST;
 			else {
-				LOGDHCP(logdebugx, "ignoring ack of");
+				LOGDHCP(LOG_DEBUG, "ignoring ack of");
 				return;
 			}
 		}
 
 rapidcommit:
 		if (!(ifo->options & DHCPCD_INFORM))
-			LOGDHCP(logdebugx, "acknowledged");
+			LOGDHCP(LOG_DEBUG, "acknowledged");
 		else
 		    ifo->options &= ~DHCPCD_STATIC;
 	}
@@ -3307,7 +3308,7 @@ is_packet_udp_bootp(void *packet, size_t
 	memcpy(&udp, (char *)ip + ip_hlen, sizeof(udp));
 	if (ntohs(udp.uh_ulen) < sizeof(udp))
 		return false;
-	if (ip_hlen + ntohs(udp.uh_ulen) > plen)
+	if (ip_hlen + (size_t)ntohs(udp.uh_ulen) > plen)
 		return false;
 
 	/* Check it's to and from the right ports. */
@@ -3432,9 +3433,10 @@ static void
 dhcp_readbpf(void *arg)
 {
 	struct interface *ifp = arg;
-	uint8_t buf[MTU_MAX];
+	uint8_t buf[FRAMELEN_MAX];
 	ssize_t bytes;
 	struct dhcp_state *state = D_STATE(ifp);
+	ssize_t fl = (ssize_t)bpf_frame_header_len(ifp);
 
 	/* Some RAW mechanisms are generic file descriptors, not sockets.
 	 * This means we have no kernel call to just get one packet,
@@ -3451,7 +3453,12 @@ dhcp_readbpf(void *arg)
 			}
 			break;
 		}
-		dhcp_packet(ifp, buf, (size_t)bytes);
+		if (bytes < fl) {
+			logerrx("%s: %s: short frame header",
+			    __func__, ifp->name);
+			break;
+		}
+		dhcp_packet(ifp, buf + fl, (size_t)(bytes - fl));
 		/* Check we still have a state after processing. */
 		if ((state = D_STATE(ifp)) == NULL)
 			break;

Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.11.2.4 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.11.2.5
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.11.2.4	Sun Jan  5 09:38:28 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c	Sun Apr 12 08:29:40 2020
@@ -44,8 +44,9 @@
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <syslog.h>
 
-#define ELOOP_QUEUE 4
+#define ELOOP_QUEUE	ELOOP_DHCP6
 #include "config.h"
 #include "common.h"
 #include "dhcp.h"
@@ -174,6 +175,12 @@ static void dhcp6_failinform(void *);
 static int dhcp6_openudp(unsigned int, struct in6_addr *);
 static void dhcp6_recvaddr(void *);
 
+#ifdef SMALL
+#define dhcp6_hasprefixdelegation(a)	(0)
+#else
+static int dhcp6_hasprefixdelegation(struct interface *);
+#endif
+
 void
 dhcp6_printoptions(const struct dhcpcd_ctx *ctx,
     const struct dhcp_opt *opts, size_t opts_len)
@@ -1551,11 +1558,12 @@ dhcp6_startdiscover(void *arg)
 	struct dhcp6_state *state;
 
 	ifp = arg;
+	state = D6_STATE(ifp);
 #ifndef SMALL
-	dhcp6_delete_delegates(ifp);
+	if (state->reason == NULL || strcmp(state->reason, "TIMEOUT6") != 0)
+		dhcp6_delete_delegates(ifp);
 #endif
 	loginfox("%s: soliciting a DHCPv6 lease", ifp->name);
-	state = D6_STATE(ifp);
 	state->state = DH6S_DISCOVER;
 	state->RTC = 0;
 	state->IMD = SOL_MAX_DELAY;
@@ -1606,8 +1614,37 @@ dhcp6_startinform(void *arg)
 	    INF_MAX_RD, dhcp6_failinform, ifp);
 }
 
+static bool
+dhcp6_startdiscoinform(struct interface *ifp)
+{
+	unsigned long long opts = ifp->options->options;
+
+	if (opts & DHCPCD_IA_FORCED || ipv6nd_hasradhcp(ifp, true))
+		dhcp6_startdiscover(ifp);
+	else if (opts & DHCPCD_INFORM6 || ipv6nd_hasradhcp(ifp, false))
+		dhcp6_startinform(ifp);
+	else
+		return false;
+	return true;
+}
+
 static void
-dhcp6_fail(struct interface *ifp)
+dhcp6_leaseextend(struct interface *ifp)
+{
+	struct dhcp6_state *state = D6_STATE(ifp);
+	struct ipv6_addr *ia;
+
+	logwarnx("%s: extending DHCPv6 lease", ifp->name);
+	TAILQ_FOREACH(ia, &state->addrs, next) {
+		ia->flags |= IPV6_AF_EXTENDED;
+		/* Set infinite lifetimes. */
+		ia->prefix_pltime = ND6_INFINITE_LIFETIME;
+		ia->prefix_vltime = ND6_INFINITE_LIFETIME;
+	}
+}
+
+static void
+dhcp6_fail(struct interface* ifp)
 {
 	struct dhcp6_state *state = D6_STATE(ifp);
 
@@ -1618,36 +1655,30 @@ dhcp6_fail(struct interface *ifp)
 	 * mobile clients.
 	 * dhcpcd also has LASTLEASE_EXTEND to extend this lease past it's
 	 * expiry, but this is strictly not RFC compliant in any way or form. */
-	if (state->new == NULL ||
-	    !(ifp->options->options & DHCPCD_LASTLEASE))
+	if (state->new != NULL &&
+	    ifp->options->options & DHCPCD_LASTLEASE_EXTEND)
 	{
+		dhcp6_leaseextend(ifp);
+		dhcp6_bind(ifp, NULL, NULL);
+	} else {
+		dhcp6_freedrop_addrs(ifp, 1, NULL);
 #ifndef SMALL
 		dhcp6_delete_delegates(ifp);
 #endif
-		if (state->state != DH6S_INFORM)
-			dhcp6_startdiscover(ifp);
-		return;
-	}
-
-	switch (state->state) {
-	case DH6S_INFORM:
-	case DH6S_INFORMED:
-		state->state = DH6S_ITIMEDOUT;
-		break;
-	default:
-		state->state = DH6S_TIMEDOUT;
-		break;
+		free(state->old);
+		state->old = state->new;
+		state->old_len = state->new_len;
+		state->new = NULL;
+		state->new_len = 0;
+		if (state->old != NULL)
+			script_runreason(ifp, "EXPIRE6");
+		unlink(state->leasefile);
 	}
 
-	dhcp6_bind(ifp, NULL, NULL);
-
-	switch (state->state) {
-	case DH6S_BOUND:
-	case DH6S_INFORMED:
-		break;
-	default:
-		dhcp6_startdiscover(ifp);
-		break;
+	if (!dhcp6_startdiscoinform(ifp)) {
+		logwarnx("%s: no advertising IPv6 router wants DHCP",ifp->name);
+		state->state = DH6S_INIT;
+		eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 	}
 }
 
@@ -1681,9 +1712,7 @@ dhcp6_failinform(void *arg)
 	dhcp6_fail(ifp);
 }
 
-#ifdef SMALL
-#define dhcp6_hasprefixdelegation(a)	(0)
-#else
+#ifndef SMALL
 static void
 dhcp6_failrebind(void *arg)
 {
@@ -1809,21 +1838,6 @@ dhcp6_startconfirm(struct interface *ifp
 }
 
 static void
-dhcp6_leaseextend(struct interface *ifp)
-{
-	struct dhcp6_state *state = D6_STATE(ifp);
-	struct ipv6_addr *ia;
-
-	logwarnx("%s: extending DHCPv6 lease", ifp->name);
-	TAILQ_FOREACH(ia, &state->addrs, next) {
-		ia->flags |= IPV6_AF_EXTENDED;
-		/* Set infinite lifetimes. */
-		ia->prefix_pltime = ND6_INFINITE_LIFETIME;
-		ia->prefix_vltime = ND6_INFINITE_LIFETIME;
-	}
-}
-
-static void
 dhcp6_startexpire(void *arg)
 {
 	struct interface *ifp;
@@ -1832,24 +1846,7 @@ dhcp6_startexpire(void *arg)
 	eloop_timeout_delete(ifp->ctx->eloop, dhcp6_sendrebind, ifp);
 
 	logerrx("%s: DHCPv6 lease expired", ifp->name);
-	if (ifp->options->options & DHCPCD_LASTLEASE_EXTEND) {
-		struct dhcp6_state *state = D6_STATE(ifp);
-
-		dhcp6_leaseextend(ifp);
-		ipv6_addaddrs(&state->addrs);
-	} else {
-		dhcp6_freedrop_addrs(ifp, 1, NULL);
-#ifndef SMALL
-		dhcp6_delete_delegates(ifp);
-#endif
-		script_runreason(ifp, "EXPIRE6");
-	}
-	if (!(ifp->options->options & DHCPCD_IPV6RS) ||
-	    ipv6nd_hasradhcp(ifp) ||
-	    dhcp6_hasprefixdelegation(ifp))
-		dhcp6_startdiscover(ifp);
-	else
-		logwarnx("%s: no advertising IPv6 router wants DHCP",ifp->name);
+	dhcp6_fail(ifp);
 }
 
 static void
@@ -1907,7 +1904,7 @@ dhcp6_checkstatusok(const struct interfa
 	void * (*f)(void *, size_t, uint16_t, uint16_t *), *farg;
 	char buf[32], *sbuf;
 	const char *status;
-	logfunc_t *logfunc;
+	int loglevel;
 
 	state = D6_STATE(ifp);
 	f = p ? dhcp6_findoption : dhcp6_findmoption;
@@ -1956,10 +1953,10 @@ dhcp6_checkstatusok(const struct interfa
 	}
 
 	if (state->lerror == code || state->state == DH6S_INIT)
-		logfunc = logdebugx;
+		loglevel = LOG_DEBUG;
 	else
-		logfunc = logerrx;
-	logfunc("%s: DHCPv6 REPLY: %s", ifp->name, status);
+		loglevel = LOG_ERR;
+	logmessage(loglevel, "%s: DHCPv6 REPLY: %s", ifp->name, status);
 	free(sbuf);
 	state->lerror = code;
 	errno = 0;
@@ -2407,7 +2404,7 @@ dhcp6_deprecateaddrs(struct ipv6_addrhea
 		if (ia->flags & IPV6_AF_REQUEST) {
 			ia->prefix_vltime = ia->prefix_pltime = 0;
 			eloop_q_timeout_delete(ia->iface->ctx->eloop,
-			    0, NULL, ia);
+			    ELOOP_QUEUE_ALL, NULL, ia);
 			continue;
 		}
 		TAILQ_REMOVE(addrs, ia, next);
@@ -2623,7 +2620,7 @@ dhcp6_startinit(struct interface *ifp)
 	{
 		r = dhcp6_readlease(ifp, 1);
 		if (r == -1) {
-			if (errno != ENOENT)
+			if (errno != ENOENT && errno != ESRCH)
 				logerr("%s: %s", __func__, state->leasefile);
 		} else if (r != 0) {
 			/* RFC 3633 section 12.1 */
@@ -2636,7 +2633,7 @@ dhcp6_startinit(struct interface *ifp)
 			return;
 		}
 	}
-	dhcp6_startdiscover(ifp);
+	dhcp6_startdiscoinform(ifp);
 }
 
 #ifndef SMALL
@@ -2797,16 +2794,16 @@ dhcp6_delegate_prefix(struct interface *
 			if (!(ap->flags & IPV6_AF_DELEGATEDPFX))
 				continue;
 			if (!(ap->flags & IPV6_AF_DELEGATEDLOG)) {
-				logfunc_t *logfunc;
+				int loglevel;
 
 				if (ap->flags & IPV6_AF_NEW)
-					logfunc = loginfox;
+					loglevel = LOG_INFO;
 				else
-					logfunc = logdebugx;
+					loglevel = LOG_DEBUG;
 				/* We only want to log this the once as we loop
 				 * through many interfaces first. */
 				ap->flags |= IPV6_AF_DELEGATEDLOG;
-				logfunc("%s: delegated prefix %s",
+				logmessage(loglevel, "%s: delegated prefix %s",
 				    ifp->name, ap->saddr);
 				ap->flags &= ~IPV6_AF_NEW;
 			}
@@ -2938,9 +2935,9 @@ static void
 dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom)
 {
 	struct dhcp6_state *state = D6_STATE(ifp);
-	bool has_new = false;
+	bool timedout = (op == NULL), has_new = false, confirmed;
 	struct ipv6_addr *ia;
-	logfunc_t *lognewinfo;
+	int loglevel;
 	struct timespec now;
 
 	TAILQ_FOREACH(ia, &state->addrs, next) {
@@ -2949,25 +2946,30 @@ dhcp6_bind(struct interface *ifp, const 
 			break;
 		}
 	}
-	lognewinfo = has_new ? loginfox : logdebugx;
-	if (op != NULL)
-		lognewinfo("%s: %s received from %s", ifp->name, op, sfrom);
+	loglevel = has_new ? LOG_INFO : LOG_DEBUG;
+	if (!timedout) {
+		logmessage(loglevel, "%s: %s received from %s",
+		    ifp->name, op, sfrom);
+		/* If we delegated from an unconfirmed lease we MUST drop
+		 * them now. Hopefully we have new delegations. */
+		if (state->reason != NULL &&
+		    strcmp(state->reason, "TIMEOUT6") == 0)
+			dhcp6_delete_delegates(ifp);
+		state->reason = NULL;
+	} else
+		state->reason = "TIMEOUT6";
+
+	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+	clock_gettime(CLOCK_MONOTONIC, &now);
 
-	state->reason = NULL;
-	if (state->state != DH6S_ITIMEDOUT)
-		eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 	switch(state->state) {
 	case DH6S_INFORM:
-		if (state->reason == NULL)
-			state->reason = "INFORM6";
-		/* FALLTHROUGH */
-	case DH6S_ITIMEDOUT:
 	{
 		struct dhcp6_option *o;
 		uint16_t ol;
 
 		if (state->reason == NULL)
-			state->reason = "ITIMEDOUT";
+			state->reason = "INFORM6";
 		o = dhcp6_findmoption(state->new, state->new_len,
 		                      D6_OPTION_INFO_REFRESH_TIME, &ol);
 		if (o == NULL || ol != sizeof(uint32_t))
@@ -2999,10 +3001,6 @@ dhcp6_bind(struct interface *ifp, const 
 	case DH6S_CONFIRM:
 		if (state->reason == NULL)
 			state->reason = "REBOOT6";
-		/* FALLTHROUGH */
-	case DH6S_TIMEDOUT:
-		if (state->reason == NULL)
-			state->reason = "TIMEOUT6";
 		if (state->renew != 0) {
 			bool all_expired = true;
 
@@ -3048,12 +3046,21 @@ dhcp6_bind(struct interface *ifp, const 
 		break;
 	}
 
-	clock_gettime(CLOCK_MONOTONIC, &now);
-	if (state->state == DH6S_TIMEDOUT || state->state == DH6S_ITIMEDOUT) {
+	if (state->state != DH6S_CONFIRM && !timedout) {
+		state->acquired = now;
+		free(state->old);
+		state->old = state->new;
+		state->old_len = state->new_len;
+		state->new = state->recv;
+		state->new_len = state->recv_len;
+		state->recv = NULL;
+		state->recv_len = 0;
+		confirmed = false;
+	} else {
+		/* Reduce timers based on when we got the lease. */
 		struct timespec diff;
 		uint32_t diffsec;
 
-		/* Reduce timers */
 		timespecsub(&now, &state->acquired, &diff);
 		diffsec = (uint32_t)diff.tv_sec;
 		if (state->renew && state->renew != ND6_INFINITE_LIFETIME) {
@@ -3071,69 +3078,19 @@ dhcp6_bind(struct interface *ifp, const 
 		if (state->expire && state->expire != ND6_INFINITE_LIFETIME) {
 			if (state->expire > diffsec)
 				state->expire -= diffsec;
-			else {
-				if (!(ifp->options->options &
-				    DHCPCD_LASTLEASE_EXTEND))
-					return;
-				state->expire = ND6_INFINITE_LIFETIME;
-			}
-		}
-		if (state->expire == ND6_INFINITE_LIFETIME &&
-		    ifp->options->options & DHCPCD_LASTLEASE_EXTEND)
-			dhcp6_leaseextend(ifp);
-
-		/* Restart rebind or renew phases in a second. */
-		if (state->expire != ND6_INFINITE_LIFETIME) {
-			if (state->rebind == 0 &&
-			    state->rebind != ND6_INFINITE_LIFETIME)
-				state->rebind = 1;
-			else if (state->renew == 0 &&
-			    state->renew != ND6_INFINITE_LIFETIME)
-				state->renew = 1;
+			else
+				state->expire = 0;
 		}
-	} else
-		state->acquired = now;
-
-	switch (state->state) {
-	case DH6S_CONFIRM:
-	case DH6S_TIMEDOUT:
-	case DH6S_ITIMEDOUT:
-		break;
-	default:
-		free(state->old);
-		state->old = state->new;
-		state->old_len = state->new_len;
-		state->new = state->recv;
-		state->new_len = state->recv_len;
-		state->recv = NULL;
-		state->recv_len = 0;
-		break;
+		confirmed = true;
 	}
 
 	if (ifp->ctx->options & DHCPCD_TEST)
 		script_runreason(ifp, "TEST");
 	else {
-		bool timed_out;
-
-		switch(state->state) {
-		case DH6S_TIMEDOUT:
-		case DH6S_ITIMEDOUT:
-			timed_out = true;
-			break;
-		default:
-			timed_out = false;
-			break;
-		}
-
-		switch(state->state) {
-		case DH6S_INFORM:
-		case DH6S_ITIMEDOUT:
+		if (state->state == DH6S_INFORM)
 			state->state = DH6S_INFORMED;
-			break;
-		default:
+		else
 			state->state = DH6S_BOUND;
-			break;
-		}
 
 		if (state->renew && state->renew != ND6_INFINITE_LIFETIME)
 			eloop_timeout_add_sec(ifp->ctx->eloop,
@@ -3146,31 +3103,30 @@ dhcp6_bind(struct interface *ifp, const 
 		if (state->expire != ND6_INFINITE_LIFETIME)
 			eloop_timeout_add_sec(ifp->ctx->eloop,
 			    (time_t)state->expire, dhcp6_startexpire, ifp);
-		else if (timed_out)
-			eloop_timeout_add_sec(ifp->ctx->eloop,
-			    (time_t)state->expire, dhcp6_startdiscover, ifp);
 
 		ipv6_addaddrs(&state->addrs);
-		dhcp6_deprecateaddrs(&state->addrs);
+		if (!timedout)
+			dhcp6_deprecateaddrs(&state->addrs);
 
 		if (state->state == DH6S_INFORMED)
-			lognewinfo("%s: refresh in %"PRIu32" seconds",
+			logmessage(loglevel, "%s: refresh in %"PRIu32" seconds",
 			    ifp->name, state->renew);
 		else if (state->renew == ND6_INFINITE_LIFETIME)
-			lognewinfo("%s: leased for infinity", ifp->name);
+			logmessage(loglevel, "%s: leased for infinity",
+			    ifp->name);
 		else if (state->renew || state->rebind)
-			lognewinfo("%s: renew in %"PRIu32", "
+			logmessage(loglevel, "%s: renew in %"PRIu32", "
 			    "rebind in %"PRIu32", "
 			    "expire in %"PRIu32" seconds",
 			    ifp->name,
 			    state->renew, state->rebind, state->expire);
 		else if (state->expire == 0)
-			lognewinfo("%s: will expire", ifp->name);
+			logmessage(loglevel, "%s: will expire", ifp->name);
 		else
-			lognewinfo("%s: expire in %"PRIu32" seconds",
+			logmessage(loglevel, "%s: expire in %"PRIu32" seconds",
 			    ifp->name, state->expire);
 		rt_build(ifp->ctx, AF_INET6);
-		if (!timed_out)
+		if (!confirmed && !timedout)
 			dhcp6_writelease(ifp);
 #ifndef SMALL
 		dhcp6_delegate_prefix(ifp);
@@ -3286,7 +3242,7 @@ dhcp6_recvif(struct interface *ifp, cons
 		case DH6S_CONFIRM:
 			if (dhcp6_validatelease(ifp, r, len, sfrom, NULL) == -1)
 			{
-				dhcp6_startdiscover(ifp);
+				dhcp6_startdiscoinform(ifp);
 				return;
 			}
 			break;
@@ -3325,7 +3281,7 @@ dhcp6_recvif(struct interface *ifp, cons
 				 * until a new one is found.
 				 */
 				if (state->state != DH6S_DISCOVER)
-					dhcp6_startdiscover(ifp);
+					dhcp6_startdiscoinform(ifp);
 				return;
 			}
 			/* RFC8415 18.2.10.1 */
@@ -3457,13 +3413,11 @@ dhcp6_recvif(struct interface *ifp, cons
 	memcpy(state->recv, r, len);
 	state->recv_len = len;
 
-	switch (r->type) {
-	case DHCP6_ADVERTISE:
-	{
+	if (r->type == DHCP6_ADVERTISE) {
 		struct ipv6_addr *ia;
 
 		if (state->state == DH6S_REQUEST) /* rapid commit */
-			break;
+			goto bind;
 		TAILQ_FOREACH(ia, &state->addrs, next) {
 			if (!(ia->flags & (IPV6_AF_STALE | IPV6_AF_REQUEST)))
 				break;
@@ -3476,13 +3430,11 @@ dhcp6_recvif(struct interface *ifp, cons
 		else
 			loginfox("%s: ADV %s from %s",
 			    ifp->name, ia->saddr, sfrom);
-		if (ifp->ctx->options & DHCPCD_TEST)
-			break;
 		dhcp6_startrequest(ifp);
 		return;
 	}
-	}
 
+bind:
 	dhcp6_bind(ifp, op, sfrom);
 }
 
@@ -3806,12 +3758,17 @@ dhcp6_start(struct interface *ifp, enum 
 		case DH6S_INIT:
 			goto gogogo;
 		case DH6S_INFORM:
-			if (state->state == DH6S_INFORMED)
+			if (state->state == DH6S_INIT ||
+			    state->state == DH6S_INFORMED ||
+			    (state->state == DH6S_DISCOVER &&
+			    !(ifp->options->options & DHCPCD_IA_FORCED) &&
+			    !ipv6nd_hasradhcp(ifp, true)))
 				dhcp6_startinform(ifp);
 			break;
 		case DH6S_REQUEST:
 			if (ifp->options->options & DHCPCD_DHCP6 &&
-			    (state->state == DH6S_INFORM ||
+			    (state->state == DH6S_INIT ||
+			     state->state == DH6S_INFORM ||
 			     state->state == DH6S_INFORMED ||
 			     state->state == DH6S_DELEGATED))
 			{
@@ -3860,8 +3817,7 @@ gogogo:
 	dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
 	    AF_INET6, ifp);
 	if (ipv6_linklocal(ifp) == NULL) {
-		logdebugx("%s: delaying DHCPv6 soliciation for LL address",
-		    ifp->name);
+		logdebugx("%s: delaying DHCPv6 for LL address", ifp->name);
 		ipv6_addlinklocalcallback(ifp, dhcp6_start1, ifp);
 		return 0;
 	}
@@ -3884,11 +3840,8 @@ dhcp6_reboot(struct interface *ifp)
 	case DH6S_BOUND:
 		dhcp6_startrebind(ifp);
 		break;
-	case DH6S_INFORMED:
-		dhcp6_startinform(ifp);
-		break;
 	default:
-		dhcp6_startdiscover(ifp);
+		dhcp6_startdiscoinform(ifp);
 		break;
 	}
 }
@@ -4004,6 +3957,20 @@ dhcp6_abort(struct interface *ifp)
 		ipv6nd_advertise(ia);
 	}
 #endif
+
+	eloop_timeout_delete(ifp->ctx->eloop, dhcp6_startdiscover, ifp);
+	eloop_timeout_delete(ifp->ctx->eloop, dhcp6_senddiscover, ifp);
+	eloop_timeout_delete(ifp->ctx->eloop, dhcp6_startinform, ifp);
+	eloop_timeout_delete(ifp->ctx->eloop, dhcp6_sendinform, ifp);
+	switch (state->state) {
+	case DH6S_DISCOVER:	/* FALLTHROUGH */
+	case DH6S_REQUEST:	/* FALLTHROUGH */
+	case DH6S_INFORM:
+		state->state = DH6S_INIT;
+		break;
+	default:
+		break;
+	}
 }
 
 void

Index: src/external/bsd/dhcpcd/dist/src/dhcp6.h
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.h:1.1.1.12 src/external/bsd/dhcpcd/dist/src/dhcp6.h:1.1.1.12.2.1
--- src/external/bsd/dhcpcd/dist/src/dhcp6.h:1.1.1.12	Tue Jul 30 10:23:05 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.h	Sun Apr 12 08:29:40 2020
@@ -167,8 +167,6 @@ enum DH6S {
 	DH6S_RENEW_REQUESTED,
 	DH6S_PROBE,
 	DH6S_DELEGATED,
-	DH6S_TIMEDOUT,
-	DH6S_ITIMEDOUT,
 	DH6S_RELEASE,
 	DH6S_RELEASED
 };

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.23.2.5 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.23.2.6
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.23.2.5	Sun Jan  5 09:38:28 2020
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c	Sun Apr 12 08:29:40 2020
@@ -47,6 +47,7 @@ const char dhcpcd_copyright[] = "Copyrig
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
+#include <syslog.h>
 
 #include "config.h"
 #include "arp.h"
@@ -435,7 +436,7 @@ stop_interface(struct interface *ifp)
 		script_runreason(ifp, "STOPPED");
 
 	/* Delete all timeouts for the interfaces */
-	eloop_q_timeout_delete(ctx->eloop, 0, NULL, ifp);
+	eloop_q_timeout_delete(ctx->eloop, ELOOP_QUEUE_ALL, NULL, ifp);
 
 	/* De-activate the interface */
 	ifp->active = IF_INACTIVE;
@@ -2044,11 +2045,11 @@ printpidfile:
 	}
 	if (ifp == NULL) {
 		if (ctx.ifc == 0) {
-			logfunc_t *logfunc;
+			int loglevel;
 
-			logfunc = ctx.options & DHCPCD_INACTIVE ?
-			    logdebugx : logerrx;
-			logfunc("no valid interfaces found");
+			loglevel = ctx.options & DHCPCD_INACTIVE ?
+			    LOG_DEBUG : LOG_ERR;
+			logmessage(loglevel, "no valid interfaces found");
 		} else
 			goto exit_failure;
 		if (!(ctx.options & DHCPCD_LINK)) {
@@ -2092,11 +2093,11 @@ printpidfile:
 		    ctx.options & DHCPCD_LINK &&
 		    !(ctx.options & DHCPCD_WAITIP))
 		{
-			logfunc_t *logfunc;
+			int loglevel;
 
-			logfunc = ctx.options & DHCPCD_INACTIVE ?
-			    logdebugx : logwarnx;
-			logfunc("no interfaces have a carrier");
+			loglevel = ctx.options & DHCPCD_INACTIVE ?
+			    LOG_DEBUG : LOG_WARNING;
+			logmessage(loglevel, "no interfaces have a carrier");
 			if (dhcpcd_daemonise(&ctx))
 				goto exit_success;
 		} else if (t > 0 &&

Index: src/external/bsd/dhcpcd/dist/src/eloop.h
diff -u src/external/bsd/dhcpcd/dist/src/eloop.h:1.1.1.5.2.1 src/external/bsd/dhcpcd/dist/src/eloop.h:1.1.1.5.2.2
--- src/external/bsd/dhcpcd/dist/src/eloop.h:1.1.1.5.2.1	Fri Nov 22 08:01:50 2019
+++ src/external/bsd/dhcpcd/dist/src/eloop.h	Sun Apr 12 08:29:40 2020
@@ -67,6 +67,9 @@
   #define ELOOP_QUEUE 1
 #endif
 
+/* Used for deleting a timeout for all queues. */
+#define	ELOOP_QUEUE_ALL	0
+
 /* Forward declare eloop - the content should be invisible to the outside */
 struct eloop;
 

Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.10.2.4 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.10.2.5
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.10.2.4	Tue Jan 28 09:48:34 2020
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c	Sun Apr 12 08:29:40 2020
@@ -106,6 +106,7 @@ static const char * const ifnames_ignore
 	"bridge",
 	"fwe",		/* Firewire */
 	"tap",
+	"xvif",		/* XEN DOM0 -> guest interface */
 	NULL
 };
 

Index: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.16.2.3 src/external/bsd/dhcpcd/dist/src/if-options.c:1.16.2.4
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.16.2.3	Sun Jan  5 09:38:28 2020
+++ src/external/bsd/dhcpcd/dist/src/if-options.c	Sun Apr 12 08:29:40 2020
@@ -1165,7 +1165,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 			np = strchr(p, '/');
 			if (np)
 				*np++ = '\0';
-			if (inet_pton(AF_INET6, p, &ifo->req_addr6) == 1) {
+			if ((i = inet_pton(AF_INET6, p, &ifo->req_addr6)) == 1) {
 				if (np) {
 					ifo->req_prefix_len = (uint8_t)strtou(np,
 					    NULL, 0, 0, 128, &e);
@@ -1178,6 +1178,14 @@ parse_option(struct dhcpcd_ctx *ctx, con
 				} else
 					ifo->req_prefix_len = 128;
 			}
+			if (np)
+				*(--np) = '\0';
+			if (i != 1) {
+				logerrx("invalid AF_INET6: %s", p);
+				memset(&ifo->req_addr6, 0,
+				    sizeof(ifo->req_addr6));
+				return -1;
+			}
 		} else
 			add_environ(&ifo->config, arg, 1);
 		break;
@@ -1398,8 +1406,8 @@ parse_option(struct dhcpcd_ctx *ctx, con
 				p = strchr(arg, '/');
 				if (p)
 					*p++ = '\0';
-				if (inet_pton(AF_INET6, arg, &ia->addr) == -1) {
-					logerr("%s", arg);
+				if (inet_pton(AF_INET6, arg, &ia->addr) != 1) {
+					logerrx("invalid AF_INET6: %s", arg);
 					memset(&ia->addr, 0, sizeof(ia->addr));
 				}
 				if (p && ia->ia_type == D6_OPTION_IA_PD) {

Index: src/external/bsd/dhcpcd/dist/src/if.c
diff -u src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.14.2.3 src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.14.2.4
--- src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.14.2.3	Fri Nov 22 08:01:50 2019
+++ src/external/bsd/dhcpcd/dist/src/if.c	Sun Apr 12 08:29:40 2020
@@ -30,6 +30,7 @@
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
+#include <syslog.h>
 
 #include "config.h"
 
@@ -54,6 +55,7 @@
 #include <errno.h>
 #include <ifaddrs.h>
 #include <inttypes.h>
+#include <fcntl.h>
 #include <fnmatch.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -407,8 +409,9 @@ if_discover(struct dhcpcd_ctx *ctx, stru
 #endif
 
 		if (if_vimaster(ctx, spec.devname) == 1) {
-			logfunc_t *logfunc = argc != 0 ? logerrx : logdebugx;
-			logfunc("%s: is a Virtual Interface Master, skipping",
+			int loglevel = argc != 0 ? LOG_ERR : LOG_DEBUG;
+			logmessage(loglevel,
+			    "%s: is a Virtual Interface Master, skipping",
 			    spec.devname);
 			continue;
 		}
@@ -612,11 +615,18 @@ if_discover(struct dhcpcd_ctx *ctx, stru
 	return ifs;
 }
 
-/* Decode bge0:1 as dev = bge, ppa = 0 and lun = 1 */
+/*
+ * eth0.100:2 OR eth0i100:2 (seems to be NetBSD xvif(4) only)
+ *
+ * drvname == eth
+ * devname == eth0.100 OR eth0i100
+ * ppa = 0
+ * lun = 2
+ */
 int
 if_nametospec(const char *ifname, struct if_spec *spec)
 {
-	char *ep;
+	char *ep, *pp;
 	int e;
 
 	if (ifname == NULL || *ifname == '\0' ||
@@ -628,6 +638,8 @@ if_nametospec(const char *ifname, struct
 		errno = EINVAL;
 		return -1;
 	}
+
+	/* :N is an alias */
 	ep = strchr(spec->drvname, ':');
 	if (ep) {
 		spec->lun = (int)strtoi(ep + 1, NULL, 10, 0, INT_MAX, &e);
@@ -640,18 +652,28 @@ if_nametospec(const char *ifname, struct
 		spec->lun = -1;
 		ep = spec->drvname + strlen(spec->drvname) - 1;
 	}
+
 	strlcpy(spec->devname, spec->drvname, sizeof(spec->devname));
-	while (ep > spec->drvname && isdigit((int)*ep))
-		ep--;
-	if (*ep++ == ':') {
-		errno = EINVAL;
-		return -1;
+	for (ep = spec->drvname; *ep != '\0' && !isdigit((int)*ep); ep++) {
+		if (*ep == ':') {
+			errno = EINVAL;
+			return -1;
+		}
 	}
-	spec->ppa = (int)strtoi(ep, NULL, 10, 0, INT_MAX, &e);
-	if (e != 0)
-		spec->ppa = -1;
+	spec->ppa = (int)strtoi(ep, &pp, 10, 0, INT_MAX, &e);
 	*ep = '\0';
 
+	/*
+	 * . is used for VLAN style names
+	 * i is used on NetBSD for xvif interfaces
+	 */
+	if (pp != NULL && (*pp == '.' || *pp == 'i')) {
+		spec->vlid = (int)strtoi(pp + 1, NULL, 10, 0, INT_MAX, &e);
+		if (e)
+			spec->vlid = -1;
+	} else
+		spec->vlid = -1;
+
 	return 0;
 }
 

Index: src/external/bsd/dhcpcd/dist/src/if.h
diff -u src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.10.2.3 src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.10.2.4
--- src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.10.2.3	Fri Nov 22 08:01:50 2019
+++ src/external/bsd/dhcpcd/dist/src/if.h	Sun Apr 12 08:29:40 2020
@@ -81,6 +81,11 @@
 #  define ARPHRD_INFINIBAND		32
 #endif
 
+/* Maximum frame length.
+ * Support jumbo frames and some extra. */
+#define	FRAMEHDRLEN_MAX			14	/* only ethernet support */
+#define	FRAMELEN_MAX			(FRAMEHDRLEN_MAX + 9216)
+
 /* Work out if we have a private address or not
  * 10/8
  * 172.16/12
@@ -145,6 +150,7 @@ struct if_spec {
 	char devname[IF_NAMESIZE];
 	char drvname[IF_NAMESIZE];
 	int ppa;
+	int vlid;
 	int lun;
 };
 int if_nametospec(const char *, struct if_spec *);

Index: src/external/bsd/dhcpcd/dist/src/ipv4ll.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv4ll.c:1.1.1.9.2.1 src/external/bsd/dhcpcd/dist/src/ipv4ll.c:1.1.1.9.2.2
--- src/external/bsd/dhcpcd/dist/src/ipv4ll.c:1.1.1.9.2.1	Sat Oct 12 14:44:32 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv4ll.c	Sun Apr 12 08:29:40 2020
@@ -36,7 +36,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#define ELOOP_QUEUE 6
+#define ELOOP_QUEUE	IPV4LL
 #include "config.h"
 #include "arp.h"
 #include "common.h"

Index: src/external/bsd/dhcpcd/dist/src/ipv6.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6.c:1.3.2.5 src/external/bsd/dhcpcd/dist/src/ipv6.c:1.3.2.6
--- src/external/bsd/dhcpcd/dist/src/ipv6.c:1.3.2.5	Tue Jan 28 09:48:34 2020
+++ src/external/bsd/dhcpcd/dist/src/ipv6.c	Sun Apr 12 08:29:40 2020
@@ -36,6 +36,7 @@
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
+#include <syslog.h>
 
 #include "config.h"
 
@@ -59,7 +60,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#define ELOOP_QUEUE 7
+#define ELOOP_QUEUE	ELOOP_IPV6
 #include "common.h"
 #include "if.h"
 #include "dhcpcd.h"
@@ -380,25 +381,14 @@ ipv6_makeaddr(struct in6_addr *addr, str
 static int
 ipv6_makeprefix(struct in6_addr *prefix, const struct in6_addr *addr, int len)
 {
-	int bytes, bits;
+	struct in6_addr mask;
+	size_t i;
 
-	if (len < 0 || len > 128) {
-		errno = EINVAL;
+	if (ipv6_mask(&mask, len) == -1)
 		return -1;
-	}
-
-	bytes = len / NBBY;
-	bits = len % NBBY;
-	memcpy(&prefix->s6_addr, &addr->s6_addr, (size_t)bytes);
-	if (bits != 0) {
-		/* Coverify false positive.
-		 * bytelen cannot be 16 if bitlen is non zero */
-		/* coverity[overrun-local] */
-		prefix->s6_addr[bytes] =
-		    (uint8_t)(prefix->s6_addr[bytes] >> (NBBY - bits));
-	}
-	memset((char *)prefix->s6_addr + bytes, 0,
-	    sizeof(prefix->s6_addr) - (size_t)bytes);
+	*prefix = *addr;
+	for (i = 0; i < sizeof(prefix->s6_addr); i++)
+		prefix->s6_addr[i] &= mask.s6_addr[i];
 	return 0;
 }
 
@@ -627,7 +617,7 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons
 {
 	struct interface *ifp;
 	uint32_t pltime, vltime;
-	__printflike(1, 2) void (*logfunc)(const char *, ...);
+	int loglevel;
 #ifdef ND6_ADVERTISE
 	bool vltime_was_zero = ia->prefix_vltime == 0;
 #endif
@@ -688,8 +678,8 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons
 		}
 	}
 
-	logfunc = ia->flags & IPV6_AF_NEW ? loginfox : logdebugx;
-	logfunc("%s: adding %saddress %s", ifp->name,
+	loglevel = ia->flags & IPV6_AF_NEW ? LOG_INFO : LOG_DEBUG;
+	logmessage(loglevel, "%s: adding %saddress %s", ifp->name,
 #ifdef IPV6_AF_TEMPORARY
 	    ia->flags & IPV6_AF_TEMPORARY ? "temporary " : "",
 #else
@@ -932,7 +922,7 @@ ipv6_doaddr(struct ipv6_addr *ia, struct
 		if (ia->flags & IPV6_AF_ADDED)
 			ipv6_deleteaddr(ia);
 		eloop_q_timeout_delete(ia->iface->ctx->eloop,
-		    0, NULL, ia);
+		    ELOOP_QUEUE_ALL, NULL, ia);
 		if (ia->flags & IPV6_AF_REQUEST) {
 			ia->flags &= ~IPV6_AF_ADDED;
 			return 0;
@@ -974,6 +964,7 @@ ipv6_addaddrs(struct ipv6_addrhead *iadd
 void
 ipv6_freeaddr(struct ipv6_addr *ia)
 {
+	struct eloop *eloop = ia->iface->ctx->eloop;
 #ifndef SMALL
 	struct ipv6_addr *iad;
 
@@ -989,10 +980,10 @@ ipv6_freeaddr(struct ipv6_addr *ia)
 
 	if (ia->dhcp6_fd != -1) {
 		close(ia->dhcp6_fd);
-		eloop_event_delete(ia->iface->ctx->eloop, ia->dhcp6_fd);
+		eloop_event_delete(eloop, ia->dhcp6_fd);
 	}
 
-	eloop_q_timeout_delete(ia->iface->ctx->eloop, 0, NULL, ia);
+	eloop_q_timeout_delete(eloop, ELOOP_QUEUE_ALL, NULL, ia);
 	free(ia->na);
 	free(ia);
 }
@@ -1538,9 +1529,10 @@ ipv6_newaddr(struct interface *ifp, cons
 	/* If adding a new DHCP / RA derived address, check current flags
 	 * from an existing address. */
 	ia = ipv6_iffindaddr(ifp, addr, 0);
-	if (ia != NULL)
+	if (ia != NULL) {
 		addr_flags = ia->addr_flags;
-	else
+		flags |= IPV6_AF_ADDED;
+	} else
 		addr_flags = IN6_IFF_TENTATIVE;
 
 	ia = calloc(1, sizeof(*ia));

Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.10.2.5 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.10.2.6
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.10.2.5	Tue Jan 28 09:48:34 2020
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c	Sun Apr 12 08:29:40 2020
@@ -42,8 +42,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <syslog.h>
 
-#define ELOOP_QUEUE 3
+#define ELOOP_QUEUE	ELOOP_IPV6ND
 #include "common.h"
 #include "dhcpcd.h"
 #include "dhcp-common.h"
@@ -379,10 +380,8 @@ ipv6nd_sendrsprobe(void *arg)
 	if (state->rsprobes++ < MAX_RTR_SOLICITATIONS)
 		eloop_timeout_add_sec(ifp->ctx->eloop,
 		    RTR_SOLICITATION_INTERVAL, ipv6nd_sendrsprobe, ifp);
-	else {
+	else
 		logwarnx("%s: no IPv6 Routers available", ifp->name);
-		ipv6nd_drop(ifp);
-	}
 }
 
 #ifdef ND6_ADVERTISE
@@ -531,19 +530,13 @@ ipv6nd_expire(void *arg)
 {
 	struct interface *ifp = arg;
 	struct ra *rap;
-	struct ipv6_addr *ia;
-	struct timespec now = { .tv_sec = 1 };
 
 	if (ifp->ctx->ra_routers == NULL)
 		return;
 
 	TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
-		if (rap->iface == ifp)
-			continue;
-		rap->acquired = now;
-		TAILQ_FOREACH(ia, &rap->addrs, next) {
-			ia->acquired = now;
-		}
+		if (rap->iface == ifp && rap->willexpire)
+			rap->doexpire = true;
 	}
 	ipv6nd_expirera(ifp);
 }
@@ -551,9 +544,17 @@ ipv6nd_expire(void *arg)
 void
 ipv6nd_startexpire(struct interface *ifp)
 {
+	struct ra *rap;
 
-	eloop_timeout_add_sec(ifp->ctx->eloop, RTR_CARRIER_EXPIRE,
-	    ipv6nd_expire, ifp);
+	if (ifp->ctx->ra_routers == NULL)
+		return;
+
+	TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
+		if (rap->iface == ifp)
+			rap->willexpire = true;
+	}
+	eloop_q_timeout_add_sec(ifp->ctx->eloop, ELOOP_IPV6RA_EXPIRE,
+	    RTR_CARRIER_EXPIRE, ipv6nd_expire, ifp);
 }
 
 static int
@@ -584,19 +585,22 @@ ipv6nd_sortrouters(struct dhcpcd_ctx *ct
 	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)
+			if (ra1->iface->metric > ra2->iface->metric)
 				continue;
 			if (ra1->expired && !ra2->expired)
 				continue;
+			if (ra1->willexpire && !ra2->willexpire)
+				continue;
 			if (ra1->lifetime == 0 && ra2->lifetime != 0)
 				continue;
 			if (!ra1->isreachable && ra2->reachable)
 				continue;
-			if (ipv6nd_rtpref(ra1) < ipv6nd_rtpref(ra2))
+			if (ipv6nd_rtpref(ra1) <= ipv6nd_rtpref(ra2))
 				continue;
 			/* All things being equal, prefer older routers. */
-			if (timespeccmp(&ra1->acquired, &ra2->acquired, >=))
-				continue;
+			/* We don't need to check time, becase newer
+			 * routers are always added to the tail and then
+			 * sorted. */
 			TAILQ_INSERT_BEFORE(ra2, ra1, next);
 			break;
 		}
@@ -994,7 +998,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 	bool new_rap, new_data, has_address;
 	uint32_t old_lifetime;
 	int ifmtu;
-	__printflike(1, 2) void (*logfunc)(const char *, ...);
+	int loglevel;
 #ifdef IPV6_MANAGETEMPADDR
 	uint8_t new_ap;
 #endif
@@ -1093,8 +1097,11 @@ 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_data || !rap->isreachable ? loginfox : logdebugx,
-	logfunc("%s: Router Advertisement from %s", ifp->name, rap->sfrom);
+	if (rap->willexpire)
+		new_data = true;
+	loglevel = new_data || !rap->isreachable ? LOG_INFO : LOG_DEBUG,
+	logmessage(loglevel, "%s: Router Advertisement from %s",
+	    ifp->name, rap->sfrom);
 
 	clock_gettime(CLOCK_MONOTONIC, &rap->acquired);
 	rap->flags = nd_ra->nd_ra_flags_reserved;
@@ -1117,7 +1124,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 		rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
 	else
 		rap->retrans = RETRANS_TIMER;
-	rap->expired = false;
+	rap->expired = rap->willexpire = rap->doexpire = false;
 	rap->hasdns = false;
 	rap->isreachable = true;
 	has_address = false;
@@ -1177,15 +1184,15 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 
 		switch (ndo.nd_opt_type) {
 		case ND_OPT_PREFIX_INFORMATION:
-			logfunc = new_data ? logerrx : logdebugx;
+			loglevel = new_data ? LOG_ERR : LOG_DEBUG;
 			if (ndo.nd_opt_len != 4) {
-				logfunc("%s: invalid option len for prefix",
+				logmessage(loglevel, "%s: invalid option len for prefix",
 				    ifp->name);
 				continue;
 			}
 			memcpy(&pi, p, sizeof(pi));
 			if (pi.nd_opt_pi_prefix_len > 128) {
-				logfunc("%s: invalid prefix len", ifp->name);
+				logmessage(loglevel, "%s: invalid prefix len", ifp->name);
 				continue;
 			}
 			/* nd_opt_pi_prefix is not aligned. */
@@ -1194,13 +1201,13 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 			if (IN6_IS_ADDR_MULTICAST(&pi_prefix) ||
 			    IN6_IS_ADDR_LINKLOCAL(&pi_prefix))
 			{
-				logfunc("%s: invalid prefix in RA", ifp->name);
+				logmessage(loglevel, "%s: invalid prefix in RA", ifp->name);
 				continue;
 			}
 			if (ntohl(pi.nd_opt_pi_preferred_time) >
 			    ntohl(pi.nd_opt_pi_valid_time))
 			{
-				logfunc("%s: pltime > vltime", ifp->name);
+				logmessage(loglevel, "%s: pltime > vltime", ifp->name);
 				continue;
 			}
 			TAILQ_FOREACH(ap, &rap->addrs, next)
@@ -1280,13 +1287,13 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 
 		case ND_OPT_MTU:
 			if (len < sizeof(mtu)) {
-				logfunc("%s: short MTU option", ifp->name);
+				logmessage(loglevel, "%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) {
-				logfunc("%s: invalid MTU %d",
+				logmessage(loglevel, "%s: invalid MTU %d",
 				    ifp->name, mtu.nd_opt_mtu_mtu);
 				break;
 			}
@@ -1294,7 +1301,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 			if (ifmtu == -1)
 				logerr("if_getmtu");
 			else if (mtu.nd_opt_mtu_mtu > (uint32_t)ifmtu) {
-				logfunc("%s: advertised MTU %d"
+				logmessage(loglevel, "%s: advertised MTU %d"
 				    " is greater than link MTU %d",
 				    ifp->name, mtu.nd_opt_mtu_mtu, ifmtu);
 				rap->mtu = (uint32_t)ifmtu;
@@ -1303,7 +1310,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 			break;
 		case ND_OPT_RDNSS:
 			if (len < sizeof(rdnss)) {
-				logfunc("%s: short RDNSS option", ifp->name);
+				logmessage(loglevel, "%s: short RDNSS option", ifp->name);
 				break;
 			}
 			memcpy(&rdnss, p, sizeof(rdnss));
@@ -1397,7 +1404,8 @@ ipv6nd_hasralifetime(const struct interf
 
 	if (ifp->ctx->ra_routers) {
 		TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next)
-			if (rap->iface == ifp && !rap->expired &&
+			if (rap->iface == ifp &&
+			    !rap->expired &&
 			    (!lifetime ||rap->lifetime))
 				return true;
 	}
@@ -1405,15 +1413,16 @@ ipv6nd_hasralifetime(const struct interf
 }
 
 bool
-ipv6nd_hasradhcp(const struct interface *ifp)
+ipv6nd_hasradhcp(const struct interface *ifp, bool managed)
 {
 	const struct ra *rap;
 
 	if (ifp->ctx->ra_routers) {
 		TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
 			if (rap->iface == ifp &&
-			    !rap->expired &&
-			    (rap->flags &(ND_RA_FLAG_MANAGED|ND_RA_FLAG_OTHER)))
+			    !rap->expired && !rap->willexpire &&
+			    ((managed && rap->flags & ND_RA_FLAG_MANAGED) ||
+			    (!managed && rap->flags & ND_RA_FLAG_OTHER)))
 				return true;
 		}
 	}
@@ -1604,7 +1613,7 @@ ipv6nd_expirera(void *arg)
 			lt.tv_sec = (time_t)rap->lifetime;
 			lt.tv_nsec = 0;
 			timespecadd(&rap->acquired, &lt, &expire);
-			if (timespeccmp(&now, &expire, >)) {
+			if (timespeccmp(&now, &expire, >) || rap->doexpire) {
 				if (!rap->expired) {
 					logwarnx("%s: %s: router expired",
 					    ifp->name, rap->sfrom);
@@ -1626,14 +1635,16 @@ ipv6nd_expirera(void *arg)
 		TAILQ_FOREACH(ia, &rap->addrs, next) {
 			if (ia->prefix_vltime == 0)
 				continue;
-			if (ia->prefix_vltime == ND6_INFINITE_LIFETIME) {
+			if (ia->prefix_vltime == ND6_INFINITE_LIFETIME &&
+			    !rap->doexpire)
+			{
 				valid = true;
 				continue;
 			}
 			lt.tv_sec = (time_t)ia->prefix_vltime;
 			lt.tv_nsec = 0;
 			timespecadd(&ia->acquired, &lt, &expire);
-			if (timespeccmp(&now, &expire, >)) {
+			if (timespeccmp(&now, &expire, >) || rap->doexpire) {
 				if (ia->flags & IPV6_AF_ADDED) {
 					logwarnx("%s: expired address %s",
 					    ia->iface->name, ia->saddr);
@@ -1700,6 +1711,10 @@ ipv6nd_expirera(void *arg)
 
 			if (ltime == 0)
 				continue;
+			if (rap->doexpire) {
+				expired = true;
+				continue;
+			}
 			if (ltime == ND6_INFINITE_LIFETIME) {
 				valid = true;
 				continue;
@@ -1735,7 +1750,8 @@ ipv6nd_expirera(void *arg)
 		eloop_timeout_add_tv(ifp->ctx->eloop,
 		    &next, ipv6nd_expirera, ifp);
 	if (expired) {
-		logwarnx("%s: part of Router Advertisement expired", ifp->name);
+		logwarnx("%s: part of a Router Advertisement expired",
+		    ifp->name);
 		rt_build(ifp->ctx, AF_INET6);
 		script_runreason(ifp, "ROUTERADVERT");
 	}

Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.h
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.h:1.1.1.10.2.2 src/external/bsd/dhcpcd/dist/src/ipv6nd.h:1.1.1.10.2.3
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.h:1.1.1.10.2.2	Fri Nov 22 08:01:50 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.h	Sun Apr 12 08:29:40 2020
@@ -54,6 +54,8 @@ struct ra {
 	struct ipv6_addrhead addrs;
 	bool hasdns;
 	bool expired;
+	bool willexpire;
+	bool doexpire;
 	bool isreachable;
 };
 
@@ -108,7 +110,7 @@ ssize_t ipv6nd_free(struct interface *);
 void ipv6nd_expirera(void *arg);
 bool ipv6nd_hasralifetime(const struct interface *, bool);
 #define	ipv6nd_hasra(i)		ipv6nd_hasralifetime((i), false)
-bool ipv6nd_hasradhcp(const struct interface *);
+bool ipv6nd_hasradhcp(const struct interface *, bool);
 void ipv6nd_handleifa(int, struct ipv6_addr *, pid_t);
 int ipv6nd_dadcompleted(const struct interface *);
 void ipv6nd_advertise(struct ipv6_addr *);

Index: src/external/bsd/dhcpcd/dist/src/logerr.c
diff -u src/external/bsd/dhcpcd/dist/src/logerr.c:1.2 src/external/bsd/dhcpcd/dist/src/logerr.c:1.2.2.1
--- src/external/bsd/dhcpcd/dist/src/logerr.c:1.2	Wed Jul 24 15:06:21 2019
+++ src/external/bsd/dhcpcd/dist/src/logerr.c	Sun Apr 12 08:29:40 2020
@@ -224,7 +224,7 @@ vlogmessage(int pri, const char *fmt, va
 #pragma GCC diagnostic pop
 #endif
 
-__printflike(2, 3) static void
+__printflike(2, 3) void
 logmessage(int pri, const char *fmt, ...)
 {
 	va_list args;
@@ -244,8 +244,18 @@ vlogerrmessage(int pri, const char *fmt,
 	logmessage(pri, "%s: %s", buf, strerror(_errno));
 }
 
+__printflike(2, 3) void
+logerrmessage(int pri, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vlogerrmessage(pri, fmt, args);
+	va_end(args);
+}
+
 void
-logdebug(const char *fmt, ...)
+log_debug(const char *fmt, ...)
 {
 	va_list args;
 
@@ -255,7 +265,7 @@ logdebug(const char *fmt, ...)
 }
 
 void
-logdebugx(const char *fmt, ...)
+log_debugx(const char *fmt, ...)
 {
 	va_list args;
 
@@ -265,7 +275,7 @@ logdebugx(const char *fmt, ...)
 }
 
 void
-loginfo(const char *fmt, ...)
+log_info(const char *fmt, ...)
 {
 	va_list args;
 
@@ -275,7 +285,7 @@ loginfo(const char *fmt, ...)
 }
 
 void
-loginfox(const char *fmt, ...)
+log_infox(const char *fmt, ...)
 {
 	va_list args;
 
@@ -285,7 +295,7 @@ loginfox(const char *fmt, ...)
 }
 
 void
-logwarn(const char *fmt, ...)
+log_warn(const char *fmt, ...)
 {
 	va_list args;
 
@@ -295,7 +305,7 @@ logwarn(const char *fmt, ...)
 }
 
 void
-logwarnx(const char *fmt, ...)
+log_warnx(const char *fmt, ...)
 {
 	va_list args;
 
@@ -305,7 +315,7 @@ logwarnx(const char *fmt, ...)
 }
 
 void
-logerr(const char *fmt, ...)
+log_err(const char *fmt, ...)
 {
 	va_list args;
 
@@ -315,7 +325,7 @@ logerr(const char *fmt, ...)
 }
 
 void
-logerrx(const char *fmt, ...)
+log_errx(const char *fmt, ...)
 {
 	va_list args;
 

Index: src/external/bsd/dhcpcd/dist/src/logerr.h
diff -u src/external/bsd/dhcpcd/dist/src/logerr.h:1.1.1.5 src/external/bsd/dhcpcd/dist/src/logerr.h:1.1.1.5.2.1
--- src/external/bsd/dhcpcd/dist/src/logerr.h:1.1.1.5	Wed Jul 24 09:54:55 2019
+++ src/external/bsd/dhcpcd/dist/src/logerr.h	Sun Apr 12 08:29:40 2020
@@ -39,17 +39,42 @@
 #endif
 #endif /* !__printflike */
 
-__printflike(1, 2) typedef void logfunc_t(const char *, ...);
-
-__printflike(1, 2) void logdebug(const char *, ...);
-__printflike(1, 2) void logdebugx(const char *, ...);
-__printflike(1, 2) void loginfo(const char *, ...);
-__printflike(1, 2) void loginfox(const char *, ...);
-__printflike(1, 2) void logwarn(const char *, ...);
-__printflike(1, 2) void logwarnx(const char *, ...);
-__printflike(1, 2) void logerr(const char *, ...);
+/* Please do not call log_* functions directly, use macros below */
+__printflike(1, 2) void log_debug(const char *, ...);
+__printflike(1, 2) void log_debugx(const char *, ...);
+__printflike(1, 2) void log_info(const char *, ...);
+__printflike(1, 2) void log_infox(const char *, ...);
+__printflike(1, 2) void log_warn(const char *, ...);
+__printflike(1, 2) void log_warnx(const char *, ...);
+__printflike(1, 2) void log_err(const char *, ...);
+__printflike(1, 2) void log_errx(const char *, ...);
 #define	LOGERROR	logerr("%s: %d", __FILE__, __LINE__)
-__printflike(1, 2) void logerrx(const char *, ...);
+
+__printflike(2, 3) void logmessage(int pri, const char *fmt, ...);
+__printflike(2, 3) void logerrmessage(int pri, const char *fmt, ...);
+
+/*
+ * These are macros to prevent taking address of them so
+ * __FILE__, __LINE__, etc can easily be added.
+ *
+ * We should be using
+ * #define loginfox(fmt, __VA_OPT__(,) __VA_ARGS__)
+ * but that requires gcc-8 or clang-6 and we still have a need to support
+ * old OS's without modern compilers.
+ *
+ * Likewise, ##__VA_ARGS__ can't be used as that's a gcc only extension.
+ *
+ * The solution is to put fmt into __VA_ARGS__.
+ * It's not pretty but it's 100% portable.
+ */
+#define logdebug(...)	log_debug(__VA_ARGS__)
+#define logdebugx(...)	log_debugx(__VA_ARGS__)
+#define loginfo(...)	log_info(__VA_ARGS__)
+#define loginfox(...)	log_infox(__VA_ARGS__)
+#define logwarn(...)	log_warn(__VA_ARGS__)
+#define logwarnx(...)	log_warnx(__VA_ARGS__)
+#define logerr(...)	log_err(__VA_ARGS__)
+#define logerrx(...)	log_errx(__VA_ARGS__)
 
 void logsetopts(unsigned int);
 #define	LOGERR_DEBUG	(1U << 6)

Reply via email to