Module Name:    src
Committed By:   roy
Date:           Fri Oct 11 11:03:59 UTC 2019

Modified Files:
        src/external/bsd/dhcpcd/dist/src: bpf.c dhcp.c dhcp6.c dhcpcd.8.in
            dhcpcd.c if-bsd.c if-options.c

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/external/bsd/dhcpcd/dist/src/bpf.c \
    src/external/bsd/dhcpcd/dist/src/dhcp6.c
cvs rdiff -u -r1.27 -r1.28 src/external/bsd/dhcpcd/dist/src/dhcp.c
cvs rdiff -u -r1.3 -r1.4 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in
cvs rdiff -u -r1.26 -r1.27 src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.13 -r1.14 src/external/bsd/dhcpcd/dist/src/if-bsd.c
cvs rdiff -u -r1.17 -r1.18 src/external/bsd/dhcpcd/dist/src/if-options.c

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

Modified files:

Index: src/external/bsd/dhcpcd/dist/src/bpf.c
diff -u src/external/bsd/dhcpcd/dist/src/bpf.c:1.12 src/external/bsd/dhcpcd/dist/src/bpf.c:1.13
--- src/external/bsd/dhcpcd/dist/src/bpf.c:1.12	Wed Aug 21 17:12:19 2019
+++ src/external/bsd/dhcpcd/dist/src/bpf.c	Fri Oct 11 11:03:59 2019
@@ -410,13 +410,7 @@ bpf_cmp_hwaddr(struct bpf_insn *bpf, siz
 #endif
 
 #ifdef ARP
-
 static const struct bpf_insn bpf_arp_ether [] = {
-	/* Ensure packet is at least correct size. */
-	BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),
-	BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ether_arp), 1, 0),
-	BPF_STMT(BPF_RET + BPF_K, 0),
-
 	/* Check this is an ARP packet. */
 	BPF_STMT(BPF_LD + BPF_H + BPF_ABS,
 	         offsetof(struct ether_header, ether_type)),
@@ -552,17 +546,8 @@ 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
-
 #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
@@ -574,13 +559,14 @@ static const struct bpf_insn bpf_bootp_e
 	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 1, 0),
 	BPF_STMT(BPF_RET + BPF_K, 0),
 
-	/* Load frame header length into X. */
-	BPF_STMT(BPF_LDX + BPF_W + BPF_IMM, sizeof(struct ether_header)),
-	/* Copy frame header length to memory */
-	BPF_STMT(BPF_STX, BPF_M_FHLEN),
+	/* Advance to the IP header. */
+	BPF_STMT(BPF_LDX + BPF_K, sizeof(struct ether_header)),
 };
 #define BPF_BOOTP_ETHER_LEN	__arraycount(bpf_bootp_ether)
 
+#define BOOTP_MIN_SIZE		sizeof(struct ip) + sizeof(struct udphdr) + \
+				sizeof(struct bootp)
+
 static const struct bpf_insn bpf_bootp_filter[] = {
 	/* Make sure it's an IPv4 packet. */
 	BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0),
@@ -588,15 +574,6 @@ static const struct bpf_insn bpf_bootp_f
 	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_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)),
 	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 1, 0),
@@ -607,49 +584,17 @@ 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 length. */
-	BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct ip, ip_len)),
-	BPF_STMT(BPF_ST, BPF_M_IPLEN),
-
 	/* Advance to the UDP header. */
-	BPF_STMT(BPF_LD + BPF_MEM, BPF_M_IPHLEN),
+	BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0),
+	BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x0f),
+	BPF_STMT(BPF_ALU + BPF_MUL + BPF_K, 4),
 	BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0),
 	BPF_STMT(BPF_MISC + BPF_TAX, 0),
 
-	/* 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. */
-	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 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. */
-	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),
-
-	/* Make sure it's BOOTREPLY. */
-	BPF_STMT(BPF_LD + BPF_B + BPF_IND, offsetof(struct bootp, op)),
-	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTREPLY, 1, 0),
-	BPF_STMT(BPF_RET + BPF_K, 0),
 };
 
 #define BPF_BOOTP_FILTER_LEN	__arraycount(bpf_bootp_filter)
@@ -729,14 +674,8 @@ bpf_bootp(struct interface *ifp, int fd)
 	}
 #endif
 
-	/* 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, BPF_M_IPLEN);
-	bp++;
-	BPF_SET_STMT(bp, BPF_ALU + BPF_ADD + BPF_X, 0);
-	bp++;
-	BPF_SET_STMT(bp, BPF_RET + BPF_A, 0);
+	/* All passed, return the packet. */
+	BPF_SET_STMT(bp, BPF_RET + BPF_K, BPF_WHOLEPACKET);
 	bp++;
 
 	return bpf_attach(fd, bpf, (unsigned int)(bp - bpf));
Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.12 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.13
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.12	Wed Sep  4 13:28:56 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c	Fri Oct 11 11:03:59 2019
@@ -532,13 +532,6 @@ dhcp6_delegateaddr(struct in6_addr *addr
 		asla.prefix_len = 0;
 		asla.sla_set = 0;
 		sla = &asla;
-	} else if (sla->sla == 0 && sla->prefix_len == 0) {
-		/* An SLA of 0 was set with no prefix length specified.
-		 * This means we delegate the whole prefix. */
-		asla.sla = sla->sla;
-		asla.prefix_len = prefix->prefix_len;
-		asla.sla_set = 0;
-		sla = &asla;
 	} else if (sla->prefix_len == 0) {
 		/* An SLA was given, but prefix length was not.
 		 * We need to work out a suitable prefix length for
@@ -680,27 +673,21 @@ dhcp6_makemessage(struct interface *ifp)
 					break;
 			}
 			if (n < ifo->dhcp6_override_len)
-			    continue;
-			if (!(opt->type & OT_NOREQ) &&
-			    (opt->type & OT_REQUEST ||
-			    has_option_mask(ifo->requestmask6, opt->option)))
-			{
-				n_options++;
-				len += sizeof(o.len);
-			}
+				continue;
+			if (!DHC_REQOPT(opt, ifo->requestmask6, ifo->nomask6))
+				continue;
+			n_options++;
+			len += sizeof(o.len);
 		}
 #ifndef SMALL
 		for (l = 0, opt = ifo->dhcp6_override;
 		    l < ifo->dhcp6_override_len;
 		    l++, opt++)
 		{
-			if (!(opt->type & OT_NOREQ) &&
-			    (opt->type & OT_REQUEST ||
-			    has_option_mask(ifo->requestmask6, opt->option)))
-			{
-				n_options++;
-				len += sizeof(o.len);
-			}
+			if (!DHC_REQOPT(opt, ifo->requestmask6, ifo->nomask6))
+				continue;
+			n_options++;
+			len += sizeof(o.len);
 		}
 		if (dhcp6_findselfsla(ifp)) {
 			n_options++;
@@ -1037,7 +1024,8 @@ dhcp6_makemessage(struct interface *ifp)
 
 #ifdef AUTH
 		if ((ifo->auth.options & DHCPCD_AUTH_SENDREQUIRE) !=
-		    DHCPCD_AUTH_SENDREQUIRE)
+		    DHCPCD_AUTH_SENDREQUIRE &&
+		    !has_option_mask(ifo->nomask6, D6_OPTION_RECONF_ACCEPT))
 			COPYIN1(D6_OPTION_RECONF_ACCEPT, 0);
 #endif
 
@@ -1060,34 +1048,26 @@ dhcp6_makemessage(struct interface *ifp)
 				if (n < ifo->dhcp6_override_len)
 				    continue;
 #endif
-				if (!(opt->type & OT_NOREQ) &&
-				    (opt->type & OT_REQUEST ||
-				    has_option_mask(ifo->requestmask6,
-				        opt->option)))
-				{
-					o.code = htons((uint16_t)opt->option);
-					memcpy(p, &o.code, sizeof(o.code));
-					p += sizeof(o.code);
-					o.len = (uint16_t)
-					    (o.len + sizeof(o.code));
-				}
+				if (!DHC_REQOPT(opt, ifo->requestmask6,
+				    ifo->nomask6))
+					continue;
+				o.code = htons((uint16_t)opt->option);
+				memcpy(p, &o.code, sizeof(o.code));
+				p += sizeof(o.code);
+				o.len = (uint16_t)(o.len + sizeof(o.code));
 			}
 #ifndef SMALL
 			for (l = 0, opt = ifo->dhcp6_override;
 			    l < ifo->dhcp6_override_len;
 			    l++, opt++)
 			{
-				if (!(opt->type & OT_NOREQ) &&
-				    (opt->type & OT_REQUEST ||
-				    has_option_mask(ifo->requestmask6,
-				        opt->option)))
-				{
-					o.code = htons((uint16_t)opt->option);
-					memcpy(p, &o.code, sizeof(o.code));
-					p += sizeof(o.code);
-					o.len = (uint16_t)
-					    (o.len + sizeof(o.code));
-				}
+				if (!DHC_REQOPT(opt, ifo->requestmask6,
+				    ifo->nomask6))
+					continue;
+				o.code = htons((uint16_t)opt->option);
+				memcpy(p, &o.code, sizeof(o.code));
+				p += sizeof(o.code);
+				o.len = (uint16_t)(o.len + sizeof(o.code));
 			}
 			if (dhcp6_findselfsla(ifp)) {
 				o.code = htons(D6_OPTION_PD_EXCLUDE);
@@ -3008,7 +2988,9 @@ dhcp6_bind(struct interface *ifp, const 
 			TAILQ_FOREACH(ia, &state->addrs, next) {
 				if (ia->flags & IPV6_AF_STALE)
 					continue;
-				if (ia->prefix_vltime <= state->renew)
+				if (!(state->renew == ND6_INFINITE_LIFETIME &&
+				    ia->prefix_vltime == ND6_INFINITE_LIFETIME)
+				    && ia->prefix_vltime <= state->renew)
 					logwarnx(
 					    "%s: %s will expire before renewal",
 					    ifp->name, ia->saddr);
@@ -3152,6 +3134,8 @@ dhcp6_bind(struct interface *ifp, const 
 		if (state->state == DH6S_INFORMED)
 			lognewinfo("%s: refresh in %"PRIu32" seconds",
 			    ifp->name, state->renew);
+		else if (state->renew == ND6_INFINITE_LIFETIME)
+			lognewinfo("%s: leased for infinity", ifp->name);
 		else if (state->renew || state->rebind)
 			lognewinfo("%s: renew in %"PRIu32", "
 			    "rebind in %"PRIu32", "

Index: src/external/bsd/dhcpcd/dist/src/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.27 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.28
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.27	Fri Sep 13 11:54:03 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c	Fri Oct 11 11:03:59 2019
@@ -988,7 +988,8 @@ make_message(struct bootp **bootpm, cons
 
 #ifdef AUTH
 		if ((ifo->auth.options & DHCPCD_AUTH_SENDREQUIRE) !=
-		    DHCPCD_AUTH_SENDREQUIRE)
+		    DHCPCD_AUTH_SENDREQUIRE &&
+		    !has_option_mask(ifo->nomask, DHO_FORCERENEW_NONCE))
 		{
 			/* We support HMAC-MD5 */
 			AREA_CHECK(1);
@@ -1032,10 +1033,7 @@ make_message(struct bootp **bootpm, cons
 		    i < ifp->ctx->dhcp_opts_len;
 		    i++, opt++)
 		{
-			if (!(opt->type & OT_REQUEST ||
-			    has_option_mask(ifo->requestmask, opt->option)))
-				continue;
-			if (opt->type & OT_NOREQ)
+			if (!DHC_REQOPT(opt, ifo->requestmask, ifo->nomask))
 				continue;
 			if (type == DHCP_INFORM &&
 			    (opt->option == DHO_RENEWALTIME ||
@@ -1054,10 +1052,7 @@ make_message(struct bootp **bootpm, cons
 					break;
 			if (lp < p)
 				continue;
-			if (!(opt->type & OT_REQUEST ||
-			    has_option_mask(ifo->requestmask, opt->option)))
-				continue;
-			if (opt->type & OT_NOREQ)
+			if (!DHC_REQOPT(opt, ifo->requestmask, ifo->nomask))
 				continue;
 			if (type == DHCP_INFORM &&
 			    (opt->option == DHO_RENEWALTIME ||
@@ -1738,15 +1733,32 @@ send_message(struct interface *ifp, uint
 	if (r == -1)
 		goto fail;
 	len = (size_t)r;
-	from.s_addr = bootp->ciaddr;
-	if (from.s_addr != INADDR_ANY)
+
+	if (ipv4_iffindaddr(ifp, &state->lease.addr, NULL) != NULL)
+		from.s_addr = state->lease.addr.s_addr;
+	else
+		from.s_addr = INADDR_ANY;
+	if (from.s_addr != INADDR_ANY &&
+	    state->lease.server.s_addr != INADDR_ANY)
 		to.s_addr = state->lease.server.s_addr;
 	else
-		to.s_addr = INADDR_ANY;
+		to.s_addr = INADDR_BROADCAST;
 
-	/* If unicasting, try and avoid sending by BPF so we don't
-	 * use a L2 broadcast. */
-	if (to.s_addr != INADDR_ANY && to.s_addr != INADDR_BROADCAST) {
+	/*
+	 * If not listening on the unspecified address we can
+	 * only receive broadcast messages via BPF.
+	 * Sockets bound to an address cannot receive broadcast messages
+	 * even if they are setup to send them.
+	 * Broadcasting from UDP is only an optimisation for rebinding
+	 * and on BSD, at least, is reliant on the subnet route being
+	 * correctly configured to recieve the unicast reply.
+	 * As such, we always broadcast and receive the reply to it via BPF.
+	 * This also guarantees we have a DHCP server attached to the
+	 * interface we want to configure because we can't dictate the
+	 * interface via IP_PKTINFO unlike for IPv6.
+	 */
+	if (to.s_addr != INADDR_BROADCAST)
+	{
 		if (dhcp_sendudp(ifp, &to, bootp, len) != -1)
 			goto out;
 		logerr("%s: dhcp_sendudp", ifp->name);
@@ -2001,30 +2013,44 @@ dhcp_finish_dad(struct interface *ifp, s
 }
 
 
-static void
+static bool
 dhcp_addr_duplicated(struct interface *ifp, struct in_addr *ia)
 {
 	struct dhcp_state *state = D_STATE(ifp);
+	unsigned long long opts = ifp->options->options;
+	struct dhcpcd_ctx *ctx = ifp->ctx;
+	bool deleted = false;
 #ifdef IN_IFF_DUPLICATED
 	struct ipv4_addr *iap;
 #endif
 
 	if ((state->offer == NULL || state->offer->yiaddr != ia->s_addr) &&
 	    !IN_ARE_ADDR_EQUAL(ia, &state->lease.addr))
-		return;
+		return deleted;
 
 	/* RFC 2131 3.1.5, Client-server interaction */
 	logerrx("%s: DAD detected %s", ifp->name, inet_ntoa(*ia));
 	unlink(state->leasefile);
-	if (!(ifp->options->options & DHCPCD_STATIC) && !state->lease.frominfo)
+	if (!(opts & DHCPCD_STATIC) && !state->lease.frominfo)
 		dhcp_decline(ifp);
 #ifdef IN_IFF_DUPLICATED
-	if ((iap = ipv4_iffindaddr(ifp, ia, NULL)) != NULL)
+	if ((iap = ipv4_iffindaddr(ifp, ia, NULL)) != NULL) {
 		ipv4_deladdr(iap, 0);
+		deleted = true;
+	}
 #endif
-	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+	eloop_timeout_delete(ctx->eloop, NULL, ifp);
+	if (opts & (DHCPCD_STATIC | DHCPCD_INFORM)) {
+		state->reason = "EXPIRE";
+		script_runreason(ifp, state->reason);
+#define NOT_ONLY_SELF (DHCPCD_MASTER | DHCPCD_IPV6RS | DHCPCD_DHCP6)
+		if (!(ctx->options & NOT_ONLY_SELF))
+			eloop_exit(ifp->ctx->eloop, EXIT_FAILURE);
+		return deleted;
+	}
 	eloop_timeout_add_sec(ifp->ctx->eloop,
 	    DHCP_RAND_MAX, dhcp_discover, ifp);
+	return deleted;
 }
 #endif
 
@@ -2362,7 +2388,9 @@ dhcp_arp_address(struct interface *ifp)
 			/* Add the address now, let the kernel handle DAD. */
 			ipv4_addaddr(ifp, &l.addr, &l.mask, &l.brd,
 			    l.leasetime, l.rebindtime);
-		} else
+		} else if (ia->addr_flags & IN_IFF_DUPLICATED)
+			dhcp_addr_duplicated(ifp, &ia->addr);
+		else
 			loginfox("%s: waiting for DAD on %s",
 			    ifp->name, inet_ntoa(addr));
 		return 0;
@@ -2841,14 +2869,18 @@ dhcp_handledhcp(struct interface *ifp, s
 #define LOGDHCP(l, m) \
 	log_dhcp((l), (m), ifp, bootp, bootp_len, from, 1)
 
+#define IS_STATE_ACTIVE(s) ((s)-state != DHS_NONE && \
+	(s)->state != DHS_INIT && (s)->state != DHS_BOUND)
+
 	if (bootp->op != BOOTREPLY) {
-		logdebugx("%s: op (%d) is not BOOTREPLY",
-		    ifp->name, bootp->op);
+		if (IS_STATE_ACTIVE(state))
+			logdebugx("%s: op (%d) is not BOOTREPLY",
+			    ifp->name, bootp->op);
 		return;
 	}
 
 	if (state->xid != ntohl(bootp->xid)) {
-		if (state->state != DHS_BOUND && state->state != DHS_NONE)
+		if (IS_STATE_ACTIVE(state))
 			logdebugx("%s: wrong xid 0x%x (expecting 0x%x) from %s",
 			    ifp->name, ntohl(bootp->xid), state->xid,
 			    inet_ntoa(*from));
@@ -2859,12 +2891,14 @@ dhcp_handledhcp(struct interface *ifp, s
 	if (ifp->hwlen <= sizeof(bootp->chaddr) &&
 	    memcmp(bootp->chaddr, ifp->hwaddr, ifp->hwlen))
 	{
-		char buf[sizeof(bootp->chaddr) * 3];
+		if (IS_STATE_ACTIVE(state)) {
+			char buf[sizeof(bootp->chaddr) * 3];
 
-		logdebugx("%s: xid 0x%x is for hwaddr %s",
-		    ifp->name, ntohl(bootp->xid),
-		    hwaddr_ntoa(bootp->chaddr, sizeof(bootp->chaddr),
-		    buf, sizeof(buf)));
+			logdebugx("%s: xid 0x%x is for hwaddr %s",
+			    ifp->name, ntohl(bootp->xid),
+			    hwaddr_ntoa(bootp->chaddr, sizeof(bootp->chaddr),
+				    buf, sizeof(buf)));
+		}
 		dhcp_redirect_dhcp(ifp, bootp, bootp_len, from);
 		return;
 	}
@@ -2959,10 +2993,7 @@ dhcp_handledhcp(struct interface *ifp, s
 	}
 
 	if (state->state == DHS_BOUND) {
-		/* Before we supported FORCERENEW we closed off the raw
-		 * port so we effectively ignored all messages.
-		 * As such we'll not log by default here. */
-		//LOGDHCP(logdebugx, "bound, ignoring");
+		LOGDHCP(logdebugx, "bound, ignoring");
 		return;
 	}
 
@@ -3239,9 +3270,40 @@ get_udp_data(void *packet, size_t *len)
 	return p;
 }
 
-static int
-valid_udp_packet(void *packet, size_t plen, struct in_addr *from,
-	unsigned int flags)
+static bool
+is_packet_udp_bootp(void *packet, size_t plen)
+{
+	struct ip *ip = packet;
+	size_t ip_hlen;
+	struct udphdr *udp;
+
+	if (sizeof(*ip) > plen)
+		return false;
+
+	if (ip->ip_v != IPVERSION || ip->ip_p != IPPROTO_UDP)
+		return false;
+
+	/* Sanity. */
+	if (ntohs(ip->ip_len) != plen)
+		return false;
+
+	ip_hlen = (size_t)ip->ip_hl * 4;
+	/* Check we have a UDP header and BOOTP. */
+	if (ip_hlen + sizeof(*udp) + offsetof(struct bootp, vend) > plen)
+		return false;
+
+	/* Check it's to and from the right ports. */
+	udp = (struct udphdr *)(void *)((char *)ip + ip_hlen);
+	if (udp->uh_dport != htons(BOOTPC) || udp->uh_sport != htons(BOOTPS))
+		return false;
+
+	return true;
+}
+
+/* Lengths have already been checked. */
+static bool
+checksums_valid(void *packet,
+    struct in_addr *from, unsigned int flags)
 {
 	struct ip *ip = packet;
 	struct ip pseudo_ip = {
@@ -3250,69 +3312,34 @@ valid_udp_packet(void *packet, size_t pl
 		.ip_dst = ip->ip_dst
 	};
 	size_t ip_hlen;
-	uint16_t ip_len, udp_len, uh_sum;
+	uint16_t udp_len, uh_sum;
 	struct udphdr *udp;
 	uint32_t csum;
 
-	if (plen < sizeof(*ip)) {
-		if (from != NULL)
-			from->s_addr = INADDR_ANY;
-		errno = ERANGE;
-		return -1;
-	}
-
 	if (from != NULL)
 		from->s_addr = ip->ip_src.s_addr;
 
-	/* Check we have the IP header */
 	ip_hlen = (size_t)ip->ip_hl * 4;
-	if (ip_hlen > plen) {
-		errno = ENOBUFS;
-		return -1;
-	}
+	if (in_cksum(ip, ip_hlen, NULL) != 0)
+		return false;
 
-	if (in_cksum(ip, ip_hlen, NULL) != 0) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	/* Check we have a payload */
-	ip_len = ntohs(ip->ip_len);
-	if (ip_len <= ip_hlen + sizeof(*udp)) {
-		errno = ERANGE;
-		return -1;
-	}
-	/* Check IP doesn't go beyond the payload */
-	if (ip_len > plen) {
-		errno = ENOBUFS;
-		return -1;
-	}
+	if (flags & BPF_PARTIALCSUM)
+		return 0;
 
-	/* Check UDP doesn't go beyond the payload */
 	udp = (struct udphdr *)(void *)((char *)ip + ip_hlen);
-	udp_len = ntohs(udp->uh_ulen);
-	if (udp_len > plen - ip_hlen) {
-		errno =  ENOBUFS;
-		return -1;
-	}
-
-	if (udp->uh_sum == 0 || flags & BPF_PARTIALCSUM)
+	if (udp->uh_sum == 0)
 		return 0;
 
 	/* UDP checksum is based on a pseudo IP header alongside
 	 * the UDP header and payload. */
+	udp_len = ntohs(udp->uh_ulen);
 	uh_sum = udp->uh_sum;
 	udp->uh_sum = 0;
 	pseudo_ip.ip_len = udp->uh_ulen;
 	csum = 0;
 	in_cksum(&pseudo_ip, sizeof(pseudo_ip), &csum);
 	csum = in_cksum(udp, udp_len, &csum);
-	if (csum != uh_sum) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	return 0;
+	return csum == uh_sum;
 }
 
 static void
@@ -3321,13 +3348,12 @@ dhcp_handlebootp(struct interface *ifp, 
 {
 	size_t v;
 
-	/* udp_len must be correct because the values are checked in
-	 * valid_udp_packet(). */
 	if (len < offsetof(struct bootp, vend)) {
 		logerrx("%s: truncated packet (%zu) from %s",
 		    ifp->name, len, inet_ntoa(*from));
 		return;
 	}
+
 	/* To make our IS_DHCP macro easy, ensure the vendor
 	 * area has at least 4 octets. */
 	v = len - offsetof(struct bootp, vend);
@@ -3340,21 +3366,24 @@ dhcp_handlebootp(struct interface *ifp, 
 }
 
 static void
-dhcp_handlepacket(struct interface *ifp, uint8_t *data, size_t len)
+dhcp_handlebpf(struct interface *ifp, uint8_t *data, size_t len)
 {
 	struct bootp *bootp;
 	struct in_addr from;
 	size_t udp_len;
 	const struct dhcp_state *state = D_CSTATE(ifp);
 
-	if (valid_udp_packet(data, len, &from, state->bpf_flags) == -1) {
-		const char *errstr;
+	/* Validate filter. */
+	if (!is_packet_udp_bootp(data, len)) {
+#ifdef BPF_DEBUG
+		logerrx("%s: DHCP BPF validation failure", ifp->name);
+#endif
+		return;
+	}
 
-		if (errno == EINVAL)
-			errstr = "checksum failure";
-		else
-			errstr = "invalid UDP packet";
-		logerrx("%s: %s from %s", errstr, ifp->name, inet_ntoa(from));
+	if (!checksums_valid(data, &from, state->bpf_flags)) {
+		logerrx("%s: checksum failure from %s",
+		    ifp->name, inet_ntoa(from));
 		return;
 	}
 
@@ -3370,7 +3399,7 @@ dhcp_handlepacket(struct interface *ifp,
 }
 
 static void
-dhcp_readpacket(void *arg)
+dhcp_readbpf(void *arg)
 {
 	struct interface *ifp = arg;
 	uint8_t buf[MTU_MAX];
@@ -3392,7 +3421,7 @@ dhcp_readpacket(void *arg)
 			}
 			break;
 		}
-		dhcp_handlepacket(ifp, buf, (size_t)bytes);
+		dhcp_handlebpf(ifp, buf, (size_t)bytes);
 		/* Check we still have a state after processing. */
 		if ((state = D_STATE(ifp)) == NULL)
 			break;
@@ -3505,7 +3534,7 @@ dhcp_openbpf(struct interface *ifp)
 	}
 
 	eloop_event_add(ifp->ctx->eloop,
-	    state->bpf_fd, dhcp_readpacket, ifp);
+	    state->bpf_fd, dhcp_readbpf, ifp);
 	return 0;
 }
 
@@ -3937,7 +3966,7 @@ dhcp_abort(struct interface *ifp)
 	}
 }
 
-void
+struct ipv4_addr *
 dhcp_handleifa(int cmd, struct ipv4_addr *ia, pid_t pid)
 {
 	struct interface *ifp;
@@ -3948,7 +3977,7 @@ dhcp_handleifa(int cmd, struct ipv4_addr
 	ifp = ia->iface;
 	state = D_STATE(ifp);
 	if (state == NULL || state->state == DHS_NONE)
-		return;
+		return ia;
 
 	if (cmd == RTM_DELADDR) {
 		if (state->addr == ia) {
@@ -3959,37 +3988,37 @@ dhcp_handleifa(int cmd, struct ipv4_addr
 			 * to drop the lease. */
 			dhcp_drop(ifp, "EXPIRE");
 			dhcp_start1(ifp);
+			return NULL;
 		}
-		return;
 	}
 
 	if (cmd != RTM_NEWADDR)
-		return;
+		return ia;
 
 #ifdef IN_IFF_NOTUSEABLE
 	if (!(ia->addr_flags & IN_IFF_NOTUSEABLE))
 		dhcp_finish_dad(ifp, &ia->addr);
 	else if (ia->addr_flags & IN_IFF_DUPLICATED)
-		dhcp_addr_duplicated(ifp, &ia->addr);
+		return dhcp_addr_duplicated(ifp, &ia->addr) ? NULL : ia;
 #endif
 
 	ifo = ifp->options;
 	if (ifo->options & DHCPCD_INFORM) {
 		if (state->state != DHS_INFORM)
 			dhcp_inform(ifp);
-		return;
+		return ia;
 	}
 
 	if (!(ifo->options & DHCPCD_STATIC))
-		return;
+		return ia;
 	if (ifo->req_addr.s_addr != INADDR_ANY)
-		return;
+		return ia;
 
 	free(state->old);
 	state->old = state->new;
 	state->new_len = dhcp_message_new(&state->new, &ia->addr, &ia->mask);
 	if (state->new == NULL)
-		return;
+		return ia;
 	if (ifp->flags & IFF_POINTOPOINT) {
 		for (i = 1; i < 255; i++)
 			if (i != DHO_ROUTER && has_option_mask(ifo->dstmask,i))
@@ -4005,4 +4034,6 @@ dhcp_handleifa(int cmd, struct ipv4_addr
 		state->addr = ia;
 		dhcp_inform(ifp);
 	}
+
+	return ia;
 }

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.3 src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.4
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in:1.3	Wed Sep  4 13:28:56 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.8.in	Fri Oct 11 11:03:59 2019
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd August 28, 2019
+.Dd October 9, 2019
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -203,6 +203,15 @@ changes the routes to use the interface 
 metric.
 See options below for controlling which interfaces we allow and deny through
 the use of patterns.
+.Pp
+Non-ethernet interfaces and some virtual ethernet interfaces
+such as TAP and bridge are ignored by default,
+as is the FireWire interface.
+To work with these devices they either need to be specified on the command line,
+be listed in
+.Fl Fl allowinterfaces
+or have an interface directive in
+.Pa @SYSCONFDIR@/dhcpcd.conf .
 .Ss Hooking into events
 .Nm
 runs

Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.26 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.27
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.26	Fri Sep 13 11:01:50 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c	Fri Oct 11 11:03:59 2019
@@ -1094,8 +1094,13 @@ static void
 dhcpcd_checkcarrier(void *arg)
 {
 	struct interface *ifp = arg;
+	int carrier;
 
-	dhcpcd_handlecarrier(ifp->ctx, LINK_UNKNOWN, ifp->flags, ifp->name);
+	/* Check carrier here rather than setting LINK_UNKNOWN.
+	 * This is because we force LINK_UNKNOWN as down for wireless which
+	 * we do not want when dealing with a route socket overflow. */
+	carrier = if_carrier(ifp);
+	dhcpcd_handlecarrier(ifp->ctx, carrier, ifp->flags, ifp->name);
 }
 
 #ifndef SMALL

Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.13 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.14
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.13	Fri Sep 13 11:01:50 2019
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c	Fri Oct 11 11:03:59 2019
@@ -101,6 +101,14 @@
 #define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len))
 #endif
 
+/* Ignore these interface names which look like ethernet but are virtual. */
+static const char * const ifnames_ignore[] = {
+	"bridge",
+	"fwe",		/* Firewire */
+	"tap",
+	NULL
+};
+
 #ifdef INET6
 static void ifa_setscope(struct sockaddr_in6 *, unsigned int);
 static unsigned int ifa_getscope(const struct sockaddr_in6 *);
@@ -208,6 +216,61 @@ if_closesockets_os(struct dhcpcd_ctx *ct
 		close(priv->pf_inet6_fd);
 }
 
+static bool
+if_ignore1(const char *drvname)
+{
+	const char * const *p;
+
+	for (p = ifnames_ignore; *p; p++) {
+		if (strcmp(*p, drvname) == 0)
+			return true;
+	}
+	return false;
+}
+
+bool
+if_ignore(struct dhcpcd_ctx *ctx, const char *ifname)
+{
+	struct if_spec spec;
+
+	if (if_nametospec(ifname, &spec) != 0)
+		return false;
+
+	if (if_ignore1(spec.drvname))
+		return true;
+
+#ifdef SIOCGIFGROUP
+	struct ifgroupreq ifgr = { .ifgr_len = 0 };
+	struct ifg_req *ifg;
+	size_t ifg_len;
+
+	/* Sadly it is possible to remove the device name
+	 * from the interface groups, but hopefully this
+	 * will be very unlikely.... */
+
+	strlcpy(ifgr.ifgr_name, ifname, sizeof(ifgr.ifgr_name));
+	if (ioctl(ctx->pf_inet_fd, SIOCGIFGROUP, &ifgr) == -1 ||
+	    (ifgr.ifgr_groups = malloc(ifgr.ifgr_len)) == NULL ||
+	    ioctl(ctx->pf_inet_fd, SIOCGIFGROUP, &ifgr) == -1)
+	{
+		logerr(__func__);
+		return false;
+	}
+
+	for (ifg = ifgr.ifgr_groups, ifg_len = ifgr.ifgr_len;
+	     ifg && ifg_len >= sizeof(*ifg);
+	     ifg++, ifg_len -= sizeof(*ifg))
+	{
+		if (if_ignore1(ifg->ifgrq_group))
+			return true;
+	}
+#else
+	UNUSED(ctx);
+#endif
+
+	return false;
+}
+
 int
 if_carrier(struct interface *ifp)
 {

Index: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.17 src/external/bsd/dhcpcd/dist/src/if-options.c:1.18
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.17	Wed Aug 21 17:12:19 2019
+++ src/external/bsd/dhcpcd/dist/src/if-options.c	Fri Oct 11 11:03:59 2019
@@ -520,7 +520,7 @@ parse_addr(__unused struct in_addr *addr
 }
 #endif
 
-static const char *
+static void
 set_option_space(struct dhcpcd_ctx *ctx,
     const char *arg,
     const struct dhcp_opt **d, size_t *dl,
@@ -543,7 +543,7 @@ set_option_space(struct dhcpcd_ctx *ctx,
 		*require = ifo->requiremasknd;
 		*no = ifo->nomasknd;
 		*reject = ifo->rejectmasknd;
-		return arg + strlen("nd_");
+		return;
 	}
 
 #ifdef DHCP6
@@ -556,7 +556,7 @@ set_option_space(struct dhcpcd_ctx *ctx,
 		*require = ifo->requiremask6;
 		*no = ifo->nomask6;
 		*reject = ifo->rejectmask6;
-		return arg + strlen("dhcp6_");
+		return;
 	}
 #endif
 #endif
@@ -576,7 +576,6 @@ set_option_space(struct dhcpcd_ctx *ctx,
 	*require = ifo->requiremask;
 	*no = ifo->nomask;
 	*reject = ifo->rejectmask;
-	return arg;
 }
 
 void
@@ -806,7 +805,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		break;
 	case 'o':
 		ARG_REQUIRED;
-		arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
+		set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
 		    &request, &require, &no, &reject);
 		if (make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
 		    make_option_mask(d, dl, od, odl, no, arg, -1) != 0 ||
@@ -818,7 +817,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		break;
 	case O_REJECT:
 		ARG_REQUIRED;
-		arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
+		set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
 		    &request, &require, &no, &reject);
 		if (make_option_mask(d, dl, od, odl, reject, arg, 1) != 0 ||
 		    make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
@@ -1053,7 +1052,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		break;
 	case 'O':
 		ARG_REQUIRED;
-		arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
+		set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
 		    &request, &require, &no, &reject);
 		if (make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
 		    make_option_mask(d, dl, od, odl, require, arg, -1) != 0 ||
@@ -1065,7 +1064,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		break;
 	case 'Q':
 		ARG_REQUIRED;
-		arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
+		set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
 		    &request, &require, &no, &reject);
 		if (make_option_mask(d, dl, od, odl, require, arg, 1) != 0 ||
 		    make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
@@ -1253,7 +1252,7 @@ parse_option(struct dhcpcd_ctx *ctx, con
 		break;
 	case O_DESTINATION:
 		ARG_REQUIRED;
-		arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
+		set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
 		    &request, &require, &no, &reject);
 		if (make_option_mask(d, dl, od, odl,
 		    ifo->dstmask, arg, 2) != 0)

Reply via email to