Module Name:    src
Committed By:   martin
Date:           Thu Sep  5 08:56:55 UTC 2019

Modified Files:
        src/external/bsd/dhcpcd/dist [netbsd-9]: BUILDING.md Makefile
            Makefile.inc configure
        src/external/bsd/dhcpcd/dist/compat [netbsd-9]: rb.c rbtree.h
        src/external/bsd/dhcpcd/dist/hooks [netbsd-9]: Makefile
        src/external/bsd/dhcpcd/dist/src [netbsd-9]: Makefile bpf.c control.c
            control.h defs.h dhcp-common.c dhcp.c dhcp6.c dhcpcd.8.in dhcpcd.c
            dhcpcd.conf.5.in duid.c if-bsd.c if-linux.c if-options.c
            if-options.h if-sun.c if.c if.h ipv4.c ipv4.h ipv6.c ipv6.h
            ipv6nd.c ipv6nd.h route.c route.h sa.c script.c

Log Message:
Catch up to current for the following files, requested by roy in ticket #177:

        external/bsd/dhcpcd/dist/BUILDING.md            up to 1.1.1.5
        external/bsd/dhcpcd/dist/Makefile               up to 1.1.1.7
        external/bsd/dhcpcd/dist/Makefile.inc           up to 1.1.1.3
        external/bsd/dhcpcd/dist/configure              up to 1.1.1.15
        external/bsd/dhcpcd/dist/compat/rb.c            up to 1.1.1.2
        external/bsd/dhcpcd/dist/compat/rbtree.h        up to 1.1.1.2
        external/bsd/dhcpcd/dist/hooks/Makefile         up to 1.1.1.2
        external/bsd/dhcpcd/dist/src/Makefile           up to 1.1.1.6
        external/bsd/dhcpcd/dist/src/bpf.c              up to 1.12
        external/bsd/dhcpcd/dist/src/control.c          up to 1.1.1.8
        external/bsd/dhcpcd/dist/src/control.h          up to 1.1.1.5
        external/bsd/dhcpcd/dist/src/defs.h             up to 1.1.1.27
        external/bsd/dhcpcd/dist/src/dhcp-common.c      up to 1.1.1.8
        external/bsd/dhcpcd/dist/src/dhcp.c             up to 1.25
        external/bsd/dhcpcd/dist/src/dhcp6.c            up to 1.12
        external/bsd/dhcpcd/dist/src/dhcpcd.8.in        up to 1.3
        external/bsd/dhcpcd/dist/src/dhcpcd.c           up to 1.25
        external/bsd/dhcpcd/dist/src/dhcpcd.conf.5.in   up to 1.1.1.14
        external/bsd/dhcpcd/dist/src/duid.c             up to 1.1.1.7
        external/bsd/dhcpcd/dist/src/if-bsd.c           up to 1.12
        external/bsd/dhcpcd/dist/src/if-linux.c         up to 1.1.1.16
        external/bsd/dhcpcd/dist/src/if-options.c       up to 1.17
        external/bsd/dhcpcd/dist/src/if-options.h       up to 1.1.1.11
        external/bsd/dhcpcd/dist/src/if-sun.c           up to 1.1.1.11
        external/bsd/dhcpcd/dist/src/if.c               up to 1.1.1.16
        external/bsd/dhcpcd/dist/src/if.h               up to 1.1.1.11
        external/bsd/dhcpcd/dist/src/ipv4.c             up to 1.1.1.17
        external/bsd/dhcpcd/dist/src/ipv4.h             up to 1.1.1.10
        external/bsd/dhcpcd/dist/src/ipv6.c             up to 1.4
        external/bsd/dhcpcd/dist/src/ipv6.h             up to 1.5
        external/bsd/dhcpcd/dist/src/ipv6nd.c           up to 1.11
        external/bsd/dhcpcd/dist/src/ipv6nd.h           up to 1.1.1.11
        external/bsd/dhcpcd/dist/src/route.c            up to 1.1.1.14
        external/bsd/dhcpcd/dist/src/route.h            up to 1.1.1.9
        external/bsd/dhcpcd/dist/src/sa.c               up to 1.1.1.6
        external/bsd/dhcpcd/dist/src/script.c           up to 1.1.1.11

Import dhcpcd-8.0.4 with the following changes:

 * BSD: Fixed router reachability tests
 * inet6: If router unreachable, just solicit a new one
 * inet6: Fon't install a default route if only lladdresses
 * inet6: Stop listening to NA messages
 * BSD: Listen to RTM_MISS messages
 * DHCP: Fix in_cksum for Big Endian
 * DHCP{,6}: Don't log an error if the lease file is truncated

Changes in dhcpcd-8.0.3:

 *  DHCP: Work with IP headers with options
 *  script: Assert that env string are correctly terminated
 *  script: Terminate env strings with no value
 *  script: Don't attempt to use an invalid env string
 *  route: Fix NULL deference error when using static routes
 *  ARP: Respect IFF_NOARP
 *  DHCP: Allow full DHCP support for PtP interfaces, but not by default
 *  control: sends correct buffer to listeners

dhcpcd-ui now correctly reports SSD association and all the addresses
obtained (regression from dhcpcd-7)


To generate a diff of this commit:
cvs rdiff -u -r1.1.1.4 -r1.1.1.4.2.1 src/external/bsd/dhcpcd/dist/BUILDING.md
cvs rdiff -u -r1.1.1.6 -r1.1.1.6.2.1 src/external/bsd/dhcpcd/dist/Makefile
cvs rdiff -u -r1.1.1.2 -r1.1.1.2.8.1 \
    src/external/bsd/dhcpcd/dist/Makefile.inc
cvs rdiff -u -r1.1.1.14 -r1.1.1.14.2.1 src/external/bsd/dhcpcd/dist/configure
cvs rdiff -u -r1.1.1.1 -r1.1.1.1.2.1 src/external/bsd/dhcpcd/dist/compat/rb.c \
    src/external/bsd/dhcpcd/dist/compat/rbtree.h
cvs rdiff -u -r1.1.1.1 -r1.1.1.1.20.1 \
    src/external/bsd/dhcpcd/dist/hooks/Makefile
cvs rdiff -u -r1.1.1.5 -r1.1.1.5.2.1 \
    src/external/bsd/dhcpcd/dist/src/Makefile \
    src/external/bsd/dhcpcd/dist/src/sa.c
cvs rdiff -u -r1.11 -r1.11.2.1 src/external/bsd/dhcpcd/dist/src/bpf.c \
    src/external/bsd/dhcpcd/dist/src/dhcp6.c
cvs rdiff -u -r1.1.1.6 -r1.1.1.6.2.1 \
    src/external/bsd/dhcpcd/dist/src/control.c \
    src/external/bsd/dhcpcd/dist/src/dhcp-common.c \
    src/external/bsd/dhcpcd/dist/src/duid.c
cvs rdiff -u -r1.1.1.4 -r1.1.1.4.2.1 \
    src/external/bsd/dhcpcd/dist/src/control.h
cvs rdiff -u -r1.1.1.25 -r1.1.1.25.2.1 \
    src/external/bsd/dhcpcd/dist/src/defs.h
cvs rdiff -u -r1.23 -r1.23.2.1 src/external/bsd/dhcpcd/dist/src/dhcp.c \
    src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.2 -r1.2.2.1 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in
cvs rdiff -u -r1.1.1.13 -r1.1.1.13.2.1 \
    src/external/bsd/dhcpcd/dist/src/dhcpcd.conf.5.in
cvs rdiff -u -r1.10 -r1.10.2.1 src/external/bsd/dhcpcd/dist/src/if-bsd.c \
    src/external/bsd/dhcpcd/dist/src/ipv6nd.c
cvs rdiff -u -r1.1.1.14 -r1.1.1.14.2.1 \
    src/external/bsd/dhcpcd/dist/src/if-linux.c \
    src/external/bsd/dhcpcd/dist/src/if.c
cvs rdiff -u -r1.16 -r1.16.2.1 src/external/bsd/dhcpcd/dist/src/if-options.c
cvs rdiff -u -r1.1.1.9 -r1.1.1.9.2.1 \
    src/external/bsd/dhcpcd/dist/src/if-options.h \
    src/external/bsd/dhcpcd/dist/src/ipv4.h
cvs rdiff -u -r1.1.1.10 -r1.1.1.10.2.1 \
    src/external/bsd/dhcpcd/dist/src/if-sun.c \
    src/external/bsd/dhcpcd/dist/src/if.h \
    src/external/bsd/dhcpcd/dist/src/ipv6nd.h \
    src/external/bsd/dhcpcd/dist/src/script.c
cvs rdiff -u -r1.1.1.16 -r1.1.1.16.2.1 \
    src/external/bsd/dhcpcd/dist/src/ipv4.c
cvs rdiff -u -r1.3 -r1.3.2.1 src/external/bsd/dhcpcd/dist/src/ipv6.c \
    src/external/bsd/dhcpcd/dist/src/ipv6.h
cvs rdiff -u -r1.1.1.12 -r1.1.1.12.2.1 \
    src/external/bsd/dhcpcd/dist/src/route.c
cvs rdiff -u -r1.1.1.7 -r1.1.1.7.2.1 src/external/bsd/dhcpcd/dist/src/route.h

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/BUILDING.md
diff -u src/external/bsd/dhcpcd/dist/BUILDING.md:1.1.1.4 src/external/bsd/dhcpcd/dist/BUILDING.md:1.1.1.4.2.1
--- src/external/bsd/dhcpcd/dist/BUILDING.md:1.1.1.4	Tue Jul 30 10:23:01 2019
+++ src/external/bsd/dhcpcd/dist/BUILDING.md	Thu Sep  5 08:56:55 2019
@@ -134,9 +134,13 @@ You can decide which polling mechanism d
 
 
 ## Importing into another source control system
-To prepare dhcpcd for import into a platform source tree (like NetBSD)
-you can use the make import target to create /tmp/dhcpcd-$version and
-populate it with all the source files and hooks needed.
+To import the full sources, use the import target.
+To import only the needed sources and documentation, use the import-src
+target.
+Both targets support DESTDIR to set the installation directory,
+if unset it defaults to `/tmp/dhcpcd-$VERSION`
+Example: `make DESTDIR=/usr/src/contrib/dhcpcd import-src`
+
 In this instance, you may wish to disable some configured tests when
 the binary has to run on older versions which lack support, such as getline.
 `./configure --without-getline`

Index: src/external/bsd/dhcpcd/dist/Makefile
diff -u src/external/bsd/dhcpcd/dist/Makefile:1.1.1.6 src/external/bsd/dhcpcd/dist/Makefile:1.1.1.6.2.1
--- src/external/bsd/dhcpcd/dist/Makefile:1.1.1.6	Wed Apr 17 23:33:08 2019
+++ src/external/bsd/dhcpcd/dist/Makefile	Thu Sep  5 08:56:55 2019
@@ -2,8 +2,7 @@ SUBDIRS=	src hooks
 
 VERSION!=	sed -n 's/\#define VERSION[[:space:]]*"\(.*\)".*/\1/p' src/defs.h
 
-DIST!=		if test -f .fslckout; then echo "dist-fossil"; \
-		elif test -d .git; then echo "dist-git"; \
+DIST!=		if test -d .git; then echo "dist-git"; \
 		else echo "dist-inst"; fi
 FOSSILID?=	current
 GITREF?=	HEAD
@@ -52,12 +51,6 @@ distclean: clean
 	rm -f config.h config.mk config.log \
 		${DISTFILE} ${DISTFILEGZ} ${DISTINFO} ${DISTINFOSIGN}
 
-
-dist-fossil:
-	fossil tarball --name ${DISTPREFIX} ${FOSSILID} ${DISTFILEGZ}
-	gunzip -c ${DISTFILEGZ} | xz >${DISTFILE}
-	rm ${DISTFILEGZ}
-
 dist-git:
 	git archive --prefix=${DISTPREFIX}/ ${GITREF} | xz >${DISTFILE}
 
@@ -86,9 +79,28 @@ snapshot:
 	tar cf - -C /tmp ${DISTPREFIX} | xz >${DISTFILE}
 	ls -l ${DISTFILE}
 
-import: dist
-	rm -rf /tmp/${DISTPREFIX}
-	${INSTALL} -d /tmp/${DISTPREFIX}
-	tar xvJpf ${DISTFILE} -C /tmp
+_import: dist
+	rm -rf ${DESTDIR}/*
+	${INSTALL} -d ${DESTDIR}
+	tar xvpf ${DISTFILE} -C ${DESTDIR} --strip 1
+	@${ECHO}
+	@${ECHO} "============================================================="
+	@${ECHO} "dhcpcd-${VERSION} imported to ${DESTDIR}"
+
+import:
+	${MAKE} _import DESTDIR=`if [ -n "${DESTDIR}" ]; then echo "${DESTDIR}"; else  echo /tmp/${DISTPREFIX}; fi`
+
+
+_import-src:
+	rm -rf ${DESTDIR}/*
+	${INSTALL} -d ${DESTDIR}
+	cp LICENSE README.md ${DESTDIR};
+	for x in ${SUBDIRS}; do cd $$x; ${MAKE} DESTDIR=${DESTDIR} $@ || exit $$?; cd ..; done
+	@${ECHO}
+	@${ECHO} "============================================================="
+	@${ECHO} "dhcpcd-${VERSION} imported to ${DESTDIR}"
+
+import-src:
+	${MAKE} _import-src DESTDIR=`if [ -n "${DESTDIR}" ]; then echo "${DESTDIR}"; else  echo /tmp/${DISTPREFIX}; fi`
 
 include Makefile.inc

Index: src/external/bsd/dhcpcd/dist/Makefile.inc
diff -u src/external/bsd/dhcpcd/dist/Makefile.inc:1.1.1.2 src/external/bsd/dhcpcd/dist/Makefile.inc:1.1.1.2.8.1
--- src/external/bsd/dhcpcd/dist/Makefile.inc:1.1.1.2	Tue Sep 19 19:16:48 2017
+++ src/external/bsd/dhcpcd/dist/Makefile.inc	Thu Sep  5 08:56:55 2019
@@ -8,6 +8,7 @@ MANMODE?=	${NONBINMODE}
 CONFMODE?=	0644
 
 CC?=		cc
+ECHO?=		echo
 INSTALL?=	install
 LINT?=		lint
 SED?=		sed

Index: src/external/bsd/dhcpcd/dist/configure
diff -u src/external/bsd/dhcpcd/dist/configure:1.1.1.14 src/external/bsd/dhcpcd/dist/configure:1.1.1.14.2.1
--- src/external/bsd/dhcpcd/dist/configure:1.1.1.14	Tue Jul 30 10:23:02 2019
+++ src/external/bsd/dhcpcd/dist/configure	Thu Sep  5 08:56:55 2019
@@ -179,25 +179,6 @@ done
 : ${WC:=wc}
 
 : ${FORK:=yes}
-: ${SYSCONFDIR:=$PREFIX/etc}
-: ${SBINDIR:=$PREFIX/sbin}
-: ${LIBDIR:=$PREFIX/lib}
-: ${LIBEXECDIR:=$PREFIX/libexec}
-: ${STATEDIR:=/var}
-: ${DBDIR:=$STATEDIR/db/dhcpcd}
-: ${RUNDIR:=$STATEDIR/run}
-: ${MANDIR:=${PREFIX:-/usr}/share/man}
-: ${DATADIR:=${PREFIX:-/usr}/share}
-
-eval SYSCONFDIR="$SYSCONFDIR"
-eval LIBDIR="$LIBDIR"
-eval LIBEXECDIR="$LIBEXECDIR"
-eval STATEDIR="$STATEDIR"
-eval DBDIR="$DBDIR"
-eval RUNDIR="$RUNDIR"
-eval MANDIR="$MANDIR"
-eval DATADIR="$DATADIR"
-
 _which()
 {
 	x="$(which "$1" 2>/dev/null)"
@@ -252,6 +233,10 @@ if [ -z "$OS" ]; then
 	esac
 	# Special case
 	case "$OS" in
+	dragonfly*)
+		# This means /usr HAS to be mounted not via dhcpcd
+		: ${LIBEXECDIR:=${PREFIX:-/usr}/libexec}
+		;;
 	gnu*) OS=hurd;; # No HURD support as yet
 	esac
 fi
@@ -261,6 +246,26 @@ rm -f $CONFIG_H $CONFIG_MK
 echo "# $OS" >$CONFIG_MK
 echo "/* $OS */" >$CONFIG_H
 
+: ${SYSCONFDIR:=$PREFIX/etc}
+: ${SBINDIR:=$PREFIX/sbin}
+: ${LIBDIR:=$PREFIX/lib}
+: ${LIBEXECDIR:=$PREFIX/libexec}
+: ${STATEDIR:=/var}
+: ${DBDIR:=$STATEDIR/db/dhcpcd}
+: ${RUNDIR:=$STATEDIR/run}
+: ${MANDIR:=${PREFIX:-/usr}/share/man}
+: ${DATADIR:=${PREFIX:-/usr}/share}
+
+eval SYSCONFDIR="$SYSCONFDIR"
+eval LIBDIR="$LIBDIR"
+eval LIBEXECDIR="$LIBEXECDIR"
+eval STATEDIR="$STATEDIR"
+eval DBDIR="$DBDIR"
+eval RUNDIR="$RUNDIR"
+eval MANDIR="$MANDIR"
+eval DATADIR="$DATADIR"
+
+echo "#ifndef	SYSCONFDIR" >>$CONFIG_H
 for x in SYSCONFDIR SBINDIR LIBDIR LIBEXECDIR DBDIR RUNDIR; do
 	eval v=\$$x
 	# Make files look nice for import
@@ -272,6 +277,8 @@ for x in SYSCONFDIR SBINDIR LIBDIR LIBEX
 	[ $l -gt 2 ] && t="	"
 	echo "#define	$x$t		\"$v\"" >>$CONFIG_H
 done
+echo "#endif" >>$CONFIG_H
+
 echo "LIBDIR=		$LIBDIR" >>$CONFIG_MK
 echo "MANDIR=		$MANDIR" >>$CONFIG_MK
 echo "DATADIR=	$DATADIR" >>$CONFIG_MK
@@ -452,8 +459,6 @@ qnx*)
 	echo "DHCPCD_SRCS+=	if-bsd.c" >>$CONFIG_MK
 	;;
 sunos*)
-	echo "WARNING!!! Solaris support is at early development stage!" >&2
-	echo "so don't expect it to work just yet, patches welcome" >&2
 	echo "CPPFLAGS+=	-D_XPG4_2 -D__EXTENSIONS__ -DBSD_COMP" \
 	    >>$CONFIG_MK
 	echo "DHCPCD_SRCS+=	if-sun.c" >>$CONFIG_MK
@@ -497,10 +502,6 @@ if [ -z "$AUTH" -o "$AUTH" = yes ]; then
 	echo "Enabling Authentication"
 	echo "CPPFLAGS+=	-DAUTH" >>$CONFIG_MK
 	echo "SRCS+=		auth.c" >>$CONFIG_MK
-	echo "CRYPT_SRCS+=	\${HMAC_SRC}" >>$CONFIG_MK
-fi
-if [ -z "$INET6" -o "$INET6" = yes -o -z "$AUTH" -o "$AUTH" = yes ]; then
-	echo "CRYPT_SRCS+=	\${MD5_SRC} \${SHA256_SRC}" >>$CONFIG_MK
 fi
 
 echo "Using compiler .. $CC"
@@ -931,6 +932,30 @@ EOF
 	echo "$TAILQ_FOREACH_SAFE"
 	rm -f _queue.c _queue
 fi
+if [ "$TAILQ_FOREACH_SAFE" = no ] && [ -z "$TAILQ_FOREACH_MUTABLE" ]; then
+	printf "Testing for TAILQ_FOREACH_MUTABLE ... "
+	cat <<EOF >_queue.c
+#include <sys/queue.h>
+int main(void) {
+#ifndef TAILQ_FOREACH_MUTABLE
+#error TAILQ_FOREACH_MUTABLE
+#endif
+	return 0;
+}
+EOF
+	if $XCC _queue.c -o _queue 2>&3; then
+		TAILQ_FOREACH_MUTABLE=yes
+		TAILQ_FOREACH_SAFE=yes
+		TAILQ_FOREACH=yes
+		echo "#define	TAILQ_FOREACH_SAFE	TAILQ_FOREACH_MUTABLE" \
+			>> $CONFIG_H
+	else
+		TAILQ_FOREACH_MUTABLE=no
+	fi
+	echo "$TAILQ_FOREACH_MUTABLE"
+	rm -f _queue.c _queue
+fi
+
 
 if [ -z "$TAILQ_CONCAT" ]; then
 	printf "Testing for TAILQ_CONCAT ..."
@@ -1007,7 +1032,7 @@ EOF
 	rm -f _rbtree.c _rbtree
 fi
 if [ "$RBTREE" = no ]; then
-	echo "CPPFLAGS+=	-DRBTEST" >>$CONFIG_MK
+	echo "#define	RBTEST" >>$CONFIG_H
 	echo "COMPAT_SRCS+=	compat/rb.c" >>$CONFIG_MK
 	echo "#include			\"compat/rbtree.h\"" >>$CONFIG_H
 else
@@ -1186,6 +1211,14 @@ if [ "$FLS64" = yes ]; then
 	echo "#define	HAVE_SYS_BITOPS_H" >>$CONFIG_H
 fi
 
+# Workaround for DragonFlyBSD import
+if [ "$OS" = dragonfly ]; then
+	echo "#ifdef	USE_PRIVATECRYPTO" >>$CONFIG_H
+	echo "#define	HAVE_MD5_H" >>$CONFIG_H
+	echo "#define	SHA2_H	<sha256.h>" >>$CONFIG_H
+	echo "#else" >>$CONFIG_H
+fi
+
 if [ -z "$MD5" ]; then
 	MD5_LIB=
 	printf "Testing for MD5Init ... "
@@ -1322,6 +1355,9 @@ else
 	[ -n "$SHA2_LIB" ] && echo "LDADD+=		$SHA2_LIB" >>$CONFIG_MK
 fi
 
+# Workarond for DragonFlyBSD import
+[ "$OS" = dragonfly ] && echo "#endif" >>$CONFIG_H
+
 if [ -z "$HMAC" ]; then
 	HMAC_LIB=
 	printf "Testing for hmac ... "
@@ -1363,6 +1399,21 @@ else
 	echo "HMAC_SRC=" >>$CONFIG_MK
 fi
 
+if [ -z "$AUTH" ] || [ "$AUTH" = yes ]; then
+	if [ "$HMAC" = no ]; then
+		echo "CRYPT_SRCS+=	\${HMAC_SRC}" >>$CONFIG_MK
+	fi
+fi
+if [ -z "$INET6" ] || [ "$INET6" = yes ] || \
+    [ -z "$AUTH" ] || [ "$AUTH" = yes ]; then
+	if [ "$MD5" = no ]; then
+		echo "CRYPT_SRCS+=	\${MD5_SRC}" >>$CONFIG_MK
+	fi
+	if [ "$SHA2" = no ]; then
+		echo "CRYPT_SRCS+=	\${SHA256_SRC}" >>$CONFIG_MK
+	fi
+fi
+
 if [ "$DEV" != no -a "$UDEV" != no ]; then
 	printf "Checking for libudev ... "
 	if type "$PKG_CONFIG" >/dev/null 2>&1; then

Index: src/external/bsd/dhcpcd/dist/compat/rb.c
diff -u src/external/bsd/dhcpcd/dist/compat/rb.c:1.1.1.1 src/external/bsd/dhcpcd/dist/compat/rb.c:1.1.1.1.2.1
--- src/external/bsd/dhcpcd/dist/compat/rb.c:1.1.1.1	Wed Jul 24 09:54:48 2019
+++ src/external/bsd/dhcpcd/dist/compat/rb.c	Thu Sep  5 08:56:55 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: rb.c,v 1.1.1.1 2019/07/24 09:54:48 roy Exp $	*/
+/*	$NetBSD: rb.c,v 1.1.1.1.2.1 2019/09/05 08:56:55 martin Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -29,6 +29,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "config.h"
 #include "common.h"
 
 #if !defined(_KERNEL) && !defined(_STANDALONE)
@@ -43,10 +44,10 @@
 #define KASSERT(s)	do { } while (/*CONSTCOND*/ 0)
 #define	__rbt_unused	__unused
 #endif
-__RCSID("$NetBSD: rb.c,v 1.1.1.1 2019/07/24 09:54:48 roy Exp $");
+__RCSID("$NetBSD: rb.c,v 1.1.1.1.2.1 2019/09/05 08:56:55 martin Exp $");
 #else
 #include <lib/libkern/libkern.h>
-__KERNEL_RCSID(0, "$NetBSD: rb.c,v 1.1.1.1 2019/07/24 09:54:48 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rb.c,v 1.1.1.1.2.1 2019/09/05 08:56:55 martin Exp $");
 #ifndef DIAGNOSTIC
 #define	__rbt_unused	__unused
 #else
Index: src/external/bsd/dhcpcd/dist/compat/rbtree.h
diff -u src/external/bsd/dhcpcd/dist/compat/rbtree.h:1.1.1.1 src/external/bsd/dhcpcd/dist/compat/rbtree.h:1.1.1.1.2.1
--- src/external/bsd/dhcpcd/dist/compat/rbtree.h:1.1.1.1	Wed Jul 24 09:54:48 2019
+++ src/external/bsd/dhcpcd/dist/compat/rbtree.h	Thu Sep  5 08:56:55 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: rbtree.h,v 1.1.1.1 2019/07/24 09:54:48 roy Exp $	*/
+/*	$NetBSD: rbtree.h,v 1.1.1.1.2.1 2019/09/05 08:56:55 martin Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -32,6 +32,7 @@
 #ifndef _SYS_RBTREE_H_
 #define	_SYS_RBTREE_H_
 
+#include "config.h"
 #include "common.h"
 
 #if defined(_KERNEL) || defined(_STANDALONE)
@@ -40,7 +41,11 @@
 #include <stdbool.h>
 #include <inttypes.h>
 #endif
+#ifdef HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
+#else
 #include "queue.h"
+#endif
 #if !defined(__linux__) && !defined(__QNX__) && !defined(__sun)
 #include <sys/endian.h>
 #else

Index: src/external/bsd/dhcpcd/dist/hooks/Makefile
diff -u src/external/bsd/dhcpcd/dist/hooks/Makefile:1.1.1.1 src/external/bsd/dhcpcd/dist/hooks/Makefile:1.1.1.1.20.1
--- src/external/bsd/dhcpcd/dist/hooks/Makefile:1.1.1.1	Fri Mar 31 20:51:16 2017
+++ src/external/bsd/dhcpcd/dist/hooks/Makefile	Thu Sep  5 08:56:55 2019
@@ -61,4 +61,11 @@ import: ${HOOKSCRIPTS}
 	${INSTALL} -m ${NONBINMODE} ${SCRIPTS} /tmp/${DISTPREFIX}/dhcpcd-hooks
 	${INSTALL} -m ${NONBINMODE} ${FILES} /tmp/${DISTPREFIX}/dhcpcd-hooks
 
+_import-src:
+	${INSTALL} -d ${DESTDIR}/hooks
+	cp dhcpcd-run-hooks.in dhcpcd-run-hooks.8.in [0-9]* ${DESTDIR}/hooks
+	rm ${DESTDIR}/hooks/50-dhcpcd-compat
+	if [ `uname` = Linux ]; then rm ${DESTDIR}/hooks/50-ypbind.in; \
+		else rm ${DESTDIR}/hooks/50-yp.conf; fi
+
 include ${TOP}/Makefile.inc

Index: src/external/bsd/dhcpcd/dist/src/Makefile
diff -u src/external/bsd/dhcpcd/dist/src/Makefile:1.1.1.5 src/external/bsd/dhcpcd/dist/src/Makefile:1.1.1.5.2.1
--- src/external/bsd/dhcpcd/dist/src/Makefile:1.1.1.5	Wed Apr 17 23:33:08 2019
+++ src/external/bsd/dhcpcd/dist/src/Makefile	Thu Sep  5 08:56:55 2019
@@ -135,4 +135,38 @@ clean:
 distclean: clean
 	rm -f .depend
 
+_import-src: ${SRCS}
+	${INSTALL} -d ${DESTDIR}/src
+	touch if-bsd.h if-linux.h if-sun.h
+	cp defs.h ${SRCS} ${SRCS:.c=.h} dev.h ${MAN5}.in ${MAN8}.in ${DESTDIR}/src
+	rm if-bsd.h if-linux.h if-sun.h
+	rm -f ${DESTDIR}/src/if-bsd.h ${DESTDIR}/src/if-linux.h ${DESTDIR}/src/if-sun.h
+	if [ -n "${COMPAT_SRCS}" ]; then \
+		${INSTALL} -d ${DESTDIR}/compat; \
+		cd ..; \
+		touch compat/rb.h compat/strtou.h; \
+		cp ${COMPAT_SRCS} ${COMPAT_SRCS:.c=.h} ${DESTDIR}/compat; \
+		rm compat/rb.h compat/strtou.h; \
+		rm -f ${DESTDIR}/compat/rb.h ${DESTDIR}/compat/strtou.h; \
+	fi
+	if ! grep HAVE_SYS_BITOPS_H ../config.h; then \
+		cp ../compat/bitops.h ${DESTDIR}/compat; \
+	fi
+	if grep compat/consttime_memequal.h ../config.h; then \
+		cp ../compat/consttime_memequal.h ${DESTDIR}/compat; \
+	fi
+	if [ -e ${DESTDIR}/compat/rb.c ]; then \
+		cp ../compat/rbtree.h ${DESTDIR}/compat; \
+	fi
+	if [ -e ${DESTDIR}/compat/strtoi.c ]; then \
+		cp ../compat/_strtoi.h ${DESTDIR}/compat; \
+	fi
+	if [ -n "${CRYPT_SRCS}" ]; then \
+		${INSTALL} -d ${DESTDIR}/compat/crypt; \
+		cd ..; \
+		cp ${CRYPT_SRCS} ${CRYPT_SRCS:.c=.h} ${DESTDIR}/compat/crypt; \
+	fi
+	# DragonFlyBSD builds base version with private crypto
+	if [ `uname` = DragonFly ]; then rm ${DESTDIR}/compat/crypt/md5* ${DESTDIR}/compat/crypt/sha256*; fi
+
 include ${TOP}/Makefile.inc
Index: src/external/bsd/dhcpcd/dist/src/sa.c
diff -u src/external/bsd/dhcpcd/dist/src/sa.c:1.1.1.5 src/external/bsd/dhcpcd/dist/src/sa.c:1.1.1.5.2.1
--- src/external/bsd/dhcpcd/dist/src/sa.c:1.1.1.5	Wed Jul 24 09:54:55 2019
+++ src/external/bsd/dhcpcd/dist/src/sa.c	Thu Sep  5 08:56:55 2019
@@ -288,11 +288,9 @@ sa_toprefix(const struct sockaddr *sa)
 #ifndef NDEBUG
 	/* Ensure the calculation is correct */
 	if (!sa_inprefix) {
-		union sa_ss ss;
+		union sa_ss ss = { .sa.sa_family = sa->sa_family };
 
 		sa_inprefix = true;
-		memset(&ss, 0, sizeof(ss));
-		ss.sa.sa_family = sa->sa_family;
 		sa_fromprefix(&ss.sa, prefix);
 		assert(sa_cmp(sa, &ss.sa) == 0);
 		sa_inprefix = false;

Index: src/external/bsd/dhcpcd/dist/src/bpf.c
diff -u src/external/bsd/dhcpcd/dist/src/bpf.c:1.11 src/external/bsd/dhcpcd/dist/src/bpf.c:1.11.2.1
--- src/external/bsd/dhcpcd/dist/src/bpf.c:1.11	Tue Jul 30 10:25:03 2019
+++ src/external/bsd/dhcpcd/dist/src/bpf.c	Thu Sep  5 08:56:55 2019
@@ -558,6 +558,15 @@ bpf_arp(struct interface *ifp, int fd)
 #define	BPF_M_UDP	3
 #define	BPF_M_UDPLEN	4
 
+#ifdef ARPHRD_NONE
+static const struct bpf_insn bpf_bootp_none[] = {
+	/* Set the frame header length to zero. */
+	BPF_STMT(BPF_LD + BPF_IMM, 0),
+	BPF_STMT(BPF_ST, BPF_M_FHLEN),
+};
+#define BPF_BOOTP_NONE_LEN	__arraycount(bpf_bootp_none)
+#endif
+
 static const struct bpf_insn bpf_bootp_ether[] = {
 	/* Make sure this is an IP packet. */
 	BPF_STMT(BPF_LD + BPF_H + BPF_ABS,
@@ -665,6 +674,12 @@ bpf_bootp(struct interface *ifp, int fd)
 	bp = bpf;
 	/* Check frame header. */
 	switch(ifp->family) {
+#ifdef ARPHRD_NONE
+	case ARPHRD_NONE:
+		memcpy(bp, bpf_bootp_none, sizeof(bpf_bootp_none));
+		bp += BPF_BOOTP_NONE_LEN;
+		break;
+#endif
 	case ARPHRD_ETHER:
 		memcpy(bp, bpf_bootp_ether, sizeof(bpf_bootp_ether));
 		bp += BPF_BOOTP_ETHER_LEN;
Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.11 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.11.2.1
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.11	Tue Jul 30 10:25:03 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c	Thu Sep  5 08:56:55 2019
@@ -2488,22 +2488,22 @@ dhcp6_readlease(struct interface *ifp, i
 	struct dhcp6_state *state;
 	struct stat st;
 	int fd;
-	struct dhcp6_message *lease;
 	time_t now;
 	int retval;
-	bool fd_opened;
+	bool read_stdin, fd_opened;
 #ifdef AUTH
 	uint8_t *o;
 	uint16_t ol;
 #endif
 
 	state = D6_STATE(ifp);
-	if (state->leasefile[0] == '\0') {
+	read_stdin = state->leasefile[0] == '\0';
+	if (read_stdin) {
 		logdebugx("reading standard input");
 		fd = fileno(stdin);
 		fd_opened = false;
 	} else {
-		logdebugx("%s: reading lease `%s'", ifp->name, state->leasefile);
+		logdebugx("%s: reading lease `%s'", ifp->name,state->leasefile);
 		fd = open(state->leasefile, O_RDONLY);
 		if (fd != -1 && fstat(fd, &st) == -1) {
 			close(fd);
@@ -2514,19 +2514,19 @@ dhcp6_readlease(struct interface *ifp, i
 	if (fd == -1)
 		return -1;
 	retval = -1;
-	lease = NULL;
 	free(state->new);
-	state->new_len = dhcp_read_lease_fd(fd, (void **)&lease);
-	state->new = lease;
+	state->new_len = dhcp_read_lease_fd(fd, (void **)&state->new);
 	if (fd_opened)
 		close(fd);
-	if (state->new_len == 0)
-		goto ex;
 
-	if (ifp->ctx->options & DHCPCD_DUMPLEASE ||
-	    state->leasefile[0] == '\0')
+	if (ifp->ctx->options & DHCPCD_DUMPLEASE || read_stdin)
 		return 0;
 
+	if (state->new_len == 0) {
+		retval = 0;
+		goto ex;
+	}
+
 	/* If not validating IA's and if they have expired,
 	 * skip to the auth check. */
 	if (!validate) {
@@ -2546,14 +2546,12 @@ dhcp6_readlease(struct interface *ifp, i
 		goto ex;
 
 	if (state->expire != ND6_INFINITE_LIFETIME &&
-	    state->leasefile[0] != '\0')
+	    (time_t)state->expire < now - st.st_mtime &&
+	    !(ifp->options->options & DHCPCD_LASTLEASE_EXTEND))
 	{
-		if ((time_t)state->expire < now - st.st_mtime &&
-		    !(ifp->options->options & DHCPCD_LASTLEASE_EXTEND)) {
-			logdebugx("%s: discarding expired lease", ifp->name);
-			retval = 0;
-			goto ex;
-		}
+		logdebugx("%s: discarding expired lease", ifp->name);
+		retval = 0;
+		goto ex;
 	}
 
 auth:
@@ -2586,12 +2584,10 @@ auth:
 
 ex:
 	dhcp6_freedrop_addrs(ifp, 0, NULL);
+	unlink(state->leasefile);
 	free(state->new);
 	state->new = NULL;
 	state->new_len = 0;
-	if (!(ifp->ctx->options & DHCPCD_DUMPLEASE) &&
-	    state->leasefile[0] != '\0')
-		unlink(state->leasefile);
 	return retval;
 }
 

Index: src/external/bsd/dhcpcd/dist/src/control.c
diff -u src/external/bsd/dhcpcd/dist/src/control.c:1.1.1.6 src/external/bsd/dhcpcd/dist/src/control.c:1.1.1.6.2.1
--- src/external/bsd/dhcpcd/dist/src/control.c:1.1.1.6	Wed Jul 24 09:54:49 2019
+++ src/external/bsd/dhcpcd/dist/src/control.c	Thu Sep  5 08:56:55 2019
@@ -53,41 +53,26 @@
 #endif
 
 static void
-control_queue_purge(struct dhcpcd_ctx *ctx, char *data)
-{
-	int found;
-	struct fd_list *fp;
-	struct fd_data *fpd;
-
-	/* If no other fd queue has the same data, free it */
-	found = 0;
-	TAILQ_FOREACH(fp, &ctx->control_fds, next) {
-		TAILQ_FOREACH(fpd, &fp->queue, next) {
-			if (fpd->data == data) {
-				found = 1;
-				break;
-			}
-		}
-	}
-	if (!found)
-		free(data);
-}
-
-static void
 control_queue_free(struct fd_list *fd)
 {
 	struct fd_data *fdp;
 
 	while ((fdp = TAILQ_FIRST(&fd->queue))) {
 		TAILQ_REMOVE(&fd->queue, fdp, next);
-		if (fdp->freeit)
-			control_queue_purge(fd->ctx, fdp->data);
+		if (fdp->data_size != 0)
+			free(fdp->data);
 		free(fdp);
 	}
+	fd->queue_len = 0;
+
+#ifdef CTL_FREE_LIST
 	while ((fdp = TAILQ_FIRST(&fd->free_queue))) {
 		TAILQ_REMOVE(&fd->free_queue, fdp, next);
+		if (fdp->data_size != 0)
+			free(fdp->data);
 		free(fdp);
 	}
+#endif
 }
 
 static void
@@ -161,29 +146,33 @@ control_handle1(struct dhcpcd_ctx *ctx, 
 
 	len = sizeof(run);
 	if ((fd = accept(lfd, (struct sockaddr *)&run, &len)) == -1)
-		return;
+		goto error;
 	if ((flags = fcntl(fd, F_GETFD, 0)) == -1 ||
 	    fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
-	{
-		close(fd);
-	        return;
-	}
+		goto error;
 	if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
 	    fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
-	{
-		close(fd);
-	        return;
-	}
+		goto error;
+
 	l = malloc(sizeof(*l));
-	if (l) {
-		l->ctx = ctx;
-		l->fd = fd;
-		l->flags = fd_flags;
-		TAILQ_INIT(&l->queue);
-		TAILQ_INIT(&l->free_queue);
-		TAILQ_INSERT_TAIL(&ctx->control_fds, l, next);
-		eloop_event_add(ctx->eloop, l->fd, control_handle_data, l);
-	} else
+	if (l == NULL)
+		goto error;
+
+	l->ctx = ctx;
+	l->fd = fd;
+	l->flags = fd_flags;
+	TAILQ_INIT(&l->queue);
+	l->queue_len = 0;
+#ifdef CTL_FREE_LIST
+	TAILQ_INIT(&l->free_queue);
+#endif
+	TAILQ_INSERT_TAIL(&ctx->control_fds, l, next);
+	eloop_event_add(ctx->eloop, l->fd, control_handle_data, l);
+	return;
+
+error:
+	logerr(__func__);
+	if (fd != -1)
 		close(fd);
 }
 
@@ -374,40 +363,88 @@ control_writeone(void *arg)
 	}
 
 	TAILQ_REMOVE(&fd->queue, data, next);
-	if (data->freeit)
-		control_queue_purge(fd->ctx, data->data);
-	data->data = NULL; /* safety */
-	data->data_len = 0;
+	fd->queue_len--;
+#ifdef CTL_FREE_LIST
 	TAILQ_INSERT_TAIL(&fd->free_queue, data, next);
+#else
+	if (data->data_size != 0)
+		free(data->data);
+	free(data);
+#endif
 
 	if (TAILQ_FIRST(&fd->queue) == NULL)
 		eloop_event_remove_writecb(fd->ctx->eloop, fd->fd);
 }
 
 int
-control_queue(struct fd_list *fd, char *data, size_t data_len, uint8_t fit)
+control_queue(struct fd_list *fd, void *data, size_t data_len, bool fit)
 {
 	struct fd_data *d;
-	size_t n;
 
-	d = TAILQ_FIRST(&fd->free_queue);
-	if (d) {
-		TAILQ_REMOVE(&fd->free_queue, d, next);
-	} else {
-		n = 0;
-		TAILQ_FOREACH(d, &fd->queue, next) {
-			if (++n == CONTROL_QUEUE_MAX) {
-				errno = ENOBUFS;
-				return -1;
+	if (data_len == 0)
+		return 0;
+
+#ifdef CTL_FREE_LIST
+	struct fd_data *df;
+
+	d = NULL;
+	TAILQ_FOREACH(df, &fd->free_queue, next) {
+		if (!fit) {
+			if (df->data_size == 0) {
+				d = df;
+				break;
 			}
+			continue;
+		}
+		if (d == NULL || d->data_size < df->data_size) {
+			d = df;
+			if (d->data_size <= data_len)
+				break;
+		}
+	}
+	if (d != NULL)
+		TAILQ_REMOVE(&fd->free_queue, d, next);
+	else
+#endif
+	{
+		if (fd->queue_len == CONTROL_QUEUE_MAX) {
+			errno = ENOBUFS;
+			return -1;
 		}
-		d = malloc(sizeof(*d));
+		fd->queue_len++;
+		d = calloc(1, sizeof(*d));
 		if (d == NULL)
 			return -1;
 	}
-	d->data = data;
+
+	if (!fit) {
+#ifdef CTL_FREE_LIST
+		if (d->data_size != 0) {
+			free(d->data);
+			d->data_size = 0;
+		}
+#endif
+		d->data = data;
+		d->data_len = data_len;
+		goto queue;
+	}
+
+	if (d->data_size == 0)
+		d->data = NULL;
+	if (d->data_size < data_len) {
+		void *nbuf = realloc(d->data, data_len);
+		if (nbuf == NULL) {
+			free(d->data);
+			free(d);
+			return -1;
+		}
+		d->data = nbuf;
+		d->data_size = data_len;
+	}
+	memcpy(d->data, data, data_len);
 	d->data_len = data_len;
-	d->freeit = fit;
+
+queue:
 	TAILQ_INSERT_TAIL(&fd->queue, d, next);
 	eloop_event_add_w(fd->ctx->eloop, fd->fd, control_writeone, fd);
 	return 0;
Index: src/external/bsd/dhcpcd/dist/src/dhcp-common.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp-common.c:1.1.1.6 src/external/bsd/dhcpcd/dist/src/dhcp-common.c:1.1.1.6.2.1
--- src/external/bsd/dhcpcd/dist/src/dhcp-common.c:1.1.1.6	Wed Jul 24 09:54:49 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp-common.c	Thu Sep  5 08:56:55 2019
@@ -622,6 +622,7 @@ print_option(FILE *fp, const char *prefi
     int vname,
     const uint8_t *data, size_t dl, const char *ifname)
 {
+	fpos_t fp_pos;
 	const uint8_t *e, *t;
 	uint16_t u16;
 	int16_t s16;
@@ -636,25 +637,32 @@ print_option(FILE *fp, const char *prefi
 	if ((ssize_t)dl == -1)
 		return 0;
 
-	if (fprintf(fp, "%s", prefix) == -1)
+	if (fgetpos(fp, &fp_pos) == -1)
 		return -1;
+	if (fprintf(fp, "%s", prefix) == -1)
+		goto err;
+
+	/* We printed something, so always goto err from now-on
+	 * to terminate the string. */
 	if (vname) {
 		if (fprintf(fp, "_%s", opt->var) == -1)
-			return -1;
+			goto err;
 	}
 	if (fputc('=', fp) == EOF)
-		return -1;
+		goto err;
 	if (dl == 0)
-		return 1;
+		goto done;
 
 	if (opt->type & OT_RFC1035) {
 		char domain[NS_MAXDNAME];
 
 		sl = decode_rfc1035(domain, sizeof(domain), data, dl);
-		if (sl == 0 || sl == -1)
-			return sl;
+		if (sl == -1)
+			goto err;
+		if (sl == 0)
+			goto done;
 		if (valid_domainname(domain, opt->type) == -1)
-			return -1;
+			goto err;
 		return efprintf(fp, "%s", domain);
 	}
 
@@ -670,7 +678,7 @@ print_option(FILE *fp, const char *prefi
 		char buf[1024];
 
 		if (print_string(buf, sizeof(buf), opt->type, data, dl) == -1)
-			return -1;
+			goto err;
 		return efprintf(fp, "%s", buf);
 	}
 
@@ -690,12 +698,10 @@ print_option(FILE *fp, const char *prefi
 			    *data & (1 << sl))
 			{
 				if (fputc(opt->bitflags[l], fp) == EOF)
-					return -1;
+					goto err;
 			}
 		}
-		if (fputc('\0', fp) == EOF)
-			return -1;
-		return 1;
+		goto done;
 	}
 
 	t = data;
@@ -703,66 +709,71 @@ print_option(FILE *fp, const char *prefi
 	while (data < e) {
 		if (data != t) {
 			if (fputc(' ', fp) == EOF)
-				return -1;
+				goto err;
 		}
 		if (opt->type & OT_UINT8) {
 			if (fprintf(fp, "%u", *data) == -1)
-				return -1;
+				goto err;
 			data++;
 		} else if (opt->type & OT_INT8) {
 			if (fprintf(fp, "%d", *data) == -1)
-				return -1;
+				goto err;
 			data++;
 		} else if (opt->type & OT_UINT16) {
 			memcpy(&u16, data, sizeof(u16));
 			u16 = ntohs(u16);
 			if (fprintf(fp, "%u", u16) == -1)
-				return -1;
+				goto err;
 			data += sizeof(u16);
 		} else if (opt->type & OT_INT16) {
 			memcpy(&u16, data, sizeof(u16));
 			s16 = (int16_t)ntohs(u16);
 			if (fprintf(fp, "%d", s16) == -1)
-				return -1;
+				goto err;
 			data += sizeof(u16);
 		} else if (opt->type & OT_UINT32) {
 			memcpy(&u32, data, sizeof(u32));
 			u32 = ntohl(u32);
 			if (fprintf(fp, "%u", u32) == -1)
-				return -1;
+				goto err;
 			data += sizeof(u32);
 		} else if (opt->type & OT_INT32) {
 			memcpy(&u32, data, sizeof(u32));
 			s32 = (int32_t)ntohl(u32);
 			if (fprintf(fp, "%d", s32) == -1)
-				return -1;
+				goto err;
 			data += sizeof(u32);
 		} else if (opt->type & OT_ADDRIPV4) {
 			memcpy(&addr.s_addr, data, sizeof(addr.s_addr));
 			if (fprintf(fp, "%s", inet_ntoa(addr)) == -1)
-				return -1;
+				goto err;
 			data += sizeof(addr.s_addr);
 		} else if (opt->type & OT_ADDRIPV6) {
 			char buf[INET6_ADDRSTRLEN];
 
 			if (inet_ntop(AF_INET6, data, buf, sizeof(buf)) == NULL)
-				return -1;
+				goto err;
 			if (fprintf(fp, "%s", buf) == -1)
-				return -1;
+				goto err;
 			if (data[0] == 0xfe && (data[1] & 0xc0) == 0x80) {
 				if (fprintf(fp,"%%%s", ifname) == -1)
-					return -1;
+					goto err;
 			}
 			data += 16;
 		} else {
 			errno = EINVAL;
-			return -1;
+			goto err;
 		}
 	}
 
+done:
 	if (fputc('\0', fp) == EOF)
 		return -1;
 	return 1;
+
+err:
+	(void)fsetpos(fp, &fp_pos);
+	return -1;
 }
 
 int
@@ -950,6 +961,8 @@ dhcp_read_lease_fd(int fd, void **lease)
 	}
 
 	sz = (size_t)st.st_size;
+	if (sz == 0)
+		goto out;
 	if ((buf = malloc(sz)) == NULL)
 		goto out;
 	if ((len = read(fd, buf, sz)) == -1) {
Index: src/external/bsd/dhcpcd/dist/src/duid.c
diff -u src/external/bsd/dhcpcd/dist/src/duid.c:1.1.1.6 src/external/bsd/dhcpcd/dist/src/duid.c:1.1.1.6.2.1
--- src/external/bsd/dhcpcd/dist/src/duid.c:1.1.1.6	Wed Jul 24 09:54:52 2019
+++ src/external/bsd/dhcpcd/dist/src/duid.c	Thu Sep  5 08:56:55 2019
@@ -52,10 +52,6 @@
 #include <time.h>
 #include <unistd.h>
 
-#ifndef ARPHRD_NETROM
-#  define ARPHRD_NETROM	0
-#endif
-
 #include "common.h"
 #include "dhcpcd.h"
 #include "duid.h"
@@ -189,10 +185,10 @@ duid_get(uint8_t **d, const struct inter
 		return len;
 
 	/* No UUID? OK, lets make one based on our interface */
-	if (ifp->family == ARPHRD_NETROM) {
-		logwarnx("%s: is a NET/ROM pseudo interface", ifp->name);
+	if (ifp->hwlen == 0) {
+		logwarnx("%s: does not have hardware address", ifp->name);
 		TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
-			if (ifp2->family != ARPHRD_NETROM)
+			if (ifp2->hwlen != 0)
 				break;
 		}
 		if (ifp2) {

Index: src/external/bsd/dhcpcd/dist/src/control.h
diff -u src/external/bsd/dhcpcd/dist/src/control.h:1.1.1.4 src/external/bsd/dhcpcd/dist/src/control.h:1.1.1.4.2.1
--- src/external/bsd/dhcpcd/dist/src/control.h:1.1.1.4	Wed Jul 24 09:54:49 2019
+++ src/external/bsd/dhcpcd/dist/src/control.h	Thu Sep  5 08:56:55 2019
@@ -31,14 +31,20 @@
 
 #include "dhcpcd.h"
 
+#if !defined(CTL_FREE_LIST)
+#define	CTL_FREE_LIST 1
+#elif CTL_FREE_LIST == 0
+#undef	CTL_FREE_LIST
+#endif
+
 /* Limit queue size per fd */
 #define CONTROL_QUEUE_MAX	100
 
 struct fd_data {
 	TAILQ_ENTRY(fd_data) next;
-	char *data;
+	void *data;
+	size_t data_size;
 	size_t data_len;
-	uint8_t freeit;
 };
 TAILQ_HEAD(fd_data_head, fd_data);
 
@@ -48,7 +54,10 @@ struct fd_list {
 	int fd;
 	unsigned int flags;
 	struct fd_data_head queue;
+	size_t queue_len;
+#ifdef CTL_FREE_LIST
 	struct fd_data_head free_queue;
+#endif
 };
 TAILQ_HEAD(fd_list_head, fd_list);
 
@@ -59,7 +68,7 @@ int control_start(struct dhcpcd_ctx *, c
 int control_stop(struct dhcpcd_ctx *);
 int control_open(const char *);
 ssize_t control_send(struct dhcpcd_ctx *, int, char * const *);
-int control_queue(struct fd_list *fd, char *data, size_t data_len, uint8_t fit);
+int control_queue(struct fd_list *, void *, size_t, bool);
 void control_close(struct dhcpcd_ctx *ctx);
 
 #endif

Index: src/external/bsd/dhcpcd/dist/src/defs.h
diff -u src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.25 src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.25.2.1
--- src/external/bsd/dhcpcd/dist/src/defs.h:1.1.1.25	Tue Jul 30 10:23:04 2019
+++ src/external/bsd/dhcpcd/dist/src/defs.h	Thu Sep  5 08:56:55 2019
@@ -29,7 +29,7 @@
 #define CONFIG_H
 
 #define PACKAGE			"dhcpcd"
-#define VERSION			"8.0.2"
+#define VERSION			"8.0.4"
 
 #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 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.23.2.1
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.23	Tue Jul 30 10:25:03 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c	Thu Sep  5 08:56:55 2019
@@ -1176,11 +1176,8 @@ read_lease(struct interface *ifp, struct
 	bytes = dhcp_read_lease_fd(fd, (void **)&lease);
 	if (fd_opened)
 		close(fd);
-	if (bytes == 0) {
-		free(lease);
-		logerr("%s: dhcp_read_lease_fd", __func__);
+	if (bytes == 0)
 		return 0;
-	}
 
 	/* Ensure the packet is at lease BOOTP sized
 	 * with a vendor area of 4 octets
@@ -1584,24 +1581,24 @@ eexit:
 }
 
 static uint16_t
-checksum(const void *data, size_t len)
+in_cksum(const void *data, size_t len, uint32_t *isum)
 {
-	const uint8_t *addr = data;
-	uint32_t sum = 0;
+	const uint16_t *word = data;
+	uint32_t sum = isum != NULL ? *isum : 0;
 
-	while (len > 1) {
-		sum += (uint32_t)(addr[0] * 256 + addr[1]);
-		addr += 2;
-		len -= 2;
-	}
+	for (; len > 1; len -= sizeof(*word))
+		sum += *word++;
 
 	if (len == 1)
-		sum += (uint32_t)(*addr * 256);
+		sum += htons((uint16_t)(*(const uint8_t *)word << 8));
+
+	if (isum != NULL)
+		*isum = sum;
 
 	sum = (sum >> 16) + (sum & 0xffff);
 	sum += (sum >> 16);
 
-	return (uint16_t)~htons((uint16_t)sum);
+	return (uint16_t)~sum;
 }
 
 static struct bootp_pkt *
@@ -1639,14 +1636,16 @@ dhcp_makeudppacket(size_t *sz, const uin
 	udp->uh_dport = htons(BOOTPS);
 	udp->uh_ulen = htons((uint16_t)(sizeof(*udp) + length));
 	ip->ip_len = udp->uh_ulen;
-	udp->uh_sum = checksum(udpp, sizeof(*ip) +  sizeof(*udp) + length);
+	udp->uh_sum = in_cksum(udpp, sizeof(*ip) + sizeof(*udp) + length, NULL);
 
 	ip->ip_v = IPVERSION;
 	ip->ip_hl = sizeof(*ip) >> 2;
 	ip->ip_id = (uint16_t)arc4random_uniform(UINT16_MAX);
 	ip->ip_ttl = IPDEFTTL;
 	ip->ip_len = htons((uint16_t)(sizeof(*ip) + sizeof(*udp) + length));
-	ip->ip_sum = checksum(ip, sizeof(*ip));
+	ip->ip_sum = in_cksum(ip, sizeof(*ip), NULL);
+	if (ip->ip_sum == 0)
+		ip->ip_sum = 0xffff; /* RFC 768 */
 
 	*sz = sizeof(*ip) + sizeof(*udp) + length;
 	return udpp;
@@ -2235,7 +2234,7 @@ dhcp_bind(struct interface *ifp)
 	ipv4_applyaddr(ifp);
 
 #ifdef IP_PKTINFO
-	/* Close the BPF filter as we can now receive the DHCP renew messages
+	/* Close the BPF filter as we can now receive DHCP messages
 	 * on a UDP socket. */
 	if (state->udp_fd == -1 ||
 	    (state->old != NULL && state->old->yiaddr != state->new->yiaddr))
@@ -2244,9 +2243,15 @@ dhcp_bind(struct interface *ifp)
 		/* If not in master mode, open an address specific socket. */
 		if (ctx->udp_fd == -1) {
 			state->udp_fd = dhcp_openudp(ifp);
-			if (state->udp_fd == -1)
+			if (state->udp_fd == -1) {
 				logerr(__func__);
-			else
+				/* Address sharing without master mode is
+				 * not supported. It's also possible another
+				 * DHCP client could be running which is
+				 * even worse.
+				 * We still need to work, so re-open BPF. */
+				dhcp_openbpf(ifp);
+			} else
 				eloop_event_add(ctx->eloop,
 				    state->udp_fd, dhcp_handleifudp, ifp);
 		}
@@ -2363,7 +2368,10 @@ dhcp_arp_address(struct interface *ifp)
 		return 0;
 	}
 #else
-	if (ifp->options->options & DHCPCD_ARP && ia == NULL) {
+	if (!(ifp->flags & IFF_NOARP) &&
+	    ifp->options->options & DHCPCD_ARP &&
+	    ia == NULL)
+	{
 		struct arp_state *astate;
 		struct dhcp_lease l;
 
@@ -3236,10 +3244,15 @@ valid_udp_packet(void *packet, size_t pl
 	unsigned int flags)
 {
 	struct ip *ip = packet;
-	char ip_hlv = *(char *)ip;
+	struct ip pseudo_ip = {
+		.ip_p = IPPROTO_UDP,
+		.ip_src = ip->ip_src,
+		.ip_dst = ip->ip_dst
+	};
 	size_t ip_hlen;
 	uint16_t ip_len, uh_sum;
 	struct udphdr *udp;
+	uint32_t csum;
 
 	if (plen < sizeof(*ip)) {
 		if (from != NULL)
@@ -3252,13 +3265,13 @@ valid_udp_packet(void *packet, size_t pl
 		from->s_addr = ip->ip_src.s_addr;
 
 	ip_hlen = (size_t)ip->ip_hl * 4;
-	if (checksum(ip, ip_hlen) != 0) {
+	if (in_cksum(ip, ip_hlen, NULL) != 0) {
 		errno = EINVAL;
 		return -1;
 	}
 
-	ip_len = ntohs(ip->ip_len);
 	/* Check we have a payload */
+	ip_len = ntohs(ip->ip_len);
 	if (ip_len <= ip_hlen + sizeof(*udp)) {
 		errno = ERANGE;
 		return -1;
@@ -3272,28 +3285,22 @@ valid_udp_packet(void *packet, size_t pl
 	if (flags & BPF_PARTIALCSUM)
 		return 0;
 
-	udp = (struct udphdr *)((char *)ip + ip_hlen);
+	/* UDP checksum is based on a pseudo IP header alongside
+	 * the UDP header and payload. */
+	udp = (struct udphdr *)(void *)((char *)ip + ip_hlen);
 	if (udp->uh_sum == 0)
 		return 0;
-	uh_sum = udp->uh_sum;
 
-	/* This does scribble on the packet, but at this point
-	 * we don't care to keep it. */
+	uh_sum = udp->uh_sum;
 	udp->uh_sum = 0;
-	ip->ip_hl = 0;
-	ip->ip_v = 0;
-	ip->ip_tos = 0;
-	ip->ip_len = udp->uh_ulen;
-	ip->ip_id = 0;
-	ip->ip_off = 0;
-	ip->ip_ttl = 0;
-	ip->ip_sum = 0;
-	if (checksum(packet, ip_len) != uh_sum) {
+	pseudo_ip.ip_len = udp->uh_ulen;
+	csum = 0;
+	in_cksum(&pseudo_ip, sizeof(pseudo_ip), &csum);
+	csum = in_cksum(udp, ntohs(udp->uh_ulen), &csum);
+	if (csum != uh_sum) {
 		errno = EINVAL;
 		return -1;
 	}
-	*(char *)ip = ip_hlv;
-	ip->ip_len = htons(ip_len);
 
 	return 0;
 }
@@ -3339,12 +3346,6 @@ dhcp_handlepacket(struct interface *ifp,
 			  ifp->name, inet_ntoa(from));
 		return;
 	}
-	if (ifp->flags & IFF_POINTOPOINT &&
-	    (state->addr == NULL || state->addr->brd.s_addr != from.s_addr))
-	{
-		logwarnx("%s: server %s is not destination",
-		    ifp->name, inet_ntoa(from));
-	}
 
 	/*
 	 * DHCP has a variable option area rather than a fixed vendor area.
@@ -3665,6 +3666,7 @@ static void
 dhcp_start1(void *arg)
 {
 	struct interface *ifp = arg;
+	struct dhcpcd_ctx *ctx = ifp->ctx;
 	struct if_options *ifo = ifp->options;
 	struct dhcp_state *state;
 	struct stat st;
@@ -3675,17 +3677,19 @@ dhcp_start1(void *arg)
 		return;
 
 	/* Listen on *.*.*.*:bootpc so that the kernel never sends an
-	 * ICMP port unreachable message back to the DHCP server */
-	if (ifp->ctx->udp_fd == -1) {
-		ifp->ctx->udp_fd = dhcp_openudp(NULL);
-		if (ifp->ctx->udp_fd == -1) {
+	 * ICMP port unreachable message back to the DHCP server.
+	 * Only do this in master mode so we don't swallow messages
+	 * for dhcpcd running on another interface. */
+	if (ctx->udp_fd == -1 && ctx->options & DHCPCD_MASTER) {
+		ctx->udp_fd = dhcp_openudp(NULL);
+		if (ctx->udp_fd == -1) {
 			/* Don't log an error if some other process
 			 * is handling this. */
 			if (errno != EADDRINUSE)
 				logerr("%s: dhcp_openudp", __func__);
 		} else
-			eloop_event_add(ifp->ctx->eloop,
-			    ifp->ctx->udp_fd, dhcp_handleudp, ifp->ctx);
+			eloop_event_add(ctx->eloop,
+			    ctx->udp_fd, dhcp_handleudp, ctx);
 	}
 
 	if (dhcp_init(ifp) == -1) {
@@ -3721,12 +3725,6 @@ dhcp_start1(void *arg)
 		return;
 	}
 
-	if (ifp->hwlen == 0 && ifo->clientid[0] == '\0') {
-		logwarnx("%s: needs a clientid to configure", ifp->name);
-		dhcp_drop(ifp, "FAIL");
-		eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
-		return;
-	}
 	/* We don't want to read the old lease if we NAK an old test */
 	nolease = state->offer && ifp->ctx->options & DHCPCD_TEST;
 	if (!nolease && ifo->options & DHCPCD_DHCP) {
Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.23 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.23.2.1
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.23	Tue Jul 30 10:25:03 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c	Thu Sep  5 08:56:55 2019
@@ -458,11 +458,10 @@ configure_interface1(struct interface *i
 		ifo->options &= ~DHCPCD_ARP;
 		if (!(ifp->flags & IFF_MULTICAST))
 			ifo->options &= ~DHCPCD_IPV6RS;
-		if (!(ifo->options & DHCPCD_INFORM))
+		if (!(ifo->options & (DHCPCD_INFORM | DHCPCD_WANTDHCP)))
 			ifo->options |= DHCPCD_STATIC;
 	}
-	if (ifp->flags & IFF_NOARP ||
-	    !(ifo->options & DHCPCD_ARP) ||
+	if (!(ifo->options & DHCPCD_ARP) ||
 	    ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))
 		ifo->options &= ~DHCPCD_IPV4LL;
 
@@ -951,12 +950,7 @@ dhcpcd_prestartinterface(void *arg)
 
 	if ((!(ifp->ctx->options & DHCPCD_MASTER) ||
 	    ifp->options->options & DHCPCD_IF_UP) &&
-	    if_up(ifp) == -1
-#ifdef __sun
-	    /* Interface could not yet be plumbed. */
-	    && errno != ENXIO
-#endif
-	    )
+	    if_up(ifp) == -1)
 		logerr("%s: %s", __func__, ifp->name);
 
 	dhcpcd_startinterface(ifp);
@@ -1440,10 +1434,10 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx
 	 * write callback on the fd */
 	if (strcmp(*argv, "--version") == 0) {
 		return control_queue(fd, UNCONST(VERSION),
-		    strlen(VERSION) + 1, 0);
+		    strlen(VERSION) + 1, false);
 	} else if (strcmp(*argv, "--getconfigfile") == 0) {
 		return control_queue(fd, UNCONST(fd->ctx->cffile),
-		    strlen(fd->ctx->cffile) + 1, 0);
+		    strlen(fd->ctx->cffile) + 1, false);
 	} else if (strcmp(*argv, "--getinterfaces") == 0) {
 		eloop_event_add_w(fd->ctx->eloop, fd->fd,
 		    dhcpcd_getinterfaces, fd);

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.2 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.2.2.1
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.2	Fri Jul 26 10:39:29 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in	Thu Sep  5 08:56:55 2019
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd July 25, 2019
+.Dd August 28, 2019
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -71,7 +71,7 @@
 .Fl k , Fl Fl release
 .Op interface
 .Nm
-.Fl U, Fl Fl dumplease
+.Fl U , Fl Fl dumplease
 .Ar interface
 .Nm
 .Fl Fl version
@@ -260,7 +260,7 @@ otheriwse if persistent storage is avail
 (link local address + time) is generated,
 otherwise DUID-LL is generated (link local address).
 This, plus the IAID will be used as the
-.Fl I, Fl Fl clientid .
+.Fl I , Fl Fl clientid .
 The DUID generated will be held in
 .Pa @DBDIR@/duid
 and should not be copied to other hosts.
@@ -470,7 +470,7 @@ This option is only needed when
 .Nm
 is not processing IPv6RA messages and the need for DHCPv6 Information Request
 exists.
-.It Fl S, Fl Fl static Ar value
+.It Fl S , Fl Fl static Ar value
 Configures a static DHCP
 .Ar value .
 If you set
@@ -660,7 +660,7 @@ Quiet
 .Nm
 on the command line, only warnings and errors will be displayed.
 The messages are still logged though.
-.It Fl T, Fl Fl test
+.It Fl T , Fl Fl test
 On receipt of DHCP messages just call
 .Pa @SCRIPT@
 with the reason of TEST which echos the DHCP variables found in the message
@@ -673,7 +673,7 @@ option is not sent in TEST mode so that 
 To test INFORM the interface needs to be configured with the desired address
 before starting
 .Nm .
-.It Fl U, Fl Fl dumplease Ar interface
+.It Fl U , Fl Fl dumplease Ar interface
 Dumps the last lease for the
 .Ar interface
 to stdout.
@@ -683,20 +683,20 @@ Use the
 or
 .Fl 6
 flags to specify an address family.
-.It Fl V, Fl Fl variables
+.It Fl V , Fl Fl variables
 Display a list of option codes, the associated variable and encoding for use in
 .Xr dhcpcd-run-hooks 8 .
 Variables are prefixed with new_ and old_ unless the option number is -.
 Variables without an option are part of the DHCP message and cannot be
 directly requested.
-.It Fl W, Fl Fl whitelist Ar address Ns Op /cidr
+.It Fl W , Fl Fl whitelist Ar address Ns Op /cidr
 Only accept packets from
 .Ar address Ns Op /cidr .
-.Fl X, Fl Fl blacklist
+.Fl X , Fl Fl blacklist
 is ignored if
-.Fl W, Fl Fl whitelist
+.Fl W , Fl Fl whitelist
 is set.
-.It Fl X, Fl Fl blacklist Ar address Ns Op Ar /cidr
+.It Fl X , Fl Fl blacklist Ar address Ns Op Ar /cidr
 Ignore all packets from
 .Ar address Ns Op Ar /cidr .
 .It Fl Z , Fl Fl denyinterfaces Ar pattern
@@ -771,6 +771,7 @@ If you always use the same options, put 
 .It Pa @SCRIPT@
 Bourne shell script that is run to configure or de-configure an interface.
 .It Pa @LIBDIR@/dhcpcd/dev
+Linux
 .Pa /dev
 management modules.
 .It Pa @HOOKDIR@
@@ -818,7 +819,7 @@ Control socket to per interface daemon.
 .Xr dhcpcd-run-hooks 8 ,
 .Xr resolvconf 8
 .Sh STANDARDS
-RFC\ 951, RFC\ 1534, RFC\ 2104, RFC\ 2131, RFC\ 2132, RFC\ 2563, RFC\ 2855, 
+RFC\ 951, RFC\ 1534, RFC\ 2104, RFC\ 2131, RFC\ 2132, RFC\ 2563, RFC\ 2855,
 RFC\ 3004, RFC\ 3118, RFC\ 3203, RFC\ 3315, RFC\ 3361, RFC\ 3633, RFC\ 3396,
 RFC\ 3397, RFC\ 3442, RFC\ 3495, RFC\ 3925, RFC\ 3927, RFC\ 4039, RFC\ 4075,
 RFC\ 4242, RFC\ 4361, RFC\ 4390, RFC\ 4702, RFC\ 4074, RFC\ 4861, RFC\ 4833,

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.conf.5.in
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.conf.5.in:1.1.1.13 src/external/bsd/dhcpcd/dist/src/dhcpcd.conf.5.in:1.1.1.13.2.1
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.conf.5.in:1.1.1.13	Wed Jul 24 09:54:52 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.conf.5.in	Thu Sep  5 08:56:55 2019
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 24, 2019
+.Dd August 28, 2019
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -622,7 +622,7 @@ with an infinite lease time.
 If you set
 .Ic ip6_address ,
 .Nm dhcpcd
-will continue auto-configuation as normal.
+will continue auto-configuration as normal.
 .Pp
 Here is an example which configures two static address, overriding the default
 IPv4 broadcast address, an IPv4 router, DNS and disables IPv6 auto-configuration.
@@ -705,9 +705,7 @@ Number
 with the
 .Ar data .
 This option can be set more than once to add more data, but the behaviour,
-as per
-.Xr RFC 3925
-is undefined if the Enterprise Number differs.
+as per RFC 3925 is undefined if the Enterprise Number differs.
 .It Ic waitip Op 4 | 6
 Wait for an address to be assigned before forking to the background.
 4 means wait for an IPv4 address to be assigned.

Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.10 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.10.2.1
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.10	Tue Jul 30 10:25:03 2019
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c	Thu Sep  5 08:56:55 2019
@@ -141,7 +141,7 @@ if_opensockets_os(struct dhcpcd_ctx *ctx
 #ifdef RTM_IFANNOUNCE
 	    RTM_IFANNOUNCE,
 #endif
-	    RTM_ADD, RTM_CHANGE, RTM_DELETE,
+	    RTM_ADD, RTM_CHANGE, RTM_DELETE, RTM_MISS,
 #ifdef RTM_CHGADDR
 	    RTM_CHGADDR,
 #endif
@@ -191,6 +191,8 @@ if_opensockets_os(struct dhcpcd_ctx *ctx
 	if (setsockopt(ctx->link_fd, PF_ROUTE, ROUTE_MSGFILTER,
 	    &msgfilter_mask, sizeof(msgfilter_mask)) == -1)
 		logerr(__func__);
+#else
+#warning kernel does not support route message filtering
 #endif
 
 	return 0;
@@ -637,7 +639,11 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 {
 	const struct sockaddr *rti_info[RTAX_MAX];
 
-	if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) {
+	if (!(rtm->rtm_addrs & RTA_DST)) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (rtm->rtm_type != RTM_MISS && !(rtm->rtm_addrs & RTA_GATEWAY)) {
 		errno = EINVAL;
 		return -1;
 	}
@@ -660,11 +666,8 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 	}
 #endif
 
-	/* We have already checked that at least one address must be
-	 * present after the rtm structure. */
-	/* coverity[ptr_arith] */
-	if (get_addrs(rtm->rtm_addrs, rtm + 1,
-		      rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
+	if (get_addrs(rtm->rtm_addrs, (const char *)rtm + sizeof(*rtm),
+	              rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
 		return -1;
 	memset(rt, 0, sizeof(*rt));
 
@@ -675,12 +678,24 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 		if (rt->rt_netmask.sa_family == 255) /* Why? */
 			rt->rt_netmask.sa_family = rt->rt_dest.sa_family;
 	}
-	/* dhcpcd likes an unspecified gateway to indicate via the link. */
-	if (rt->rt_flags & RTF_GATEWAY &&
-	    rti_info[RTAX_GATEWAY]->sa_family != AF_LINK)
-		if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
+
+	/* dhcpcd likes an unspecified gateway to indicate via the link.
+	 * However we need to know if gateway was a link with an address. */
+	if (rtm->rtm_addrs & RTA_GATEWAY) {
+		if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) {
+			const struct sockaddr_dl *sdl;
+
+			sdl = (const struct sockaddr_dl*)
+			    (const void *)rti_info[RTAX_GATEWAY];
+			if (sdl->sdl_alen != 0)
+				rt->rt_dflags |= RTDF_GATELINK;
+		} else if (rtm->rtm_flags & RTF_GATEWAY)
+			if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
+	}
+
 	if (rtm->rtm_addrs & RTA_IFA)
 		if_copysa(&rt->rt_ifa, rti_info[RTAX_IFA]);
+
 	rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
 
 	if (rtm->rtm_index)
@@ -692,6 +707,9 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 	else
 		rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_DST]);
 
+	if (rt->rt_ifp == NULL && rtm->rtm_type == RTM_MISS)
+		rt->rt_ifp = if_find(ctx->ifaces, "lo0");
+
 	if (rt->rt_ifp == NULL) {
 		errno = ESRCH;
 		return -1;
@@ -1071,30 +1089,30 @@ if_rtm(struct dhcpcd_ctx *ctx, const str
 		return 0;
 
 	if (if_copyrt(ctx, &rt, rtm) == -1)
-		return -1;
+		return errno == ENOTSUP ? 0 : -1;
 
 #ifdef INET6
 	/*
 	 * BSD announces host routes.
 	 * As such, we should be notified of reachability by its
 	 * existance with a hardware address.
+	 * Ensure we don't call this for a newly incomplete state.
 	 */
-	if (rt.rt_dest.sa_family == AF_INET6 && rt.rt_flags & RTF_HOST) {
-		struct sockaddr_in6 dest;
-		struct sockaddr_dl sdl;
+	if (rt.rt_dest.sa_family == AF_INET6 &&
+	    (rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) &&
+	    !(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK)))
+	{
+		bool reachable;
 
-		memcpy(&dest, &rt.rt_dest, rt.rt_dest.sa_len);
-		if (rt.rt_gateway.sa_family == AF_LINK)
-			memcpy(&sdl, &rt.rt_gateway, rt.rt_gateway.sa_len);
-		else
-			sdl.sdl_alen = 0;
-		ipv6nd_neighbour(ctx, &dest.sin6_addr,
-		    rtm->rtm_type != RTM_DELETE && sdl.sdl_alen ?
-		    IPV6ND_REACHABLE : 0);
+		reachable = (rtm->rtm_type == RTM_ADD ||
+		    rtm->rtm_type == RTM_CHANGE) &&
+		    rt.rt_dflags & RTDF_GATELINK;
+		ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable);
 	}
 #endif
 
-	rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
+	if (rtm->rtm_type != RTM_MISS)
+		rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
 	return 0;
 }
 
@@ -1115,10 +1133,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 	if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL)
 		return 0;
 
-	/* We have already checked that at least one address must be
-	 * present after the ifam structure. */
-	/* coverity[ptr_arith] */
-	if (get_addrs(ifam->ifam_addrs, ifam + 1,
+	if (get_addrs(ifam->ifam_addrs, (const char *)ifam + sizeof(*ifam),
 		      ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1)
 		return -1;
 
@@ -1303,7 +1318,8 @@ if_dispatch(struct dhcpcd_ctx *ctx, cons
 		return if_ifinfo(ctx, (const void *)rtm);
 	case RTM_ADD:		/* FALLTHROUGH */
 	case RTM_CHANGE:	/* FALLTHROUGH */
-	case RTM_DELETE:
+	case RTM_DELETE:	/* FALLTHROUGH */
+	case RTM_MISS:
 		return if_rtm(ctx, (const void *)rtm);
 #ifdef RTM_CHGADDR
 	case RTM_CHGADDR:	/* FALLTHROUGH */
@@ -1314,32 +1330,41 @@ if_dispatch(struct dhcpcd_ctx *ctx, cons
 #ifdef RTM_DESYNC
 	case RTM_DESYNC:
 		dhcpcd_linkoverflow(ctx);
+#elif !defined(SO_RERROR)
+#warning cannot detect route socket overflow within kernel
 #endif
 	}
 
 	return 0;
 }
 
+__CTASSERT(offsetof(struct rt_msghdr, rtm_msglen) == 0);
 int
 if_handlelink(struct dhcpcd_ctx *ctx)
 {
 	struct rtm rtm;
-	struct iovec iov = { .iov_base = &rtm, .iov_len = sizeof(rtm) };
-	struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
 	ssize_t len;
 
-	len = recvmsg(ctx->link_fd, &msg, 0);
+	len = read(ctx->link_fd, &rtm, sizeof(rtm));
 	if (len == -1)
 		return -1;
 	if (len == 0)
 		return 0;
-	if (len < rtm.hdr.rtm_msglen) {
+	if ((size_t)len < sizeof(rtm.hdr.rtm_msglen) ||
+	    len != rtm.hdr.rtm_msglen)
+	{
 		errno = EINVAL;
 		return -1;
 	}
-	/* We generally treat rtm.hdr has an array so we can easily
-	 * access the following data. */
-	/* coverity[callee_ptr_arith] */
+	/*
+	 * Coverity thinks that the data could be tainted from here.
+	 * I have no idea how because the length of the data we read
+	 * is guarded by len and checked to match rtm_msglen.
+	 * The issue seems to be related to extracting the addresses
+	 * at the end of the header, but seems to have no issues with the
+	 * equivalent call in if_initrt.
+	 */
+	/* coverity[tainted_data] */
 	return if_dispatch(ctx, &rtm.hdr);
 }
 
Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.10 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.10.2.1
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.10	Tue Jul 30 10:25:03 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c	Thu Sep  5 08:56:55 2019
@@ -217,7 +217,6 @@ ipv6nd_open0(void)
 		goto eexit;
 
 	ICMP6_FILTER_SETBLOCKALL(&filt);
-	ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt);
 	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
 	if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
 	    &filt, sizeof(filt)) == -1)
@@ -460,6 +459,11 @@ ipv6nd_advertise(struct ipv6_addr *ia)
 	if (IN6_IS_ADDR_MULTICAST(&ia->addr))
 		return;
 
+#ifdef __sun
+	if (!(ia->flags & IPV6_AF_AUTOCONF) && ia->flags & IPV6_AF_RAPFX)
+		return;
+#endif
+
 	ctx = ia->iface->ctx;
 	/* Find the most preferred address to advertise. */
 	iaf = NULL;
@@ -555,45 +559,60 @@ ipv6nd_startexpire(struct interface *ifp
 	    ipv6nd_expire, ifp);
 }
 
-static void
-ipv6nd_reachable(struct ra *rap, int flags)
+/*
+ * Neighbour reachability.
+ *
+ * RFC 4681 6.2.5 says when a node is no longer a router it MUST
+ * send a RA with a zero lifetime.
+ * All OS's I know of set the NA router flag if they are a router
+ * or not and disregard that they are actively advertising or
+ * shutting down. If the interface is disabled, it cant't send a NA at all.
+ *
+ * As such we CANNOT rely on the NA Router flag and MUST use
+ * unreachability or receive a RA with a lifetime of zero to remove
+ * the node as a default router.
+ */
+void
+ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, bool reachable)
 {
+	struct ra *rap, *rapr;
+
+	if (ctx->ra_routers == NULL)
+		return;
+
+	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
+		if (IN6_ARE_ADDR_EQUAL(&rap->from, addr))
+			break;
+	}
 
-	if (rap->lifetime == 0)
+	if (rap == NULL || rap->expired)
 		return;
 
-	if (flags & IPV6ND_REACHABLE) {
-		if (rap->expired == 0)
+	if (reachable) {
+		if (rap->isreachable)
 			return;
 		loginfox("%s: %s is reachable again",
 		    rap->iface->name, rap->sfrom);
-		rap->expired = 0;
+		rap->isreachable = true;
+		return;
 	} else {
-		if (rap->expired != 0)
+		if (!rap->isreachable)
 			return;
-		logwarnx("%s: %s is unreachable, expiring it",
+		logwarnx("%s: %s is unreachable",
 		    rap->iface->name, rap->sfrom);
-		rap->expired = 1;
+		rap->isreachable = false;
 	}
 
-	rt_build(rap->iface->ctx, AF_INET6);
-	/* XXX Not really an RA */
-	script_runreason(rap->iface, "ROUTERADVERT");
-}
-
-void
-ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, int flags)
-{
-	struct ra *rap;
-
-	if (ctx->ra_routers) {
-	        TAILQ_FOREACH(rap, ctx->ra_routers, next) {
-			if (IN6_ARE_ADDR_EQUAL(&rap->from, addr)) {
-				ipv6nd_reachable(rap, flags);
-				break;
-			}
-		}
+	/* If we have no reachable default routers, try and solicit one. */
+	TAILQ_FOREACH(rapr, ctx->ra_routers, next) {
+		if (rap == rapr || rap->iface != rapr->iface)
+			continue;
+		if (rapr->isreachable && !rapr->expired && rapr->lifetime)
+			break;
 	}
+
+	if (rapr == NULL)
+		ipv6nd_startrs(rap->iface);
 }
 
 const struct ipv6_addr *
@@ -944,7 +963,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 	struct in6_addr pi_prefix;
 	struct ipv6_addr *ap;
 	struct dhcp_opt *dho;
-	bool new_rap, new_data;
+	bool new_rap, new_data, has_address;
 	uint32_t old_lifetime;
 	__printflike(1, 2) void (*logfunc)(const char *, ...);
 #ifdef IPV6_MANAGETEMPADDR
@@ -1026,6 +1045,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 		strlcpy(rap->sfrom, sfrom, sizeof(rap->sfrom));
 		TAILQ_INIT(&rap->addrs);
 		new_rap = true;
+		rap->isreachable = true;
 	} else
 		new_rap = false;
 	if (rap->data_len == 0) {
@@ -1044,7 +1064,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 	 * routers like to decrease the advertised valid and preferred times
 	 * in accordance with the own prefix times which would result in too
 	 * much needless log spam. */
-	logfunc = new_rap ? loginfox : logdebugx,
+	logfunc = new_data || !rap->isreachable ? loginfox : logdebugx,
 	logfunc("%s: Router Advertisement from %s", ifp->name, rap->sfrom);
 
 	clock_gettime(CLOCK_MONOTONIC, &rap->acquired);
@@ -1064,9 +1084,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 
 		state->retrans = rap->retrans = ntohl(nd_ra->nd_ra_retransmit);
 	}
-	if (rap->lifetime)
-		rap->expired = 0;
-	rap->hasdns = 0;
+	rap->expired = false;
+	rap->hasdns = false;
+	rap->isreachable = true;
+	has_address = false;
 
 #ifdef IPV6_AF_TEMPORARY
 	ipv6_markaddrsstale(ifp, IPV6_AF_TEMPORARY);
@@ -1200,6 +1221,9 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 			    ntohl(pi.nd_opt_pi_valid_time);
 			ap->prefix_pltime =
 			    ntohl(pi.nd_opt_pi_preferred_time);
+			if (ap->prefix_vltime != 0 &&
+			    ap->flags & IPV6_AF_AUTOCONF)
+				has_address = true;
 
 #ifdef IPV6_MANAGETEMPADDR
 			/* RFC4941 Section 3.3.3 */
@@ -1266,6 +1290,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
 		}
 	}
 
+	if (new_data && !has_address && rap->lifetime && !ipv6_ifanyglobal(ifp))
+		logwarnx("%s: no global addresses for default route",
+		    ifp->name);
+
 	if (new_rap)
 		add_router(ifp->ctx, rap);
 
@@ -1316,20 +1344,21 @@ nodhcp6:
 	ipv6nd_expirera(ifp);
 }
 
-int
-ipv6nd_hasra(const struct interface *ifp)
+bool
+ipv6nd_hasralifetime(const struct interface *ifp, bool lifetime)
 {
 	const struct ra *rap;
 
 	if (ifp->ctx->ra_routers) {
 		TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next)
-			if (rap->iface == ifp && !rap->expired)
-				return 1;
+			if (rap->iface == ifp && !rap->expired &&
+			    (!lifetime ||rap->lifetime))
+				return true;
 	}
-	return 0;
+	return false;
 }
 
-int
+bool
 ipv6nd_hasradhcp(const struct interface *ifp)
 {
 	const struct ra *rap;
@@ -1338,11 +1367,11 @@ ipv6nd_hasradhcp(const struct interface 
 		TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
 			if (rap->iface == ifp &&
 			    !rap->expired &&
-			    (rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)))
-				return 1;
+			    (rap->flags &(ND_RA_FLAG_MANAGED|ND_RA_FLAG_OTHER)))
+				return true;
 		}
 	}
-	return 0;
+	return false;
 }
 
 static const uint8_t *
@@ -1399,7 +1428,7 @@ ipv6nd_env(FILE *fp, const struct interf
 	clock_gettime(CLOCK_MONOTONIC, &now);
 	i = n = 0;
 	TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
-		if (rap->iface != ifp)
+		if (rap->iface != ifp || rap->expired)
 			continue;
 		i++;
 		snprintf(ndprefix, sizeof(ndprefix), "nd%zu", i);
@@ -1503,7 +1532,7 @@ ipv6nd_expirera(void *arg)
 	struct interface *ifp;
 	struct ra *rap, *ran;
 	struct timespec now, lt, expire, next;
-	bool expired, valid, validone;
+	bool expired, valid;
 	struct ipv6_addr *ia;
 	size_t len, olen;
 	uint8_t *p;
@@ -1522,9 +1551,9 @@ ipv6nd_expirera(void *arg)
 	timespecclear(&next);
 
 	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
-		if (rap->iface != ifp)
+		if (rap->iface != ifp || rap->expired)
 			continue;
-		valid = validone = false;
+		valid = false;
 		if (rap->lifetime) {
 			lt.tv_sec = (time_t)rap->lifetime;
 			lt.tv_nsec = 0;
@@ -1533,8 +1562,8 @@ ipv6nd_expirera(void *arg)
 				if (!rap->expired) {
 					logwarnx("%s: %s: router expired",
 					    ifp->name, rap->sfrom);
-					rap->expired = expired = 1;
 					rap->lifetime = 0;
+					expired = true;
 				}
 			} else {
 				valid = true;
@@ -1552,7 +1581,7 @@ ipv6nd_expirera(void *arg)
 			if (ia->prefix_vltime == 0)
 				continue;
 			if (ia->prefix_vltime == ND6_INFINITE_LIFETIME) {
-				validone = true;
+				valid = true;
 				continue;
 			}
 			lt.tv_sec = (time_t)ia->prefix_vltime;
@@ -1576,7 +1605,7 @@ ipv6nd_expirera(void *arg)
 				if (!timespecisset(&next) ||
 				    timespeccmp(&next, &lt, >))
 					next = lt;
-				validone = true;
+				valid = true;
 			}
 		}
 
@@ -1626,7 +1655,7 @@ ipv6nd_expirera(void *arg)
 			if (ltime == 0)
 				continue;
 			if (ltime == ND6_INFINITE_LIFETIME) {
-				validone = true;
+				valid = true;
 				continue;
 			}
 
@@ -1643,15 +1672,15 @@ ipv6nd_expirera(void *arg)
 			    timespeccmp(&next, &lt, >))
 			{
 				next = lt;
-				validone = true;
+				valid = true;
 			}
 		}
 
-		if (valid || validone)
+		if (valid)
 			continue;
 
-		/* Router has expired. Let's not keep a lot of them.
-		 * We should work out if all the options have expired .... */
+		/* Router has expired. Let's not keep a lot of them. */
+		rap->expired = true;
 		if (++nexpired > EXPIRED_MAX)
 			ipv6nd_free_ra(rap);
 	}
@@ -1670,7 +1699,7 @@ void
 ipv6nd_drop(struct interface *ifp)
 {
 	struct ra *rap, *ran;
-	uint8_t expired = 0;
+	bool expired = false;
 
 	if (ifp->ctx->ra_routers == NULL)
 		return;
@@ -1678,7 +1707,7 @@ ipv6nd_drop(struct interface *ifp)
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
 		if (rap->iface == ifp) {
-			rap->expired = expired = 1;
+			rap->expired = expired = true;
 			ipv6nd_drop_ra(rap);
 		}
 	}
@@ -1690,82 +1719,6 @@ ipv6nd_drop(struct interface *ifp)
 }
 
 static void
-ipv6nd_handlena(struct dhcpcd_ctx *ctx, const char *sfrom,
-    struct interface *ifp, struct icmp6_hdr *icp, size_t len, int hoplimit)
-{
-	struct nd_neighbor_advert *nd_na;
-	struct in6_addr nd_na_target;
-	struct ra *rap;
-	uint32_t is_router, is_solicited;
-	char buf[INET6_ADDRSTRLEN];
-	const char *taddr;
-
-	if (ifp == NULL) {
-#ifdef DEBUG_NS
-		logdebugx("NA for unexpected interface from %s", sfrom);
-#endif
-		return;
-	}
-
-	if ((size_t)len < sizeof(struct nd_neighbor_advert)) {
-		logerrx("%s: IPv6 NA too short from %s", ifp->name, sfrom);
-		return;
-	}
-
-	/* RFC 4861 7.1.2 */
-	if (hoplimit != 255) {
-		logerrx("invalid hoplimit(%d) in NA from %s",
-		    hoplimit, sfrom);
-		return;
-	}
-
-	nd_na = (struct nd_neighbor_advert *)icp;
-	is_router = nd_na->nd_na_flags_reserved & ND_NA_FLAG_ROUTER;
-	is_solicited = nd_na->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED;
-	taddr = inet_ntop(AF_INET6, &nd_na->nd_na_target,
-	    buf, INET6_ADDRSTRLEN);
-
-	/* nd_na->nd_na_target is not aligned. */
-	memcpy(&nd_na_target, &nd_na->nd_na_target, sizeof(nd_na_target));
-	if (IN6_IS_ADDR_MULTICAST(&nd_na_target)) {
-		logerrx("%s: NA multicast address %s (%s)",
-		    ifp->name, taddr, sfrom);
-		return;
-	}
-
-	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
-		if (rap->iface == ifp &&
-		    IN6_ARE_ADDR_EQUAL(&rap->from, &nd_na_target))
-			break;
-	}
-	if (rap == NULL) {
-#ifdef DEBUG_NS
-		logdebugx("%s: unexpected NA from %s for %s",
-		    ifp->name, sfrom, taddr);
-#endif
-		return;
-	}
-
-#ifdef DEBUG_NS
-	logdebugx("%s: %sNA for %s from %s",
-	    ifp->name, is_solicited ? "solicited " : "", taddr, sfrom);
-#endif
-
-	/* Node is no longer a router, so remove it from consideration */
-	if (!is_router && !rap->expired) {
-		loginfox("%s: %s not a router (%s)",
-		    ifp->name, taddr, sfrom);
-		rap->expired = 1;
-		rt_build(ifp->ctx,  AF_INET6);
-		script_runreason(ifp, "ROUTERADVERT");
-		return;
-	}
-
-	if (is_solicited && is_router && rap->lifetime)
-		ipv6nd_reachable(rap, IPV6ND_REACHABLE);
-}
-
-static void
 ipv6nd_handledata(void *arg)
 {
 	struct dhcpcd_ctx *ctx;
@@ -1828,10 +1781,6 @@ ipv6nd_handledata(void *arg)
 	icp = (struct icmp6_hdr *)buf;
 	if (icp->icmp6_code == 0) {
 		switch(icp->icmp6_type) {
-			case ND_NEIGHBOR_ADVERT:
-				ipv6nd_handlena(ctx, sfrom,
-				    ifp, icp, (size_t)len, hoplimit);
-				return;
 			case ND_ROUTER_ADVERT:
 				ipv6nd_handlera(ctx, &from, sfrom,
 				    ifp, icp, (size_t)len, hoplimit);

Index: src/external/bsd/dhcpcd/dist/src/if-linux.c
diff -u src/external/bsd/dhcpcd/dist/src/if-linux.c:1.1.1.14 src/external/bsd/dhcpcd/dist/src/if-linux.c:1.1.1.14.2.1
--- src/external/bsd/dhcpcd/dist/src/if-linux.c:1.1.1.14	Wed Jul 24 09:54:53 2019
+++ src/external/bsd/dhcpcd/dist/src/if-linux.c	Thu Sep  5 08:56:55 2019
@@ -680,8 +680,6 @@ link_neigh(struct dhcpcd_ctx *ctx, __unu
 	struct ndmsg *r;
 	struct rtattr *rta;
 	size_t len;
-	struct in6_addr addr6;
-	int flags;
 
 	if (nlm->nlmsg_type != RTM_NEWNEIGH && nlm->nlmsg_type != RTM_DELNEIGH)
 		return 0;
@@ -692,14 +690,13 @@ link_neigh(struct dhcpcd_ctx *ctx, __unu
 	rta = (struct rtattr *)RTM_RTA(r);
 	len = RTM_PAYLOAD(nlm);
         if (r->ndm_family == AF_INET6) {
-		flags = 0;
-		if (r->ndm_flags & NTF_ROUTER)
-			flags |= IPV6ND_ROUTER;
-		if (nlm->nlmsg_type == RTM_NEWNEIGH &&
+		bool reachable;
+		struct in6_addr addr6;
+
+		reachable = (nlm->nlmsg_type == RTM_NEWNEIGH &&
 		    r->ndm_state &
 		    (NUD_REACHABLE | NUD_STALE | NUD_DELAY | NUD_PROBE |
-		     NUD_PERMANENT))
-		        flags |= IPV6ND_REACHABLE;
+		     NUD_PERMANENT));
 		memset(&addr6, 0, sizeof(addr6));
 		while (RTA_OK(rta, len)) {
 			switch (rta->rta_type) {
@@ -710,7 +707,7 @@ link_neigh(struct dhcpcd_ctx *ctx, __unu
 			}
 			rta = RTA_NEXT(rta, len);
 		}
-		ipv6nd_neighbour(ctx, &addr6, flags);
+		ipv6nd_neighbour(ctx, &addr6, reachable);
 	}
 
 	return 0;
@@ -1465,12 +1462,12 @@ bpf_read(struct interface *ifp, int s, v
 int
 bpf_attach(int s, void *filter, unsigned int filter_len)
 {
-	struct sock_fprog pf;
+	struct sock_fprog pf = {
+		.filter = filter,
+		.len = (unsigned short)filter_len,
+	};
 
 	/* Install the filter. */
-	memset(&pf, 0, sizeof(pf));
-	pf.filter = filter;
-	pf.len = (unsigned short)filter_len;
 	return setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf));
 }
 
@@ -1480,7 +1477,9 @@ if_address(unsigned char cmd, const stru
 	struct nlma nlm;
 	struct ifa_cacheinfo cinfo;
 	int retval = 0;
+#ifdef IFA_F_NOPREFIXROUTE
 	uint32_t flags = 0;
+#endif
 
 	memset(&nlm, 0, sizeof(nlm));
 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
@@ -1507,8 +1506,8 @@ if_address(unsigned char cmd, const stru
 #ifdef IFA_F_NOPREFIXROUTE
 		if (nlm.ifa.ifa_prefixlen < 32)
 			flags |= IFA_F_NOPREFIXROUTE;
-#endif
 		add_attr_32(&nlm.hdr, sizeof(nlm), IFA_FLAGS, flags);
+#endif
 
 		add_attr_l(&nlm.hdr, sizeof(nlm), IFA_BROADCAST,
 		    &ia->brd.s_addr, sizeof(ia->brd.s_addr));
@@ -1542,7 +1541,9 @@ if_address6(unsigned char cmd, const str
 {
 	struct nlma nlm;
 	struct ifa_cacheinfo cinfo;
+#if defined(IFA_F_MANAGETEMPADDR) || defined(IFA_F_NOPREFIXROUTE)
 	uint32_t flags = 0;
+#endif
 
 	memset(&nlm, 0, sizeof(nlm));
 	nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
@@ -1582,7 +1583,9 @@ if_address6(unsigned char cmd, const str
 		if (!IN6_IS_ADDR_LINKLOCAL(&ia->addr))
 			flags |= IFA_F_NOPREFIXROUTE;
 #endif
+#if defined(IFA_F_MANAGETEMPADDR) || defined(IFA_F_NOPREFIXROUTE)
 		add_attr_32(&nlm.hdr, sizeof(nlm), IFA_FLAGS, flags);
+#endif
 
 		memset(&cinfo, 0, sizeof(cinfo));
 		cinfo.ifa_prefered = ia->prefix_pltime;
Index: src/external/bsd/dhcpcd/dist/src/if.c
diff -u src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.14 src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.14.2.1
--- src/external/bsd/dhcpcd/dist/src/if.c:1.1.1.14	Wed Jul 24 09:54:53 2019
+++ src/external/bsd/dhcpcd/dist/src/if.c	Thu Sep  5 08:56:55 2019
@@ -72,6 +72,12 @@
 #include "ipv6nd.h"
 #include "logerr.h"
 
+#ifdef __sun
+/* It has the ioctl, but the member is missing from the struct?
+ * No matter, our getifaddrs foo in if-sun.c will DTRT. */
+#undef SIOCGIFHWADDR
+#endif
+
 void
 if_free(struct interface *ifp)
 {
@@ -235,6 +241,7 @@ if_learnaddrs(struct dhcpcd_ctx *ctx, st
 		case AF_INET6:
 			sin6 = (void *)ifa->ifa_addr;
 			net6 = (void *)ifa->ifa_netmask;
+
 #ifdef __KAME__
 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
 				/* Remove the scope from the address */
@@ -307,17 +314,16 @@ if_discover(struct dhcpcd_ctx *ctx, stru
 	struct if_spec spec;
 #ifdef AF_LINK
 	const struct sockaddr_dl *sdl;
-#ifdef SIOCGIFPRIORITY
-	struct ifreq ifr;
-#endif
 #ifdef IFLR_ACTIVE
 	struct if_laddrreq iflr = { .flags = IFLR_PREFIX };
 	int link_fd;
 #endif
-
 #elif AF_PACKET
 	const struct sockaddr_ll *sll;
 #endif
+#if defined(SIOCGIFPRIORITY) || defined(SIOCGIFHWADDR)
+	struct ifreq ifr;
+#endif
 
 	if ((ifs = malloc(sizeof(*ifs))) == NULL) {
 		logerr(__func__);
@@ -512,10 +518,21 @@ if_discover(struct dhcpcd_ctx *ctx, stru
 				memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen);
 #endif
 		}
-#ifdef __linux__
-		/* PPP addresses on Linux don't have hardware addresses */
-		else
-			ifp->index = if_nametoindex(ifp->name);
+#ifdef SIOCGIFHWADDR
+		else {
+			/* This is a huge bug in getifaddrs(3) as there
+			 * is no reason why this can't be returned in
+			 * ifa_addr. */
+			memset(&ifr, 0, sizeof(ifr));
+			strlcpy(ifr.ifr_name, ifa->ifa_name,
+			    sizeof(ifr.ifr_name));
+			if (ioctl(ctx->pf_inet_fd, SIOCGIFHWADDR, &ifr) == -1)
+				logerr("%s: SIOCGIFHWADDR", ifa->ifa_name);
+			ifp->family = ifr.ifr_hwaddr.sa_family;
+			if (ioctl(ctx->pf_inet_fd, SIOCGIFINDEX, &ifr) == -1)
+				logerr("%s: SIOCGIFINDEX", ifa->ifa_name);
+			ifp->index = (unsigned int)ifr.ifr_ifindex;
+		}
 #endif
 
 		/* Ensure hardware address is valid. */
@@ -536,6 +553,9 @@ if_discover(struct dhcpcd_ctx *ctx, stru
 #ifdef ARPHRD_PPP
 			case ARPHRD_PPP:
 #endif
+#ifdef ARPHRD_NONE
+			case ARPHRD_NONE:
+#endif
 				/* We don't warn for supported families */
 				break;
 

Index: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.16 src/external/bsd/dhcpcd/dist/src/if-options.c:1.16.2.1
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.16	Tue Jul 30 10:25:03 2019
+++ src/external/bsd/dhcpcd/dist/src/if-options.c	Thu Sep  5 08:56:55 2019
@@ -2062,7 +2062,7 @@ err_sla:
 		ifo->auth.options &= ~DHCPCD_AUTH_REQUIRE;
 		break;
 	case O_DHCP:
-		ifo->options |= DHCPCD_DHCP | DHCPCD_IPV4;
+		ifo->options |= DHCPCD_DHCP | DHCPCD_WANTDHCP | DHCPCD_IPV4;
 		break;
 	case O_NODHCP:
 		ifo->options &= ~DHCPCD_DHCP;
@@ -2281,7 +2281,7 @@ default_config(struct dhcpcd_ctx *ctx)
 	ifo->script = UNCONST(default_script);
 	ifo->metric = -1;
 	ifo->auth.options |= DHCPCD_AUTH_REQUIRE;
-	rb_tree_init(&ifo->routes, &rt_compare_proto_ops);
+	rb_tree_init(&ifo->routes, &rt_compare_list_ops);
 #ifdef AUTH
 	TAILQ_INIT(&ifo->auth.tokens);
 #endif

Index: src/external/bsd/dhcpcd/dist/src/if-options.h
diff -u src/external/bsd/dhcpcd/dist/src/if-options.h:1.1.1.9 src/external/bsd/dhcpcd/dist/src/if-options.h:1.1.1.9.2.1
--- src/external/bsd/dhcpcd/dist/src/if-options.h:1.1.1.9	Wed Jul 24 09:54:53 2019
+++ src/external/bsd/dhcpcd/dist/src/if-options.h	Thu Sep  5 08:56:55 2019
@@ -61,7 +61,7 @@
 
 #define DHCPCD_ARP			(1ULL << 0)
 #define DHCPCD_RELEASE			(1ULL << 1)
-// unused				(1ULL << 2)
+#define DHCPCD_RTBUILD			(1ULL << 2)
 #define DHCPCD_GATEWAY			(1ULL << 3)
 #define DHCPCD_STATIC			(1ULL << 4)
 #define DHCPCD_DEBUG			(1ULL << 5)
@@ -110,7 +110,7 @@
 #define DHCPCD_DHCP6			(1ULL << 50)
 #define DHCPCD_IF_UP			(1ULL << 51)
 #define DHCPCD_INFORM6			(1ULL << 52)
-// unused				(1ULL << 53)
+#define DHCPCD_WANTDHCP			(1ULL << 53)
 #define DHCPCD_IPV6RA_AUTOCONF		(1ULL << 54)
 #define DHCPCD_ROUTER_HOST_ROUTE_WARNED	(1ULL << 55)
 #define DHCPCD_LASTLEASE_EXTEND		(1ULL << 56)
Index: src/external/bsd/dhcpcd/dist/src/ipv4.h
diff -u src/external/bsd/dhcpcd/dist/src/ipv4.h:1.1.1.9 src/external/bsd/dhcpcd/dist/src/ipv4.h:1.1.1.9.2.1
--- src/external/bsd/dhcpcd/dist/src/ipv4.h:1.1.1.9	Tue Jul 30 10:23:09 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv4.h	Thu Sep  5 08:56:55 2019
@@ -63,8 +63,9 @@
     * While it supports DaD, to seems to only expose IFF_DUPLICATE
     * so we have no way of knowing if it's tentative or not.
     * I don't even know if Solaris has any special treatment for tentative. */
+#  define IN_IFF_TENTATIVE	0x01
 #  define IN_IFF_DUPLICATED	0x02
-#  define IN_IFF_NOTUSEABLE	IN_IFF_DUPLICATED
+#  define IN_IFF_DETACHED	0x00
 #endif
 
 #ifdef IN_IFF_TENTATIVE

Index: src/external/bsd/dhcpcd/dist/src/if-sun.c
diff -u src/external/bsd/dhcpcd/dist/src/if-sun.c:1.1.1.10 src/external/bsd/dhcpcd/dist/src/if-sun.c:1.1.1.10.2.1
--- src/external/bsd/dhcpcd/dist/src/if-sun.c:1.1.1.10	Wed Jul 24 09:54:53 2019
+++ src/external/bsd/dhcpcd/dist/src/if-sun.c	Thu Sep  5 08:56:55 2019
@@ -106,10 +106,27 @@ struct rtm
 	char buffer[sizeof(struct sockaddr_storage) * RTAX_MAX];
 };
 
+static int if_plumb(int, const struct dhcpcd_ctx *, int, const char *);
+
 int
-if_init(__unused struct interface *ifp)
+if_init(struct interface *ifp)
 {
 
+#ifdef INET
+	if (if_plumb(RTM_NEWADDR, ifp->ctx, AF_INET, ifp->name) == -1 &&
+	    errno != EEXIST)
+		return -1;
+#endif
+
+#ifdef INET6
+	if (if_plumb(RTM_NEWADDR, ifp->ctx, AF_INET6, ifp->name) == -1 &&
+	    errno != EEXIST)
+		return -1;
+#endif
+
+	if (ifp->index == 0)
+		ifp->index = if_nametoindex(ifp->name);
+
 	return 0;
 }
 
@@ -622,13 +639,12 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 {
 	const struct sockaddr *rti_info[RTAX_MAX];
 
-	if (~rtm->rtm_addrs & RTA_DST)
+	if (~rtm->rtm_addrs & RTA_DST) {
+		errno = EINVAL;
 		return -1;
+	}
 
-	/* We have already checked that at least one address must be
-	 * present after the rtm structure. */
-	/* coverity[ptr_arith] */
-	if (get_addrs(rtm->rtm_addrs, rtm + 1,
+	if (get_addrs(rtm->rtm_addrs, (const char *)rtm + sizeof(*rtm),
 		      rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
 		return -1;
 
@@ -638,10 +654,21 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 	COPYSA(&rt->rt_dest, rti_info[RTAX_DST]);
 	if (rtm->rtm_addrs & RTA_NETMASK)
 		COPYSA(&rt->rt_netmask, rti_info[RTAX_NETMASK]);
-	/* dhcpcd likes an unspecified gateway to indicate via the link. */
-	if (rtm->rtm_addrs & RTA_GATEWAY &&
-	    rti_info[RTAX_GATEWAY]->sa_family != AF_LINK)
-		COPYSA(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
+
+	/* dhcpcd likes an unspecified gateway to indicate via the link.
+	 * However we need to know if gateway was a link with an address. */
+	if (rtm->rtm_addrs & RTA_GATEWAY) {
+		if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) {
+			const struct sockaddr_dl *sdl;
+
+			sdl = (const struct sockaddr_dl*)
+			    (const void *)rti_info[RTAX_GATEWAY];
+			if (sdl->sdl_alen != 0)
+				rt->rt_dflags |= RTDF_GATELINK;
+		} else if (rtm->rtm_flags & RTF_GATEWAY)
+			COPYSA(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
+	}
+
 	if (rtm->rtm_addrs & RTA_SRC)
 		COPYSA(&rt->rt_ifa, rti_info[RTAX_SRC]);
 	rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
@@ -655,6 +682,9 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
 	else
 		rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_DST]);
 
+	if (rt->rt_ifp == NULL && rtm->rtm_type == RTM_MISS)
+		rt->rt_ifp = if_loopback(ctx);
+
 	if (rt->rt_ifp == NULL) {
 		errno = ESRCH;
 		return -1;
@@ -757,21 +787,23 @@ if_finishrt(struct dhcpcd_ctx *ctx, stru
 	return 0;
 }
 
-static uint64_t
-if_addrflags0(int fd, const char *ifname, const struct sockaddr *sa)
+static int
+if_addrflags0(int fd, int af, const char *ifname)
 {
 	struct lifreq		lifr;
+	int flags;
 
 	memset(&lifr, 0, sizeof(lifr));
 	strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
 	if (ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1)
-		return 0;
-	if (ioctl(fd, SIOCGLIFADDR, &lifr) == -1)
-		return 0;
-	if (sa_cmp(sa, (struct sockaddr *)&lifr.lifr_addr) != 0)
-		return 0;
+		return -1;
 
-	return lifr.lifr_flags;
+	flags = 0;
+	if (lifr.lifr_flags & IFF_DUPLICATE)
+		flags |= af == AF_INET6 ? IN6_IFF_DUPLICATED:IN_IFF_DUPLICATED;
+	else if (!(lifr.lifr_flags & IFF_UP))
+		flags |= af == AF_INET6 ? IN6_IFF_TENTATIVE:IN_IFF_TENTATIVE;
+	return flags;
 }
 
 static int
@@ -785,42 +817,29 @@ if_rtm(struct dhcpcd_ctx *ctx, const str
 		return -1;
 	}
 
-	sa = (const void *)(rtm + 1);
-	switch (sa->sa_family) {
+	if (if_copyrt(ctx, &rt, rtm) == -1 && errno != ESRCH)
+		return -1;
+
 #ifdef INET6
-	case AF_INET6:
-		if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY))
-			break;
-		/*
-		 * BSD announces host routes.
-		 * But does this work on Solaris?
-		 * As such, we should be notified of reachability by its
-		 * existance with a hardware address.
-		 */
-		if (rtm->rtm_flags & (RTF_HOST)) {
-			const struct sockaddr *rti_info[RTAX_MAX];
-			struct in6_addr dst6;
-			struct sockaddr_dl sdl;
+	/*
+	 * BSD announces host routes.
+	 * As such, we should be notified of reachability by its
+	 * existance with a hardware address.
+	 * Ensure we don't call this for a newly incomplete state.
+	 */
+	if (rt.rt_dest.sa_family == AF_INET6 &&
+	    (rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) &&
+	    !(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK)))
+	{
+		bool reachable;
 
-			if (get_addrs(rtm->rtm_addrs, sa,
-			    rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
-				return -1;
-			COPYOUT6(dst6, rti_info[RTAX_DST]);
-			if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)
-				memcpy(&sdl, rti_info[RTAX_GATEWAY],
-				    sizeof(sdl));
-			else
-				sdl.sdl_alen = 0;
-			ipv6nd_neighbour(ctx, &dst6,
-			    rtm->rtm_type != RTM_DELETE && sdl.sdl_alen ?
-			    IPV6ND_REACHABLE : 0);
-		}
-		break;
+		reachable = (rtm->rtm_type == RTM_ADD ||
+		    rtm->rtm_type == RTM_CHANGE) &&
+		    rt.rt_dflags & RTDF_GATELINK;
+		ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable);
 	}
 #endif
 
-	if (if_copyrt(ctx, &rt, rtm) == -1 && errno != ESRCH)
-		return -1;
 	if (if_finishrt(ctx, &rt) == -1)
 		return -1;
 	rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
@@ -885,10 +904,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 	if (~ifam->ifam_addrs & RTA_IFA)
 		return 0;
 
-	/* We have already checked that at least one address must be
-	 * present after the ifam structure. */
-	/* coverity[ptr_arith] */
-	if (get_addrs(ifam->ifam_addrs, ifam + 1,
+	if (get_addrs(ifam->ifam_addrs, (const char *)ifam + sizeof(*ifam),
 		      ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1)
 		return -1;
 	sa = rti_info[RTAX_IFA];
@@ -949,7 +965,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 			if (if_getbrdaddr(ctx, ifalias, &bcast) == -1)
 				return 0;
 		}
-		flags = if_addrflags(ifp, &addr, ifalias);
+		flags = if_addrflags(ifp, NULL, ifalias);
 		if (ifam->ifam_type == RTM_DELADDR) {
 			if (flags != -1)
 				return 0;
@@ -982,7 +998,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const str
 				return 0;
 			strlcpy(ifalias, ia->alias, sizeof(ifalias));
 		}
-		flags = if_addrflags6(ifp, &addr6, ifalias);
+		flags = if_addrflags6(ifp, NULL, ifalias);
 		if (ifam->ifam_type == RTM_DELADDR) {
 			if (flags != -1)
 				return 0;
@@ -1038,7 +1054,8 @@ if_dispatch(struct dhcpcd_ctx *ctx, cons
 		return if_ifinfo(ctx, (const void *)rtm);
 	case RTM_ADD:		/* FALLTHROUGH */
 	case RTM_CHANGE:	/* FALLTHROUGH */
-	case RTM_DELETE:
+	case RTM_DELETE:	/* FALLTHROUGH */
+	case RTM_MISS:
 		return if_rtm(ctx, (const void *)rtm);
 	case RTM_CHGADDR:	/* FALLTHROUGH */
 	case RTM_DELADDR:	/* FALLTHROUGH */
@@ -1053,20 +1070,28 @@ int
 if_handlelink(struct dhcpcd_ctx *ctx)
 {
 	struct rtm rtm;
-	struct iovec iov = { .iov_base = &rtm, .iov_len = sizeof(rtm) };
-	struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
 	ssize_t len;
 
-	if ((len = recvmsg(ctx->link_fd, &msg, 0)) == -1)
-		return -1;
+	len = read(ctx->link_fd, &rtm, sizeof(rtm));
 	if (len == -1)
 		return -1;
 	if (len == 0)
 		return 0;
-	if (len < rtm.hdr.rtm_msglen) {
+	if ((size_t)len < sizeof(rtm.hdr.rtm_msglen) ||
+	    len != rtm.hdr.rtm_msglen)
+	{
 		errno = EINVAL;
 		return -1;
 	}
+	/*
+	 * Coverity thinks that the data could be tainted from here.
+	 * I have no idea how because the length of the data we read
+	 * is guarded by len and checked to match rtm_msglen.
+	 * The issue seems to be related to extracting the addresses
+	 * at the end of the header, but seems to have no issues with the
+	 * equivalent call in if_initrt.
+	 */
+	/* coverity[tainted_data] */
 	return if_dispatch(ctx, &rtm.hdr);
 }
 
@@ -1087,19 +1112,41 @@ if_octetstr(char *buf, const Octet_t *o,
 }
 
 static int
+if_setflags(int fd, const char *ifname, uint64_t flags)
+{
+	struct lifreq		lifr = { .lifr_addrlen = 0 };
+
+	strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
+	if (ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1)
+		return -1;
+	if ((lifr.lifr_flags & flags) != flags) {
+		lifr.lifr_flags |= flags;
+		if (ioctl(fd, SIOCSLIFFLAGS, &lifr) == -1)
+			return -1;
+	}
+	return 0;
+}
+
+static int
 if_addaddr(int fd, const char *ifname,
     struct sockaddr_storage *addr, struct sockaddr_storage *mask,
-    struct sockaddr_storage *brd)
+    struct sockaddr_storage *brd, uint8_t plen)
 {
-	struct lifreq		lifr;
+	struct lifreq		lifr = { .lifr_addrlen = plen };
 
-	memset(&lifr, 0, sizeof(lifr));
 	strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
 
 	/* First assign the netmask. */
 	lifr.lifr_addr = *mask;
-	if (ioctl(fd, SIOCSLIFNETMASK, &lifr) == -1)
-		return -1;
+	if (addr == NULL) {
+		lifr.lifr_addrlen = plen;
+		if (ioctl(fd, SIOCSLIFSUBNET, &lifr) == -1)
+			return -1;
+		goto up;
+	} else {
+		if (ioctl(fd, SIOCSLIFNETMASK, &lifr) == -1)
+			return -1;
+	}
 
 	/* Then assign the address. */
 	lifr.lifr_addr = *addr;
@@ -1113,15 +1160,39 @@ if_addaddr(int fd, const char *ifname,
 			return -1;
 	}
 
-	/* Now bring it up. */
-	if (ioctl(fd, SIOCGLIFFLAGS, &lifr) == -1)
-		return -1;
-	if (!(lifr.lifr_flags & IFF_UP)) {
-		lifr.lifr_flags |= IFF_UP;
-		if (ioctl(fd, SIOCSLIFFLAGS, &lifr) == -1)
-			return -1;
+up:
+	return if_setflags(fd, ifname, IFF_UP);
+}
+
+static int
+if_getaf_fd(const struct dhcpcd_ctx *ctx, int af)
+{
+
+	if (af == AF_INET)
+		return ctx->pf_inet_fd;
+	if (af == AF_INET6) {
+		struct priv	*priv;
+
+		priv = (struct priv *)ctx->priv;
+		return priv->pf_inet6_fd;
 	}
 
+	errno = EAFNOSUPPORT;
+	return -1;
+}
+
+int
+if_getsubnet(struct dhcpcd_ctx *ctx, const char *ifname, int af,
+    void *subnet, size_t subnet_len)
+{
+	struct lifreq		lifr = { .lifr_addrlen = 0 };
+	int fd;
+
+	fd = if_getaf_fd(ctx, af);
+	strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
+	if (ioctl(fd, SIOCGLIFSUBNET, &lifr) == -1)
+		return -1;
+	memcpy(subnet, &lifr.lifr_addr, MIN(subnet_len,sizeof(lifr.lifr_addr)));
 	return 0;
 }
 
@@ -1134,14 +1205,7 @@ if_plumblif(int cmd, const struct dhcpcd
 	memset(&lifr, 0, sizeof(lifr));
 	strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
 	lifr.lifr_addr.ss_family = af;
-	if (af == AF_INET)
-		s = ctx->pf_inet_fd;
-	else {
-		struct priv	*priv;
-
-		priv = (struct priv *)ctx->priv;
-		s = priv->pf_inet6_fd;
-	}
+	s = if_getaf_fd(ctx, af);
 	return ioctl(s,
 	    cmd == RTM_NEWADDR ? SIOCLIFADDIF : SIOCLIFREMOVEIF,
 	    &lifr) == -1 && errno != EEXIST ? -1 : 0;
@@ -1161,23 +1225,18 @@ if_plumbif(const struct dhcpcd_ctx *ctx,
 	if (if_nametospec(ifname, &spec) == -1)
 		return -1;
 
+	af_fd = if_getaf_fd(ctx, af);
+
 	switch (af) {
 	case AF_INET:
 		flags = IFF_IPV4;
-		af_fd = ctx->pf_inet_fd;
 		udp_dev = UDP_DEV_NAME;
 		break;
 	case AF_INET6:
-	{
-		struct priv *priv;
-
 		/* We will take care of setting the link local address. */
 		flags = IFF_IPV6 | IFF_NOLINKLOCAL;
-		priv = (struct priv *)ctx->priv;
-		af_fd = priv->pf_inet6_fd;
 		udp_dev = UDP6_DEV_NAME;
 		break;
-	}
 	default:
 		errno = EPROTONOSUPPORT;
 		return -1;
@@ -1271,28 +1330,9 @@ if_unplumbif(const struct dhcpcd_ctx *ct
 
 	/* For the time being, don't unplumb the interface, just
 	 * set the address to zero. */
-	switch (af) {
-#ifdef INET
-	case AF_INET:
-		fd = ctx->pf_inet_fd;
-		break;
-#endif
-#ifdef INET6
-	case AF_INET6:
-	{
-		struct priv		*priv;
-
-		priv = (struct priv *)ctx->priv;
-		fd = priv->pf_inet6_fd;
-		break;
-	}
-#endif
-	default:
-		errno = EAFNOSUPPORT;
-		return -1;
-	}
+	fd = if_getaf_fd(ctx, af);
 	return if_addaddr(fd, ifname, &addr, &addr,
-	    af == AF_INET ? &addr : NULL);
+	    af == AF_INET ? &addr : NULL, 0);
 }
 
 static int
@@ -1567,9 +1607,11 @@ if_address(unsigned char cmd, const stru
 		struct sockaddr		sa;
 		struct sockaddr_storage ss;
 	} addr, mask, brd;
+	int fd = ia->iface->ctx->pf_inet_fd;
 
 	/* Either remove the alias or ensure it exists. */
-	if (if_plumb(cmd, ia->iface->ctx, AF_INET, ia->alias) == -1)
+	if (if_plumb(cmd, ia->iface->ctx, AF_INET, ia->alias) == -1 &&
+	    errno != EEXIST)
 		return -1;
 
 	if (cmd == RTM_DELADDR)
@@ -1586,26 +1628,15 @@ if_address(unsigned char cmd, const stru
 	sa_in_init(&addr.sa, &ia->addr);
 	sa_in_init(&mask.sa, &ia->mask);
 	sa_in_init(&brd.sa, &ia->brd);
-	return if_addaddr(ia->iface->ctx->pf_inet_fd, ia->alias,
-	    &addr.ss, &mask.ss, &brd.ss);
+	return if_addaddr(fd, ia->alias, &addr.ss, &mask.ss, &brd.ss, 0);
 }
 
 int
-if_addrflags(const struct interface *ifp, const struct in_addr *addr,
+if_addrflags(const struct interface *ifp, __unused const struct in_addr * ia,
     const char *alias)
 {
-	union sa_ss	ss;
-	uint64_t	aflags;
-	int		flags;
-
-	sa_in_init(&ss.sa, addr);
-	aflags = if_addrflags0(ifp->ctx->pf_inet_fd, alias, &ss.sa);
-	if (aflags == 0)
-		return -1;
-	flags = 0;
-	if (aflags & IFF_DUPLICATE)
-		flags |= IN_IFF_DUPLICATED;
-	return flags;
+
+	return if_addrflags0(ifp->ctx->pf_inet_fd, AF_INET, alias);
 }
 
 #endif
@@ -1619,11 +1650,11 @@ if_address6(unsigned char cmd, const str
 		struct sockaddr_in6	sin6;
 		struct sockaddr_storage ss;
 	} addr, mask;
-	const struct priv		*priv;
-	int			r;
+	int			fd, r;
 
 	/* Either remove the alias or ensure it exists. */
-	if (if_plumb(cmd, ia->iface->ctx, AF_INET6, ia->alias) == -1)
+	if (if_plumb(cmd, ia->iface->ctx, AF_INET6, ia->alias) == -1 &&
+	    errno != EEXIST)
 		return -1;
 
 	if (cmd == RTM_DELADDR)
@@ -1634,34 +1665,34 @@ if_address6(unsigned char cmd, const str
 		return -1;
 	}
 
-	sa_in6_init(&addr.sa, &ia->addr);
-	mask.sin6.sin6_family = AF_INET6;
-	ipv6_mask(&mask.sin6.sin6_addr, ia->prefix_len);
-	priv = (const struct priv *)ia->iface->ctx->priv;
-	r = if_addaddr(priv->pf_inet6_fd, ia->alias, &addr.ss, &mask.ss, NULL);
+	fd = if_getaf_fd(ia->iface->ctx, AF_INET6);
+
+	if (!(ia->flags & IPV6_AF_AUTOCONF) && ia->flags & IPV6_AF_RAPFX) {
+		if (if_setflags(fd, ia->alias, IFF_NOLOCAL) ==-1)
+			return -1;
+		sa_in6_init(&mask.sa, &ia->prefix);
+		r = if_addaddr(fd, ia->alias,
+		    NULL, &mask.ss, NULL, ia->prefix_len);
+	} else {
+		sa_in6_init(&addr.sa, &ia->addr);
+		mask.sin6.sin6_family = AF_INET6;
+		ipv6_mask(&mask.sin6.sin6_addr, ia->prefix_len);
+		r = if_addaddr(fd, ia->alias,
+		    &addr.ss, &mask.ss, NULL, ia->prefix_len);
+	}
 	if (r == -1 && errno == EEXIST)
 		return 0;
 	return r;
 }
 
 int
-if_addrflags6(const struct interface *ifp, const struct in6_addr *addr,
+if_addrflags6(const struct interface *ifp, __unused const struct in6_addr *ia,
     const char *alias)
 {
-	struct priv		*priv;
-	union sa_ss		ss;
-	uint64_t		aflags;
-	int			flags;
+	int			fd;
 
-	priv = (struct priv *)ifp->ctx->priv;
-	sa_in6_init(&ss.sa, addr);
-	aflags = if_addrflags0(priv->pf_inet6_fd, alias, &ss.sa);
-	if (aflags == 0)
-		return -1;
-	flags = 0;
-	if (aflags & IFF_DUPLICATE)
-		flags |= IN6_IFF_DUPLICATED;
-	return flags;
+	fd = if_getaf_fd(ifp->ctx, AF_INET6);
+	return if_addrflags0(fd, AF_INET6, alias);
 }
 
 int
Index: src/external/bsd/dhcpcd/dist/src/if.h
diff -u src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.10 src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.10.2.1
--- src/external/bsd/dhcpcd/dist/src/if.h:1.1.1.10	Tue Jul 30 10:23:09 2019
+++ src/external/bsd/dhcpcd/dist/src/if.h	Thu Sep  5 08:56:55 2019
@@ -107,6 +107,7 @@
 struct ifaddrs;
 int if_getifaddrs(struct ifaddrs **);
 #define	getifaddrs	if_getifaddrs
+int if_getsubnet(struct dhcpcd_ctx *, const char *, int, void *, size_t);
 #endif
 
 int if_getflags(struct interface *ifp);
Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.h
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.h:1.1.1.10 src/external/bsd/dhcpcd/dist/src/ipv6nd.h:1.1.1.10.2.1
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.h:1.1.1.10	Wed Jul 24 09:54:55 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.h	Thu Sep  5 08:56:55 2019
@@ -51,8 +51,9 @@ struct ra {
 	uint32_t retrans;
 	uint32_t mtu;
 	struct ipv6_addrhead addrs;
-	uint8_t hasdns;
-	uint8_t expired;
+	bool hasdns;
+	bool expired;
+	bool isreachable;
 };
 
 TAILQ_HEAD(ra_head, ra);
@@ -90,9 +91,6 @@ struct rs_state {
 #define	RETRANS_TIMER			1000	/* milliseconds */
 #define	DELAY_FIRST_PROBE_TIME		5	/* seconds */
 
-#define	IPV6ND_REACHABLE		(1 << 0)
-#define	IPV6ND_ROUTER			(1 << 1)
-
 void ipv6nd_printoptions(const struct dhcpcd_ctx *,
     const struct dhcp_opt *, size_t);
 void ipv6nd_startrs(struct interface *);
@@ -103,14 +101,15 @@ struct ipv6_addr *ipv6nd_findaddr(struct
     const struct in6_addr *, unsigned int);
 ssize_t ipv6nd_free(struct interface *);
 void ipv6nd_expirera(void *arg);
-int ipv6nd_hasra(const struct interface *);
-int ipv6nd_hasradhcp(const struct interface *);
+bool ipv6nd_hasralifetime(const struct interface *, bool);
+#define	ipv6nd_hasra(i)		ipv6nd_hasralifetime((i), false)
+bool ipv6nd_hasradhcp(const struct interface *);
 void ipv6nd_handleifa(int, struct ipv6_addr *, pid_t);
 int ipv6nd_dadcompleted(const struct interface *);
 void ipv6nd_advertise(struct ipv6_addr *);
 void ipv6nd_startexpire(struct interface *);
 void ipv6nd_drop(struct interface *);
-void ipv6nd_neighbour(struct dhcpcd_ctx *, struct in6_addr *, int);
+void ipv6nd_neighbour(struct dhcpcd_ctx *, struct in6_addr *, bool);
 #endif /* INET6 */
 
 #endif /* IPV6ND_H */
Index: src/external/bsd/dhcpcd/dist/src/script.c
diff -u src/external/bsd/dhcpcd/dist/src/script.c:1.1.1.10 src/external/bsd/dhcpcd/dist/src/script.c:1.1.1.10.2.1
--- src/external/bsd/dhcpcd/dist/src/script.c:1.1.1.10	Tue Jul 30 10:23:09 2019
+++ src/external/bsd/dhcpcd/dist/src/script.c	Thu Sep  5 08:56:55 2019
@@ -33,6 +33,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <signal.h>
@@ -172,12 +173,12 @@ efprintf(FILE *fp, const char *fmt, ...)
 	return r;
 }
 
-static ssize_t
+static long
 make_env(const struct interface *ifp, const char *reason)
 {
 	struct dhcpcd_ctx *ctx = ifp->ctx;
 	FILE *fp;
-	char **env, **envp, *buf, *bufp, *endp, *path;
+	char **env, **envp, *bufp, *endp, *path;
 	size_t nenv;
 	long buf_pos, i;
 	int protocol = PROTO_LINK;
@@ -458,31 +459,38 @@ dumplease:
 		logerr(__func__);
 		goto eexit;
 	}
-#ifdef HAVE_OPEN_MEMSTREAM
-	buf = ctx->script_buf;
-#else
+
+#ifndef HAVE_OPEN_MEMSTREAM
 	size_t buf_len = (size_t)buf_pos;
 	if (ctx->script_buflen < buf_len) {
-		buf = realloc(ctx->script_buf, buf_len);
+		char *buf = realloc(ctx->script_buf, buf_len);
 		if (buf == NULL)
 			goto eexit;
 		ctx->script_buf = buf;
 		ctx->script_buflen = buf_len;
 	}
-	buf = ctx->script_buf;
 	rewind(fp);
-	if (fread(buf, sizeof(char), buf_len, fp) != buf_len)
+	if (fread(ctx->script_buf, sizeof(char), buf_len, fp) != buf_len)
 		goto eexit;
 	fclose(fp);
 	fp = NULL;
 #endif
 
+	/* Count the terminated env strings.
+	 * Assert that the terminations are correct. */
 	nenv = 0;
-	endp = buf + buf_pos;
-	for (bufp = buf; bufp < endp; bufp++) {
-		if (*bufp == '\0')
+	endp = ctx->script_buf + buf_pos;
+	for (bufp = ctx->script_buf; bufp < endp; bufp++) {
+		if (*bufp == '\0') {
+#ifndef NDEBUG
+			if (bufp + 1 < endp)
+				assert(*(bufp + 1) != '\0');
+#endif
 			nenv++;
+		}
 	}
+	assert(*(bufp - 1) == '\0');
+
 	if (ctx->script_envlen < nenv) {
 		env = reallocarray(ctx->script_env, nenv + 1, sizeof(*env));
 		if (env == NULL)
@@ -490,7 +498,8 @@ dumplease:
 		ctx->script_env = env;
 		ctx->script_envlen = nenv;
 	}
-	bufp = buf;
+
+	bufp = ctx->script_buf;
 	envp = ctx->script_env;
 	*envp++ = bufp++;
 	endp--; /* Avoid setting the last \0 to an invalid pointer */
@@ -500,7 +509,7 @@ dumplease:
 	}
 	*envp = NULL;
 
-	return (ssize_t)nenv;
+	return buf_pos - 1;
 
 eexit:
 	logerr(__func__);
@@ -516,10 +525,12 @@ send_interface1(struct fd_list *fd, cons
     const char *reason)
 {
 	struct dhcpcd_ctx *ctx = ifp->ctx;
+	long len;
 
-	if (make_env(ifp, reason) == -1)
+	len = make_env(ifp, reason);
+	if (len == -1)
 		return -1;
-	return control_queue(fd, ctx->script_buf, ctx->script_buflen, 1);
+	return control_queue(fd, ctx->script_buf,  (size_t)len, 1);
 }
 
 int
@@ -636,8 +647,8 @@ send_listeners:
 	TAILQ_FOREACH(fd, &ctx->control_fds, next) {
 		if (!(fd->flags & FD_LISTEN))
 			continue;
-		if (control_queue(fd, ctx->script_buf, ctx->script_buflen, 1)
-		    == -1)
+		if (control_queue(fd, ctx->script_buf, ctx->script_buflen,
+		    true) == -1)
 			logerr("%s: control_queue", __func__);
 		else
 			status = 1;

Index: src/external/bsd/dhcpcd/dist/src/ipv4.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv4.c:1.1.1.16 src/external/bsd/dhcpcd/dist/src/ipv4.c:1.1.1.16.2.1
--- src/external/bsd/dhcpcd/dist/src/ipv4.c:1.1.1.16	Tue Jul 30 10:23:09 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv4.c	Thu Sep  5 08:56:55 2019
@@ -268,13 +268,12 @@ inet_dhcproutes(rb_tree_t *routes, struc
 	rb_tree_init(&nroutes, &rt_compare_proto_ops);
 
 	/* First, add a subnet route. */
-	if (!(ifp->flags & IFF_POINTOPOINT) &&
+	if (state->addr->mask.s_addr != INADDR_ANY
 #ifndef BSD
 	    /* BSD adds a route in this instance */
-	    state->addr->mask.s_addr != INADDR_BROADCAST &&
+	    && state->addr->mask.s_addr != INADDR_BROADCAST
 #endif
-	    state->addr->mask.s_addr != INADDR_ANY)
-	{
+	) {
 		if ((rt = rt_new(ifp)) == NULL)
 			return -1;
 		rt->rt_dflags |= RTDF_IFA_ROUTE;
@@ -680,8 +679,10 @@ ipv4_addaddr(struct interface *ifp, cons
 		logdebugx("%s: aliased %s", ia->alias, ia->saddr);
 #endif
 
-	logdebugx("%s: adding IP address %s broadcast %s",
-	    ifp->name, ia->saddr, inet_ntoa(*bcast));
+	logdebugx("%s: adding IP address %s %s %s",
+	    ifp->name, ia->saddr,
+	    ifp->flags & IFF_POINTOPOINT ? "destination" : "broadcast",
+	    inet_ntoa(*bcast));
 	if (if_address(RTM_NEWADDR, ia) == -1) {
 		if (errno != EEXIST)
 			logerr("%s: if_addaddress",
@@ -742,7 +743,8 @@ ipv4_applyaddr(void *arg)
 #ifdef ARP
 				/* Announce the preferred address to
 				 * kick ARP caches. */
-				arp_announceaddr(ifp->ctx, &lease->addr);
+				if (!(ifp->flags & IFF_NOARP))
+					arp_announceaddr(ifp->ctx,&lease->addr);
 #endif
 			}
 			script_runreason(ifp, state->reason);
@@ -804,7 +806,8 @@ ipv4_applyaddr(void *arg)
 	rt_build(ifp->ctx, AF_INET);
 
 #ifdef ARP
-	arp_announceaddr(ifp->ctx, &state->addr->addr);
+	if (!(ifp->flags & IFF_NOARP))
+		arp_announceaddr(ifp->ctx, &state->addr->addr);
 #endif
 
 	if (state->state == DHS_BOUND) {

Index: src/external/bsd/dhcpcd/dist/src/ipv6.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6.c:1.3 src/external/bsd/dhcpcd/dist/src/ipv6.c:1.3.2.1
--- src/external/bsd/dhcpcd/dist/src/ipv6.c:1.3	Tue Jul 30 10:25:03 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6.c	Thu Sep  5 08:56:55 2019
@@ -629,7 +629,7 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons
 	uint32_t pltime, vltime;
 	__printflike(1, 2) void (*logfunc)(const char *, ...);
 #ifdef ND6_ADVERTISE
-	bool vltime_was_zero;
+	bool vltime_was_zero = ia->prefix_vltime == 0;
 #endif
 #ifdef __sun
 	struct ipv6_state *state;
@@ -641,7 +641,11 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons
 	if (ia->flags & IPV6_AF_DADCOMPLETED) {
 		logdebugx("%s: IP address %s already exists",
 		    ia->iface->name, ia->saddr);
+#ifdef ND6_ADVERTISE
+		goto advertise;
+#else
 		return 0;
+#endif
 	}
 #endif
 
@@ -707,9 +711,6 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons
 		    " seconds",
 		    ifp->name, ia->prefix_pltime, ia->prefix_vltime);
 
-#ifdef ND6_ADVERTISE
-	vltime_was_zero = ia->prefix_vltime == 0;
-#endif
 	if (if_address6(RTM_NEWADDR, ia) == -1) {
 		logerr(__func__);
 		/* Restore real pltime and vltime */
@@ -774,6 +775,9 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons
 #endif
 
 #ifdef ND6_ADVERTISE
+#ifdef __sun
+advertise:
+#endif
 	/* Re-advertise the preferred address to be safe. */
 	if (!vltime_was_zero)
 		ipv6nd_advertise(ia);
@@ -1060,6 +1064,31 @@ ipv6_getstate(struct interface *ifp)
 	return state;
 }
 
+struct ipv6_addr *
+ipv6_ifanyglobal(struct interface *ifp)
+{
+	struct ipv6_state *state;
+	struct ipv6_addr *ia;
+
+	if (ifp->carrier == LINK_DOWN)
+		return NULL;
+
+	state = IPV6_STATE(ifp);
+	if (state == NULL)
+		return NULL;
+
+	TAILQ_FOREACH(ia, &state->addrs, next) {
+		if (IN6_IS_ADDR_LINKLOCAL(&ia->addr))
+			continue;
+		/* Let's be optimistic.
+		 * Any decent OS won't forward or accept traffic
+		 * from/to tentative or detached addresses. */
+		if (!(ia->addr_flags & IN6_IFF_DUPLICATED))
+			break;
+	}
+	return ia;
+}
+
 void
 ipv6_handleifa(struct dhcpcd_ctx *ctx,
     int cmd, struct if_head *ifs, const char *ifname,
@@ -1069,6 +1098,22 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
 	struct ipv6_state *state;
 	struct ipv6_addr *ia;
 	struct ll_callback *cb;
+	bool anyglobal;
+
+#ifdef __sun
+	struct sockaddr_in6 subnet;
+
+	/* Solaris on-link route is an unspecified address! */
+	if (IN6_IS_ADDR_UNSPECIFIED(addr)) {
+		if (if_getsubnet(ctx, ifname, AF_INET6,
+		    &subnet, sizeof(subnet)) == -1)
+		{
+			logerr(__func__);
+			return;
+		}
+		addr = &subnet.sin6_addr;
+	}
+#endif
 
 #if 0
 	char dbuf[INET6_ADDRSTRLEN];
@@ -1076,8 +1121,8 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
 
 	dbp = inet_ntop(AF_INET6, &addr->s6_addr,
 	    dbuf, INET6_ADDRSTRLEN);
-	loginfox("%s: cmd %d addr %s",
-	    ifname, cmd, dbp);
+	loginfox("%s: cmd %d addr %s addrflags %d",
+	    ifname, cmd, dbp, addrflags);
 #endif
 
 	if (ifs == NULL)
@@ -1088,6 +1133,7 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
 		return;
 	if ((state = ipv6_getstate(ifp)) == NULL)
 		return;
+	anyglobal = ipv6_ifanyglobal(ifp) != NULL;
 
 	TAILQ_FOREACH(ia, &state->addrs, next) {
 		if (IN6_ARE_ADDR_EQUAL(&ia->addr, addr))
@@ -1187,6 +1233,7 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
 	if (ia == NULL)
 		return;
 
+	ctx->options &= ~DHCPCD_RTBUILD;
 	ipv6nd_handleifa(cmd, ia, pid);
 #ifdef DHCP6
 	dhcp6_handleifa(cmd, ia, pid);
@@ -1198,6 +1245,15 @@ out:
 		ipv6_freeaddr(ia);
 	else if (!(ia->addr_flags & IN6_IFF_NOTUSEABLE))
 		ia->flags |= IPV6_AF_DADCOMPLETED;
+
+	/* If we've not already called rt_build via the IPv6ND
+	 * or DHCP6 handlers and the existance of any useable
+	 * global address on the interface has changed,
+	 * call rt_build to add/remove the default route. */
+	if (ifp->active && ifp->options->options & DHCPCD_IPV6 &&
+	    !(ctx->options & DHCPCD_RTBUILD) &&
+	    (ipv6_ifanyglobal(ifp) != NULL) != anyglobal)
+		rt_build(ctx, AF_INET6);
 }
 
 int
@@ -1498,7 +1554,13 @@ ipv6_newaddr(struct interface *ifp, cons
 			goto err;
 	} else if (ia->flags & IPV6_AF_RAPFX) {
 		ia->prefix = *addr;
+#ifdef __sun
+		ia->addr = *addr;
+		cbp = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf));
+		goto paddr;
+#else
 		return ia;
+#endif
 	} else if (ia->flags & (IPV6_AF_REQUEST | IPV6_AF_DELEGATEDPFX) &&
 	           prefix_len != 128)
 	{
@@ -2273,6 +2335,8 @@ inet6_raroutes(rb_tree_t *routes, struct
 		}
 		if (rap->lifetime == 0)
 			continue;
+		if (ipv6_ifanyglobal(rap->iface) == NULL)
+			continue;
 		rt = inet6_makerouter(rap);
 		if (rt == NULL)
 			continue;
Index: src/external/bsd/dhcpcd/dist/src/ipv6.h
diff -u src/external/bsd/dhcpcd/dist/src/ipv6.h:1.3 src/external/bsd/dhcpcd/dist/src/ipv6.h:1.3.2.1
--- src/external/bsd/dhcpcd/dist/src/ipv6.h:1.3	Tue Jul 30 10:25:03 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6.h	Thu Sep  5 08:56:55 2019
@@ -100,7 +100,8 @@
 #endif
 
 /* This was fixed in NetBSD */
-#if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 699002000
+#if (defined(__DragonFly_version) && __DragonFly_version >= 500704) || \
+    (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 699002000)
 #  undef IPV6_POLLADDRFLAG
 #endif
 
@@ -109,9 +110,9 @@
     * While it supports DaD, to seems to only expose IFF_DUPLICATE
     * so we have no way of knowing if it's tentative or not.
     * I don't even know if Solaris has any special treatment for tentative. */
-#  define IN6_IFF_TENTATIVE	0
+#  define IN6_IFF_TENTATIVE	0x02
 #  define IN6_IFF_DUPLICATED	0x04
-#  define IN6_IFF_DETACHED	0
+#  define IN6_IFF_DETACHED	0x00
 #endif
 
 #define IN6_IFF_NOTUSEABLE \
@@ -153,9 +154,12 @@
  * ND6 Advertising is only used for IP address sharing to prefer
  * the address on a specific interface.
  * This just fails to work on OpenBSD and causes erroneous duplicate
- * address messages on BSD's other then NetBSD.
+ * address messages on BSD's other then DragonFly and NetBSD.
  */
-#if !defined(SMALL) && (defined(__NetBSD__) || defined(__linux__))
+#if !defined(SMALL) && \
+    ((defined(__DragonFly_version) && __DragonFly_version >= 500703) || \
+    (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 899002800) || \
+    defined(__linux__) || defined(__sun))
 #  define ND6_ADVERTISE
 #endif
 
@@ -269,6 +273,7 @@ int ipv6_handleifa_addrs(int, struct ipv
 struct ipv6_addr *ipv6_iffindaddr(struct interface *,
     const struct in6_addr *, int);
 int ipv6_hasaddr(const struct interface *);
+struct ipv6_addr *ipv6_ifanyglobal(struct interface *);
 int ipv6_findaddrmatch(const struct ipv6_addr *, const struct in6_addr *,
     unsigned int);
 struct ipv6_addr *ipv6_findaddr(struct dhcpcd_ctx *,

Index: src/external/bsd/dhcpcd/dist/src/route.c
diff -u src/external/bsd/dhcpcd/dist/src/route.c:1.1.1.12 src/external/bsd/dhcpcd/dist/src/route.c:1.1.1.12.2.1
--- src/external/bsd/dhcpcd/dist/src/route.c:1.1.1.12	Tue Jul 30 10:23:09 2019
+++ src/external/bsd/dhcpcd/dist/src/route.c	Thu Sep  5 08:56:55 2019
@@ -39,6 +39,7 @@
 #include "common.h"
 #include "dhcpcd.h"
 #include "if.h"
+#include "if-options.h"
 #include "ipv4.h"
 #include "ipv4ll.h"
 #include "ipv6.h"
@@ -139,7 +140,19 @@ rt_compare_os(__unused void *context, co
 }
 
 static int
-rt_compare_proto(__unused void *context, const void *node1, const void *node2)
+rt_compare_list(__unused void *context, const void *node1, const void *node2)
+{
+	const struct rt *rt1 = node1, *rt2 = node2;
+
+	if (rt1->rt_order > rt2->rt_order)
+		return 1;
+	if (rt1->rt_order < rt2->rt_order)
+		return -1;
+	return 0;
+}
+
+static int
+rt_compare_proto(void *context, const void *node1, const void *node2)
 {
 	const struct rt *rt1 = node1, *rt2 = node2;
 	int c;
@@ -161,11 +174,7 @@ rt_compare_proto(__unused void *context,
 		return c;
 
 	/* Finally the order in which the route was given to us. */
-	if (rt1->rt_order > rt2->rt_order)
-		return 1;
-	if (rt1->rt_order < rt2->rt_order)
-		return -1;
-	return 0;
+	return rt_compare_list(context, rt1, rt2);
 }
 
 static const rb_tree_ops_t rt_compare_os_ops = {
@@ -175,6 +184,13 @@ static const rb_tree_ops_t rt_compare_os
 	.rbto_context = NULL
 };
 
+const rb_tree_ops_t rt_compare_list_ops = {
+	.rbto_compare_nodes = rt_compare_list,
+	.rbto_compare_key = rt_compare_list,
+	.rbto_node_offset = offsetof(struct rt, rt_tree),
+	.rbto_context = NULL
+};
+
 const rb_tree_ops_t rt_compare_proto_ops = {
 	.rbto_compare_nodes = rt_compare_proto,
 	.rbto_compare_key = rt_compare_proto,
@@ -670,6 +686,7 @@ rt_build(struct dhcpcd_ctx *ctx, int af)
 	rb_tree_init(&kroutes, &rt_compare_os_ops);
 	if_initrt(ctx, &kroutes, af);
 	ctx->rt_order = 0;
+	ctx->options |= DHCPCD_RTBUILD;
 
 	switch (af) {
 #ifdef INET

Index: src/external/bsd/dhcpcd/dist/src/route.h
diff -u src/external/bsd/dhcpcd/dist/src/route.h:1.1.1.7 src/external/bsd/dhcpcd/dist/src/route.h:1.1.1.7.2.1
--- src/external/bsd/dhcpcd/dist/src/route.h:1.1.1.7	Wed Jul 24 09:54:55 2019
+++ src/external/bsd/dhcpcd/dist/src/route.h	Thu Sep  5 08:56:55 2019
@@ -92,10 +92,12 @@ struct rt {
 #define	RTDF_RA			0x08		/* Router Advertisement */
 #define	RTDF_DHCP		0x10		/* DHCP route */
 #define	RTDF_STATIC		0x20		/* Configured in dhcpcd */
+#define	RTDF_GATELINK		0x40		/* Gateway is on link */
 	size_t			rt_order;
 	rb_node_t		rt_tree;
 };
 
+extern const rb_tree_ops_t rt_compare_list_ops;
 extern const rb_tree_ops_t rt_compare_proto_ops;
 
 void rt_init(struct dhcpcd_ctx *);

Reply via email to