Module Name:    src
Committed By:   roy
Date:           Tue Jul 30 10:25:03 UTC 2019

Modified Files:
        src/external/bsd/dhcpcd/dist/src: bpf.c dhcp.c dhcp6.c dhcpcd.c
            if-bsd.c if-options.c ipv6.c ipv6.h ipv6nd.c

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/external/bsd/dhcpcd/dist/src/bpf.c \
    src/external/bsd/dhcpcd/dist/src/dhcp6.c
cvs rdiff -u -r1.22 -r1.23 src/external/bsd/dhcpcd/dist/src/dhcp.c \
    src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.9 -r1.10 src/external/bsd/dhcpcd/dist/src/if-bsd.c \
    src/external/bsd/dhcpcd/dist/src/ipv6nd.c
cvs rdiff -u -r1.15 -r1.16 src/external/bsd/dhcpcd/dist/src/if-options.c
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/dhcpcd/dist/src/ipv6.c \
    src/external/bsd/dhcpcd/dist/src/ipv6.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/src/bpf.c
diff -u src/external/bsd/dhcpcd/dist/src/bpf.c:1.10 src/external/bsd/dhcpcd/dist/src/bpf.c:1.11
--- src/external/bsd/dhcpcd/dist/src/bpf.c:1.10	Wed Jul 24 09:57:43 2019
+++ src/external/bsd/dhcpcd/dist/src/bpf.c	Tue Jul 30 10:25:03 2019
@@ -93,7 +93,7 @@ bpf_frame_header_len(const struct interf
 	}
 }
 
-static const uint8_t etherbroadcastaddr[] =
+static const uint8_t etherbcastaddr[] =
     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
 int
@@ -104,7 +104,7 @@ bpf_frame_bcast(const struct interface *
 	case ARPHRD_ETHER:
 		return memcmp(frame +
 		    offsetof(struct ether_header, ether_dhost),
-		    etherbroadcastaddr, sizeof(etherbroadcastaddr));
+		    etherbcastaddr, sizeof(etherbcastaddr));
 	default:
 		return -1;
 	}
@@ -552,6 +552,12 @@ bpf_arp(struct interface *ifp, int fd)
 }
 #endif
 
+#define	BPF_M_FHLEN	0
+#define	BPF_M_IPHLEN	1
+#define	BPF_M_IPLEN	2
+#define	BPF_M_UDP	3
+#define	BPF_M_UDPLEN	4
+
 static const struct bpf_insn bpf_bootp_ether[] = {
 	/* Make sure this is an IP packet. */
 	BPF_STMT(BPF_LD + BPF_H + BPF_ABS,
@@ -561,16 +567,26 @@ static const struct bpf_insn bpf_bootp_e
 
 	/* Load frame header length into X. */
 	BPF_STMT(BPF_LDX + BPF_W + BPF_IMM, sizeof(struct ether_header)),
-	/* Copy to M0. */
-	BPF_STMT(BPF_STX, 0),
+	/* Copy frame header length to memory */
+	BPF_STMT(BPF_STX, BPF_M_FHLEN),
 };
 #define BPF_BOOTP_ETHER_LEN	__arraycount(bpf_bootp_ether)
 
 static const struct bpf_insn bpf_bootp_filter[] = {
-	/* Make sure it's an optionless IPv4 packet. */
+	/* Make sure it's an IPv4 packet. */
+	BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0),
+	BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0xf0),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x40, 1, 0),
+	BPF_STMT(BPF_RET + BPF_K, 0),
+
+	/* Ensure IP header length is big enough and
+	 * store the IP header length in memory. */
 	BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0),
-	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x45, 1, 0),
+	BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x0f),
+	BPF_STMT(BPF_ALU + BPF_MUL + BPF_K, 4),
+	BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ip), 1, 0),
 	BPF_STMT(BPF_RET + BPF_K, 0),
+	BPF_STMT(BPF_ST, BPF_M_IPHLEN),
 
 	/* Make sure it's a UDP packet. */
 	BPF_STMT(BPF_LD + BPF_B + BPF_IND, offsetof(struct ip, ip_p)),
@@ -582,39 +598,42 @@ static const struct bpf_insn bpf_bootp_f
 	BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 0, 1),
 	BPF_STMT(BPF_RET + BPF_K, 0),
 
-	/* Store IP location in M1. */
+	/* Store IP length. */
 	BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct ip, ip_len)),
-	BPF_STMT(BPF_ST, 1),
-
-	/* Store IP length in M2. */
-	BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct ip, ip_len)),
-	BPF_STMT(BPF_ST, 2),
+	BPF_STMT(BPF_ST, BPF_M_IPLEN),
 
 	/* Advance to the UDP header. */
-	BPF_STMT(BPF_MISC + BPF_TXA, 0),
-	BPF_STMT(BPF_ALU + BPF_ADD + BPF_K, sizeof(struct ip)),
+	BPF_STMT(BPF_LD + BPF_MEM, BPF_M_IPHLEN),
+	BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0),
 	BPF_STMT(BPF_MISC + BPF_TAX, 0),
 
-	/* Store X in M3. */
-	BPF_STMT(BPF_STX, 3),
+	/* Store UDP location */
+	BPF_STMT(BPF_STX, BPF_M_UDP),
 
 	/* Make sure it's from and to the right port. */
 	BPF_STMT(BPF_LD + BPF_W + BPF_IND, 0),
 	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (BOOTPS << 16) + BOOTPC, 1, 0),
 	BPF_STMT(BPF_RET + BPF_K, 0),
 
-	/* Store UDP length in X. */
+	/* Store UDP length. */
 	BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct udphdr, uh_ulen)),
+	BPF_STMT(BPF_ST, BPF_M_UDPLEN),
+
+	/* Ensure that UDP length + IP header length == IP length */
+	/* Copy IP header length to X. */
+	BPF_STMT(BPF_LDX + BPF_MEM, BPF_M_IPHLEN),
+	/* Add UDP length (A) to IP header length (X). */
+	BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0),
+	/* Store result in X. */
 	BPF_STMT(BPF_MISC + BPF_TAX, 0),
-	/* Copy IP length in M2 to A. */
-	BPF_STMT(BPF_LD + BPF_MEM, 2),
-	/* Ensure IP length - IP header size == UDP length. */
-	BPF_STMT(BPF_ALU + BPF_SUB + BPF_K, sizeof(struct ip)),
+	/* Copy IP length to A. */
+	BPF_STMT(BPF_LD + BPF_MEM, BPF_M_IPLEN),
+	/* Ensure X == A. */
 	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0),
 	BPF_STMT(BPF_RET + BPF_K, 0),
 
-	/* Advance to the BOOTP packet (UDP X is in M3). */
-	BPF_STMT(BPF_LD + BPF_MEM, 3),
+	/* Advance to the BOOTP packet. */
+	BPF_STMT(BPF_LD + BPF_MEM, BPF_M_UDP),
 	BPF_STMT(BPF_ALU + BPF_ADD + BPF_K, sizeof(struct udphdr)),
 	BPF_STMT(BPF_MISC + BPF_TAX, 0),
 
@@ -695,11 +714,10 @@ bpf_bootp(struct interface *ifp, int fd)
 	}
 #endif
 
-	/* All passed, return the packet
-	 * (Frame length in M0, IP length in M2). */
-	BPF_SET_STMT(bp, BPF_LD + BPF_MEM, 0);
+	/* All passed, return the packet - frame length + ip length */
+	BPF_SET_STMT(bp, BPF_LD + BPF_MEM, BPF_M_FHLEN);
 	bp++;
-	BPF_SET_STMT(bp, BPF_LDX + BPF_MEM, 2);
+	BPF_SET_STMT(bp, BPF_LDX + BPF_MEM, BPF_M_IPLEN);
 	bp++;
 	BPF_SET_STMT(bp, BPF_ALU + BPF_ADD + BPF_X, 0);
 	bp++;
Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.10 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.11
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.10	Fri Jul 26 10:53:45 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c	Tue Jul 30 10:25:03 2019
@@ -1938,6 +1938,7 @@ dhcp6_checkstatusok(const struct interfa
 	if ((opt = f(farg, len, D6_OPTION_STATUS_CODE, &opt_len)) == NULL) {
 		//logdebugx("%s: no status", ifp->name);
 		state->lerror = 0;
+		errno = ESRCH;
 		return 0;
 	}
 
@@ -1949,7 +1950,8 @@ dhcp6_checkstatusok(const struct interfa
 	code = ntohs(code);
 	if (code == D6_STATUS_OK) {
 		state->lerror = 0;
-		return 1;
+		errno = 0;
+		return 0;
 	}
 
 	/* Anything after the code is a message. */
@@ -1980,7 +1982,8 @@ dhcp6_checkstatusok(const struct interfa
 	logfunc("%s: DHCPv6 REPLY: %s", ifp->name, status);
 	free(sbuf);
 	state->lerror = code;
-	return -1;
+	errno = 0;
+	return (int)code;
 }
 
 const struct ipv6_addr *
@@ -2227,7 +2230,7 @@ dhcp6_findia(struct interface *ifp, stru
 	struct dhcp6_option o;
 	uint8_t *d, *p;
 	struct dhcp6_ia_na ia;
-	int i, e;
+	int i, e, error;
 	size_t j;
 	uint16_t nl;
 	uint8_t iaid[4];
@@ -2316,7 +2319,9 @@ dhcp6_findia(struct interface *ifp, stru
 			}
 		} else
 			ia.t1 = ia.t2 = 0; /* appease gcc */
-		if (dhcp6_checkstatusok(ifp, NULL, p, o.len) == -1) {
+		if ((error = dhcp6_checkstatusok(ifp, NULL, p, o.len)) != 0) {
+			if (error == D6_STATUS_NOBINDING)
+				state->has_no_binding = true;
 			e = 1;
 			continue;
 		}
@@ -2417,7 +2422,7 @@ dhcp6_validatelease(struct interface *if
     const char *sfrom, const struct timespec *acquired)
 {
 	struct dhcp6_state *state;
-	int ok, nia;
+	int nia, ok_errno;
 	struct timespec aq;
 
 	if (len <= sizeof(*m)) {
@@ -2426,8 +2431,10 @@ dhcp6_validatelease(struct interface *if
 	}
 
 	state = D6_STATE(ifp);
-	if ((ok = dhcp6_checkstatusok(ifp, m, NULL, len) == -1))
+	errno = 0;
+	if (dhcp6_checkstatusok(ifp, m, NULL, len) != 0)
 		return -1;
+	ok_errno = errno;
 
 	state->renew = state->rebind = state->expire = 0;
 	state->lowpl = ND6_INFINITE_LIFETIME;
@@ -2435,9 +2442,10 @@ dhcp6_validatelease(struct interface *if
 		clock_gettime(CLOCK_MONOTONIC, &aq);
 		acquired = &aq;
 	}
+	state->has_no_binding = false;
 	nia = dhcp6_findia(ifp, m, len, sfrom, acquired);
 	if (nia == 0) {
-		if (state->state != DH6S_CONFIRM && ok != 1) {
+		if (state->state != DH6S_CONFIRM && ok_errno != 0) {
 			logerrx("%s: no useable IA found in lease", ifp->name);
 			return -1;
 		}
@@ -2447,6 +2455,7 @@ dhcp6_validatelease(struct interface *if
 		 * IA's must have existed here otherwise we would
 		 * have rejected it earlier. */
 		assert(state->new != NULL && state->new_len != 0);
+		state->has_no_binding = false;
 		nia = dhcp6_findia(ifp, state->new, state->new_len,
 		    sfrom, acquired);
 	}
@@ -3269,7 +3278,7 @@ dhcp6_recvif(struct interface *ifp, cons
 	case DHCP6_REPLY:
 		switch(state->state) {
 		case DH6S_INFORM:
-			if (dhcp6_checkstatusok(ifp, r, NULL, len) == -1)
+			if (dhcp6_checkstatusok(ifp, r, NULL, len) != 0)
 				return;
 			break;
 		case DH6S_CONFIRM:
@@ -3317,6 +3326,14 @@ dhcp6_recvif(struct interface *ifp, cons
 					dhcp6_startdiscover(ifp);
 				return;
 			}
+			/* RFC8415 18.2.10.1 */
+			if ((state->state == DH6S_RENEW ||
+			    state->state == DH6S_REBIND) &&
+			    state->has_no_binding)
+			{
+				dhcp6_startrequest(ifp);
+				return;
+			}
 			if (state->state == DH6S_DISCOVER)
 				state->state = DH6S_REQUEST;
 			break;

Index: src/external/bsd/dhcpcd/dist/src/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.22 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.23
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.22	Fri Jul 26 10:47:29 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c	Tue Jul 30 10:25:03 2019
@@ -3220,70 +3220,80 @@ rapidcommit:
 }
 
 static void *
-get_udp_data(void *udp, size_t *len)
+get_udp_data(void *packet, size_t *len)
 {
-	struct bootp_pkt *p;
-
-	p = (struct bootp_pkt *)udp;
-	*len = (size_t)ntohs(p->ip.ip_len) - sizeof(p->ip) - sizeof(p->udp);
-	return (char *)udp + offsetof(struct bootp_pkt, bootp);
+	const struct ip *ip = packet;
+	size_t ip_hl = (size_t)ip->ip_hl * 4;
+	char *p = packet;
+
+	p += ip_hl + sizeof(struct udphdr);
+	*len = (size_t)ntohs(ip->ip_len) - sizeof(struct udphdr) - ip_hl;
+	return p;
 }
 
 static int
-valid_udp_packet(void *data, size_t data_len, struct in_addr *from,
-    int noudpcsum)
+valid_udp_packet(void *packet, size_t plen, struct in_addr *from,
+	unsigned int flags)
 {
-	struct bootp_pkt *p;
-	uint16_t bytes;
+	struct ip *ip = packet;
+	char ip_hlv = *(char *)ip;
+	size_t ip_hlen;
+	uint16_t ip_len, uh_sum;
+	struct udphdr *udp;
 
-	if (data_len < sizeof(p->ip)) {
-		if (from)
+	if (plen < sizeof(*ip)) {
+		if (from != NULL)
 			from->s_addr = INADDR_ANY;
 		errno = ERANGE;
 		return -1;
 	}
-	p = (struct bootp_pkt *)data;
-	if (from)
-		from->s_addr = p->ip.ip_src.s_addr;
-	if (checksum(&p->ip, sizeof(p->ip)) != 0) {
+
+	if (from != NULL)
+		from->s_addr = ip->ip_src.s_addr;
+
+	ip_hlen = (size_t)ip->ip_hl * 4;
+	if (checksum(ip, ip_hlen) != 0) {
 		errno = EINVAL;
 		return -1;
 	}
 
-	bytes = ntohs(p->ip.ip_len);
+	ip_len = ntohs(ip->ip_len);
 	/* Check we have a payload */
-	if (bytes <= sizeof(p->ip) + sizeof(p->udp)) {
+	if (ip_len <= ip_hlen + sizeof(*udp)) {
 		errno = ERANGE;
 		return -1;
 	}
 	/* Check we don't go beyond the payload */
-	if (bytes > data_len) {
+	if (ip_len > plen) {
 		errno = ENOBUFS;
 		return -1;
 	}
 
-	if (noudpcsum == 0) {
-		uint16_t udpsum, iplen;
+	if (flags & BPF_PARTIALCSUM)
+		return 0;
+
+	udp = (struct udphdr *)((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. */
-		iplen = p->ip.ip_len;
-		udpsum = p->udp.uh_sum;
-		p->udp.uh_sum = 0;
-		p->ip.ip_hl = 0;
-		p->ip.ip_v = 0;
-		p->ip.ip_tos = 0;
-		p->ip.ip_len = p->udp.uh_ulen;
-		p->ip.ip_id = 0;
-		p->ip.ip_off = 0;
-		p->ip.ip_ttl = 0;
-		p->ip.ip_sum = 0;
-		if (udpsum && checksum(p, bytes) != udpsum) {
-			errno = EINVAL;
-			return -1;
-		}
-		p->ip.ip_len = iplen;
+	/* This does scribble on the packet, but at this point
+	 * we don't care to keep it. */
+	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) {
+		errno = EINVAL;
+		return -1;
 	}
+	*(char *)ip = ip_hlv;
+	ip->ip_len = htons(ip_len);
 
 	return 0;
 }
@@ -3320,9 +3330,7 @@ dhcp_handlepacket(struct interface *ifp,
 	size_t udp_len;
 	const struct dhcp_state *state = D_CSTATE(ifp);
 
-	if (valid_udp_packet(data, len, &from,
-			     state->bpf_flags & RAW_PARTIALCSUM) == -1)
-	{
+	if (valid_udp_packet(data, len, &from, state->bpf_flags) == -1) {
 		if (errno == EINVAL)
 			logerrx("%s: checksum failure from %s",
 			  ifp->name, inet_ntoa(from));
@@ -3384,6 +3392,7 @@ dhcp_readpacket(void *arg)
 static void
 dhcp_readudp(struct dhcpcd_ctx *ctx, struct interface *ifp)
 {
+	const struct dhcp_state *state;
 	struct sockaddr_in from;
 	unsigned char buf[10 * 1024]; /* Maximum MTU */
 	struct iovec iov = {
@@ -3405,8 +3414,7 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, str
 	ssize_t bytes;
 
 	if (ifp != NULL) {
-		const struct dhcp_state *state = D_CSTATE(ifp);
-
+		state = D_CSTATE(ifp);
 		s = state->udp_fd;
 	} else
 		s = ctx->udp_fd;
@@ -3426,13 +3434,19 @@ dhcp_readudp(struct dhcpcd_ctx *ctx, str
 			logerr(__func__);
 			return;
 		}
-		if (D_CSTATE(ifp) == NULL) {
+		state = D_CSTATE(ifp);
+		if (state == NULL) {
 			logdebugx("%s: received BOOTP for inactive interface",
 			    ifp->name);
 			return;
 		}
 	}
 
+	if (state->bpf_fd != -1) {
+		/* Avoid a duplicate read if BPF is open for the interface. */
+		return;
+	}
+
 	dhcp_handlebootp(ifp, (struct bootp *)(void *)buf, (size_t)bytes,
 	    &from.sin_addr);
 #endif
Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.22 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.23
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.22	Thu Jul 25 08:55:18 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c	Tue Jul 30 10:25:03 2019
@@ -2125,13 +2125,13 @@ exit1:
 		}
 		free(ctx.ifaces);
 	}
+	free_options(&ctx, ifo);
 #ifdef HAVE_OPEN_MEMSTREAM
 	if (ctx.script_fp)
 		fclose(ctx.script_fp);
 #endif
 	free(ctx.script_buf);
 	free(ctx.script_env);
-	free_options(&ctx, ifo);
 	rt_dispose(&ctx);
 	free(ctx.duid);
 	if (ctx.link_fd != -1) {

Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.9 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.10
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.9	Wed Jul 24 09:57:43 2019
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c	Tue Jul 30 10:25:03 2019
@@ -51,6 +51,8 @@
 #include <netinet6/nd6.h>
 #ifdef __NetBSD__
 #include <net/if_vlanvar.h> /* Needs netinet/if_ether.h */
+#elif defined(__DragonFly__)
+#include <net/vlan/if_vlan_var.h>
 #else
 #include <net/if_vlan_var.h>
 #endif
@@ -541,7 +543,7 @@ if_route(unsigned char cmd, const struct
  * try to encourage someone to fix that by logging a waring during compile.
  */
 #if defined(__FreeBSD__) || defined(__OpenBSD__)
-#warning OS does not allow IPv6 address sharing
+#warning kernel does not allow IPv6 address sharing
 			if (!gateway_unspec || rt->rt_dest.sa_family!=AF_INET6)
 #endif
 			rtm->rtm_addrs |= RTA_IFP;
Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.9 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.10
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.9	Fri Jul 26 10:53:45 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c	Tue Jul 30 10:25:03 2019
@@ -434,13 +434,7 @@ ipv6nd_sendadvertisement(void *arg)
 	s = ctx->nd_fd;
 #endif
 	if (sendmsg(s, &msg, 0) == -1)
-#ifdef __OpenBSD__
-/* This isn't too critical as they don't support IPv6 address sharing */
-#warning Cannot send NA messages on OpenBSD
-		logdebug(__func__);
-#else
 		logerr(__func__);
-#endif
 
 	if (++ia->na_count < MAX_NEIGHBOR_ADVERTISEMENT) {
 		eloop_timeout_add_sec(ctx->eloop,
@@ -527,6 +521,8 @@ ipv6nd_advertise(struct ipv6_addr *ia)
 	eloop_timeout_delete(ctx->eloop, ipv6nd_sendadvertisement, iaf);
 	ipv6nd_sendadvertisement(iaf);
 }
+#elif !defined(SMALL)
+#warning kernel does not support userland sending ND6 advertisements
 #endif /* ND6_ADVERTISE */
 
 static void

Index: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.15 src/external/bsd/dhcpcd/dist/src/if-options.c:1.16
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.15	Wed Jul 24 09:57:43 2019
+++ src/external/bsd/dhcpcd/dist/src/if-options.c	Tue Jul 30 10:25:03 2019
@@ -2611,73 +2611,92 @@ void
 free_options(struct dhcpcd_ctx *ctx, struct if_options *ifo)
 {
 	size_t i;
+#ifdef RT_FREE_ROUTE_TABLE
+	struct interface *ifp;
+	struct rt *rt;
+#endif
 	struct dhcp_opt *opt;
 	struct vivco *vo;
 #ifdef AUTH
 	struct token *token;
 #endif
 
-	if (ifo) {
-		if (ifo->environ) {
-			i = 0;
-			while (ifo->environ[i])
-				free(ifo->environ[i++]);
-			free(ifo->environ);
-		}
-		if (ifo->config) {
-			i = 0;
-			while (ifo->config[i])
-				free(ifo->config[i++]);
-			free(ifo->config);
+	if (ifo == NULL)
+		return;
+
+	if (ifo->environ) {
+		i = 0;
+		while (ifo->environ[i])
+			free(ifo->environ[i++]);
+		free(ifo->environ);
+	}
+	if (ifo->config) {
+		i = 0;
+		while (ifo->config[i])
+			free(ifo->config[i++]);
+		free(ifo->config);
+	}
+
+#ifdef RT_FREE_ROUTE_TABLE
+	/* Stupidly, we don't know the interface when creating the options.
+	 * As such, make sure each route has one so they can goto the
+	 * free list. */
+	ifp = ctx->ifaces != NULL ? TAILQ_FIRST(ctx->ifaces) : NULL;
+	if (ifp != NULL) {
+		RB_TREE_FOREACH(rt, &ifo->routes) {
+			if (rt->rt_ifp == NULL)
+				rt->rt_ifp = ifp;
 		}
-		rt_headclear0(ctx, &ifo->routes, AF_UNSPEC);
-		if (ifo->script != default_script)
-			free(ifo->script);
-		free(ifo->arping);
-		free(ifo->blacklist);
-		free(ifo->fallback);
-
-		for (opt = ifo->dhcp_override;
-		    ifo->dhcp_override_len > 0;
-		    opt++, ifo->dhcp_override_len--)
-			free_dhcp_opt_embenc(opt);
-		free(ifo->dhcp_override);
-		for (opt = ifo->nd_override;
-		    ifo->nd_override_len > 0;
-		    opt++, ifo->nd_override_len--)
-			free_dhcp_opt_embenc(opt);
-		free(ifo->nd_override);
-		for (opt = ifo->dhcp6_override;
-		    ifo->dhcp6_override_len > 0;
-		    opt++, ifo->dhcp6_override_len--)
-			free_dhcp_opt_embenc(opt);
-		free(ifo->dhcp6_override);
-		for (vo = ifo->vivco;
-		    ifo->vivco_len > 0;
-		    vo++, ifo->vivco_len--)
-			free(vo->data);
-		free(ifo->vivco);
-		for (opt = ifo->vivso_override;
-		    ifo->vivso_override_len > 0;
-		    opt++, ifo->vivso_override_len--)
-			free_dhcp_opt_embenc(opt);
-		free(ifo->vivso_override);
+	}
+#endif
+	rt_headclear0(ctx, &ifo->routes, AF_UNSPEC);
+
+	if (ifo->script != default_script)
+		free(ifo->script);
+	free(ifo->arping);
+	free(ifo->blacklist);
+	free(ifo->fallback);
+
+	for (opt = ifo->dhcp_override;
+	    ifo->dhcp_override_len > 0;
+	    opt++, ifo->dhcp_override_len--)
+		free_dhcp_opt_embenc(opt);
+	free(ifo->dhcp_override);
+	for (opt = ifo->nd_override;
+	    ifo->nd_override_len > 0;
+	    opt++, ifo->nd_override_len--)
+		free_dhcp_opt_embenc(opt);
+	free(ifo->nd_override);
+	for (opt = ifo->dhcp6_override;
+	    ifo->dhcp6_override_len > 0;
+	    opt++, ifo->dhcp6_override_len--)
+		free_dhcp_opt_embenc(opt);
+	free(ifo->dhcp6_override);
+	for (vo = ifo->vivco;
+	    ifo->vivco_len > 0;
+	    vo++, ifo->vivco_len--)
+		free(vo->data);
+	free(ifo->vivco);
+	for (opt = ifo->vivso_override;
+	    ifo->vivso_override_len > 0;
+	    opt++, ifo->vivso_override_len--)
+		free_dhcp_opt_embenc(opt);
+	free(ifo->vivso_override);
 
 #if defined(INET6) && !defined(SMALL)
-		for (; ifo->ia_len > 0; ifo->ia_len--)
-			free(ifo->ia[ifo->ia_len - 1].sla);
+	for (; ifo->ia_len > 0; ifo->ia_len--)
+		free(ifo->ia[ifo->ia_len - 1].sla);
 #endif
-		free(ifo->ia);
+	free(ifo->ia);
 
 #ifdef AUTH
-		while ((token = TAILQ_FIRST(&ifo->auth.tokens))) {
-			TAILQ_REMOVE(&ifo->auth.tokens, token, next);
-			if (token->realm_len)
-				free(token->realm);
-			free(token->key);
-			free(token);
-		}
-#endif
-		free(ifo);
+	while ((token = TAILQ_FIRST(&ifo->auth.tokens))) {
+		TAILQ_REMOVE(&ifo->auth.tokens, token, next);
+		if (token->realm_len)
+			free(token->realm);
+		free(token->key);
+		free(token);
 	}
+#endif
+	free(ifo);
 }

Index: src/external/bsd/dhcpcd/dist/src/ipv6.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6.c:1.2 src/external/bsd/dhcpcd/dist/src/ipv6.c:1.3
--- src/external/bsd/dhcpcd/dist/src/ipv6.c:1.2	Fri Jul 26 10:53:45 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6.c	Tue Jul 30 10:25:03 2019
@@ -634,6 +634,15 @@ ipv6_addaddr1(struct ipv6_addr *ia, cons
 #ifdef __sun
 	struct ipv6_state *state;
 	struct ipv6_addr *ia2;
+
+	/* If we re-add then address on Solaris then the prefix
+	 * route will be scrubbed and re-added. Something might
+	 * be using it, so let's avoid it. */
+	if (ia->flags & IPV6_AF_DADCOMPLETED) {
+		logdebugx("%s: IP address %s already exists",
+		    ia->iface->name, ia->saddr);
+		return 0;
+	}
 #endif
 
 	/* Remember the interface of the address. */
@@ -1187,6 +1196,8 @@ out:
 	/* Done with the ia now, so free it. */
 	if (cmd == RTM_DELADDR)
 		ipv6_freeaddr(ia);
+	else if (!(ia->addr_flags & IN6_IFF_NOTUSEABLE))
+		ia->flags |= IPV6_AF_DADCOMPLETED;
 }
 
 int
@@ -1465,8 +1476,10 @@ ipv6_newaddr(struct interface *ifp, cons
 		goto err;
 
 	ia->iface = ifp;
-	ia->flags = IPV6_AF_NEW | flags;
 	ia->addr_flags = addr_flags;
+	ia->flags = IPV6_AF_NEW | flags;
+	if (!(ia->addr_flags & IN6_IFF_NOTUSEABLE))
+		ia->flags |= IPV6_AF_DADCOMPLETED;
 	ia->prefix_len = prefix_len;
 	ia->dhcp6_fd = -1;
 
Index: src/external/bsd/dhcpcd/dist/src/ipv6.h
diff -u src/external/bsd/dhcpcd/dist/src/ipv6.h:1.2 src/external/bsd/dhcpcd/dist/src/ipv6.h:1.3
--- src/external/bsd/dhcpcd/dist/src/ipv6.h:1.2	Fri Jul 26 10:53:45 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6.h	Tue Jul 30 10:25:03 2019
@@ -149,7 +149,13 @@
 #  define IN6_IFF_DETACHED	0
 #endif
 
-#ifndef SMALL
+/*
+ * 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.
+ */
+#if !defined(SMALL) && (defined(__NetBSD__) || defined(__linux__))
 #  define ND6_ADVERTISE
 #endif
 

Reply via email to