Module Name:    src
Committed By:   roy
Date:           Wed Dec  6 10:35:05 UTC 2017

Modified Files:
        src/external/bsd/dhcpcd/dist/src: bpf.c dhcp.c dhcpcd.c

Log Message:
Sync


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/external/bsd/dhcpcd/dist/src/bpf.c
cvs rdiff -u -r1.5 -r1.6 src/external/bsd/dhcpcd/dist/src/dhcp.c \
    src/external/bsd/dhcpcd/dist/src/dhcpcd.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.4 src/external/bsd/dhcpcd/dist/src/bpf.c:1.5
--- src/external/bsd/dhcpcd/dist/src/bpf.c:1.4	Tue Sep 19 19:19:21 2017
+++ src/external/bsd/dhcpcd/dist/src/bpf.c	Wed Dec  6 10:35:05 2017
@@ -194,7 +194,8 @@ eexit:
 /* BPF requires that we read the entire buffer.
  * So we pass the buffer in the API so we can loop on >1 packet. */
 ssize_t
-bpf_read(struct interface *ifp, int fd, void *data, size_t len, int *flags)
+bpf_read(struct interface *ifp, int fd, void *data, size_t len,
+    unsigned int *flags)
 {
 	ssize_t fl = (ssize_t)bpf_frame_header_len(ifp);
 	ssize_t bytes;
@@ -203,7 +204,7 @@ bpf_read(struct interface *ifp, int fd, 
 	struct bpf_hdr packet;
 	const char *payload;
 
-	*flags = 0;
+	*flags &= ~BPF_EOF;
 	for (;;) {
 		if (state->buffer_len == 0) {
 			bytes = read(fd, state->buffer, state->buffer_size);

Index: src/external/bsd/dhcpcd/dist/src/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.5 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.6
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.5	Sat Oct  7 14:14:40 2017
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c	Wed Dec  6 10:35:05 2017
@@ -428,7 +428,6 @@ decode_rfc3442_rt(struct rt_head *routes
 
 		if ((rt = rt_new(ifp)) == NULL)
 			return -1;
-		TAILQ_INSERT_TAIL(routes, rt, rt_next);
 
 		/* If we have ocets then we have a destination and netmask */
 		dest.s_addr = 0;
@@ -461,6 +460,8 @@ decode_rfc3442_rt(struct rt_head *routes
 		/* If CIDR is 32 then it's a host route. */
 		if (cidr == 32)
 			rt->rt_flags = RTF_HOST;
+
+		TAILQ_INSERT_TAIL(routes, rt, rt_next);
 		n++;
 	}
 	return n;
@@ -1408,27 +1409,24 @@ dhcp_env(char **env, const char *prefix,
 			continue;
 		if (dhcp_getoverride(ifo, opt->option))
 			continue;
-		if ((p = get_option(ifp->ctx, bootp, bootp_len,
-		    opt->option, &pl)))
-		{
-			ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
-			    opt, dhcp_getoption, p, pl);
-			if (opt->option == DHO_VIVSO &&
-			    pl > (int)sizeof(uint32_t))
-			{
-			        memcpy(&en, p, sizeof(en));
-				en = ntohl(en);
-				vo = vivso_find(en, ifp);
-				if (vo) {
-					/* Skip over en + total size */
-					p += sizeof(en) + 1;
-					pl -= sizeof(en) + 1;
-					ep += dhcp_envoption(ifp->ctx,
-					    ep, prefix, ifp->name,
-					    vo, dhcp_getoption, p, pl);
-				}
-			}
-		}
+		p = get_option(ifp->ctx, bootp, bootp_len, opt->option, &pl);
+		if (p == NULL)
+			continue;
+		ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
+		    opt, dhcp_getoption, p, pl);
+
+		if (opt->option != DHO_VIVSO || pl <= (int)sizeof(uint32_t))
+			continue;
+		memcpy(&en, p, sizeof(en));
+		en = ntohl(en);
+		vo = vivso_find(en, ifp);
+		if (vo == NULL)
+			continue;
+		/* Skip over en + total size */
+		p += sizeof(en) + 1;
+		pl -= sizeof(en) + 1;
+		ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
+		    vo, dhcp_getoption, p, pl);
 	}
 
 	for (i = 0, opt = ifo->dhcp_override;
@@ -1437,10 +1435,11 @@ dhcp_env(char **env, const char *prefix,
 	{
 		if (has_option_mask(ifo->nomask, opt->option))
 			continue;
-		if ((p = get_option(ifp->ctx, bootp, bootp_len,
-		    opt->option, &pl)))
-			ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
-			    opt, dhcp_getoption, p, pl);
+		p = get_option(ifp->ctx, bootp, bootp_len, opt->option, &pl);
+		if (p == NULL)
+			continue;
+		ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
+		    opt, dhcp_getoption, p, pl);
 	}
 
 	return ep - env;
@@ -1519,6 +1518,8 @@ static void
 dhcp_new_xid(struct interface *ifp)
 {
 	struct dhcp_state *state;
+	const struct interface *ifp1;
+	const struct dhcp_state *state1;
 
 	state = D_STATE(ifp);
 	if (ifp->options->options & DHCPCD_XID_HWADDR &&
@@ -1527,8 +1528,30 @@ dhcp_new_xid(struct interface *ifp)
 		memcpy(&state->xid,
 		    (ifp->hwaddr + ifp->hwlen) - sizeof(state->xid),
 		    sizeof(state->xid));
-	else
+	else {
+again:
 		state->xid = arc4random();
+	}
+
+	/* Ensure it's unique */
+	TAILQ_FOREACH(ifp1, ifp->ctx->ifaces, next) {
+		if (ifp == ifp1)
+			continue;
+		if ((state1 = D_CSTATE(ifp1)) == NULL)
+			continue;
+		if (state1->xid == state->xid)
+			break;
+	}
+	if (ifp1 != NULL) {
+		if (ifp->options->options & DHCPCD_XID_HWADDR &&
+		    ifp->hwlen >= sizeof(state->xid))
+		{
+			logerrx("%s: duplicate xid on %s",
+			    ifp->name, ifp1->name);
+			    return;
+		}
+		goto again;
+	}
 
 	/* We can't do this when sharing leases across interfaes */
 #if 0
@@ -1552,6 +1575,7 @@ dhcp_close(struct interface *ifp)
 		eloop_event_delete(ifp->ctx->eloop, state->bpf_fd);
 		bpf_close(ifp, state->bpf_fd);
 		state->bpf_fd = -1;
+		state->bpf_flags |= BPF_EOF;
 	}
 
 	state->interval = 0;
@@ -2464,11 +2488,43 @@ dhcp_reboot_newopts(struct interface *if
 	}
 }
 
+#ifdef ARP
+static int
+dhcp_activeaddr(const struct interface *ifp, const struct in_addr *addr)
+{
+	const struct interface *ifp1;
+	const struct dhcp_state *state;
+
+	TAILQ_FOREACH(ifp1, ifp->ctx->ifaces, next) {
+		if (ifp1 == ifp)
+			continue;
+		if ((state = D_CSTATE(ifp1)) == NULL)
+			continue;
+		switch(state->state) {
+		case DHS_REBOOT:
+		case DHS_RENEW:
+		case DHS_REBIND:
+		case DHS_BOUND:
+		case DHS_INFORM:
+			break;
+		default:
+			continue;
+		}
+		if (state->lease.addr.s_addr == addr->s_addr)
+			return 1;
+	}
+	return 0;
+}
+#endif
+
 static void
 dhcp_reboot(struct interface *ifp)
 {
 	struct if_options *ifo;
 	struct dhcp_state *state = D_STATE(ifp);
+#ifdef ARP
+	struct ipv4_addr *ia;
+#endif
 
 	if (state == NULL || state->state == DHS_NONE)
 		return;
@@ -2499,6 +2555,20 @@ dhcp_reboot(struct interface *ifp)
 
 	loginfox("%s: rebinding lease of %s",
 	    ifp->name, inet_ntoa(state->lease.addr));
+
+#ifdef ARP
+	/* If the address exists on the interface and no other interface
+	 * is currently using it then announce it to ensure this
+	 * interface gets the reply. */
+	ia = ipv4_iffindaddr(ifp, &state->lease.addr, NULL);
+	if (ia != NULL &&
+#ifdef IN_IFF_NOTUSEABLE
+	    !(ia->addr_flags & IN_IFF_NOTUSEABLE) &&
+#endif
+	    dhcp_activeaddr(ifp, &state->lease.addr) == 0)
+		arp_ifannounceaddr(ifp, &state->lease.addr);
+#endif
+
 	dhcp_new_xid(ifp);
 	state->lease.server.s_addr = 0;
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
@@ -3147,7 +3217,7 @@ valid_udp_packet(void *data, size_t data
 	if (data_len < sizeof(p->ip) + sizeof(p->udp)) {
 		if (from)
 			from->s_addr = INADDR_ANY;
-		errno = EINVAL;
+		errno = ERANGE;
 		return -1;
 	}
 	p = (struct bootp_pkt *)data;
@@ -3160,7 +3230,7 @@ valid_udp_packet(void *data, size_t data
 
 	bytes = ntohs(p->ip.ip_len);
 	if (bytes > data_len) {
-		errno = EINVAL;
+		errno = ENOBUFS;
 		return -1;
 	}
 
@@ -3191,17 +3261,22 @@ valid_udp_packet(void *data, size_t data
 }
 
 static void
-dhcp_handlepacket(struct interface *ifp, uint8_t *data, size_t len, int flags)
+dhcp_handlepacket(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, flags & RAW_PARTIALCSUM) == -1)
+	if (valid_udp_packet(data, len, &from,
+			     state->bpf_flags & RAW_PARTIALCSUM) == -1)
 	{
-		logerrx("%s: invalid UDP packet from %s",
-		    ifp->name, inet_ntoa(from));
+		if (errno == EINVAL)
+			logerrx("%s: UDP checksum failure from %s",
+			  ifp->name, inet_ntoa(from));
+		else
+			logerr("%s: invalid UDP packet from %s",
+			  ifp->name, inet_ntoa(from));
 		return;
 	}
 	if (ifp->flags & IFF_POINTOPOINT &&
@@ -3243,27 +3318,30 @@ dhcp_readpacket(void *arg)
 	struct interface *ifp = arg;
 	uint8_t buf[MTU_MAX];
 	ssize_t bytes;
-	int flags;
-	const struct dhcp_state *state = D_CSTATE(ifp);
+	struct dhcp_state *state = D_STATE(ifp);
 
 	/* Some RAW mechanisms are generic file descriptors, not sockets.
 	 * This means we have no kernel call to just get one packet,
 	 * so we have to process the entire buffer. */
-	flags = 0;
-	while (!(flags & BPF_EOF)) {
-		bytes = bpf_read(ifp, state->bpf_fd, buf, sizeof(buf), &flags);
+	state->bpf_flags &= ~BPF_EOF;
+	state->bpf_flags |= BPF_READING;
+	while (!(state->bpf_flags & BPF_EOF)) {
+		bytes = bpf_read(ifp, state->bpf_fd, buf, sizeof(buf),
+				 &state->bpf_flags);
 		if (bytes == -1) {
 			if (state->state != DHS_NONE) {
 				logerr("%s: %s", __func__, ifp->name);
 				dhcp_close(ifp);
 			}
-			return;
+			break;
 		}
-		dhcp_handlepacket(ifp, buf, (size_t)bytes, flags);
+		dhcp_handlepacket(ifp, buf, (size_t)bytes);
 		/* Check we still have a state after processing. */
-		if ((state = D_CSTATE(ifp)) == NULL || state->bpf_fd == -1)
+		if ((state = D_STATE(ifp)) == NULL)
 			break;
 	}
+	if (state != NULL)
+		state->bpf_flags &= ~BPF_READING;
 }
 
 static void
@@ -3284,51 +3362,30 @@ dhcp_handleudp(void *arg)
 	}
 }
 
-
 static int
-dhcp_openbpf1(struct interface *ifp, bool logerror)
+dhcp_openbpf(struct interface *ifp)
 {
 	struct dhcp_state *state;
 
 	state = D_STATE(ifp);
+	if (state->bpf_fd != -1)
+		return 0;
+
+	state->bpf_fd = bpf_open(ifp, bpf_bootp);
 	if (state->bpf_fd == -1) {
-		state->bpf_fd = bpf_open(ifp, bpf_bootp);
-		if (state->bpf_fd == -1) {
-			if (errno == ENOENT) {
-				logerrx("%s not found", bpf_name);
-				/* May as well disable IPv4 entirely at
-				 * this point as we really need it. */
-				ifp->options->options &= ~DHCPCD_IPV4;
-			} else if (logerror)
-				logerr("%s: %s", __func__, ifp->name);
-			return -1;
-		}
-		eloop_event_add(ifp->ctx->eloop,
-		    state->bpf_fd, dhcp_readpacket, ifp);
+		if (errno == ENOENT) {
+			logerrx("%s not found", bpf_name);
+			/* May as well disable IPv4 entirely at
+			 * this point as we really need it. */
+			ifp->options->options &= ~DHCPCD_IPV4;
+		} else
+			logerr("%s: %s", __func__, ifp->name);
+		return -1;
 	}
-	return 0;
-}
-
-/* This blows chunks.
- * Because we may (although unlikely) get the same IP address
- * across different interfaces we need to open a BPF socket
- * on ALL interfaces as thanks to ARP magic we might get the
- * DHCP reply on a different interface. */
-static int
-dhcp_openbpf(struct interface *ifp)
-{
-	struct interface *ifn;
-	int r, o;
 
-	r = -1;
-	TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
-		if (dhcp_initstate(ifn) == -1)
-			continue;
-		o = dhcp_openbpf1(ifn, ifn == ifp);
-		if (ifn == ifp)
-			r = o;
-	}
-	return r;
+	eloop_event_add(ifp->ctx->eloop,
+	    state->bpf_fd, dhcp_readpacket, ifp);
+	return 0;
 }
 
 int
Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.5 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.6
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.5	Tue Sep 19 19:19:21 2017
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c	Wed Dec  6 10:35:05 2017
@@ -871,37 +871,22 @@ dhcpcd_startinterface(void *arg)
 				ipv6nd_startrs(ifp);
 		}
 
-		if (ifo->options & DHCPCD_DHCP6)
+
+		if (ifo->options & DHCPCD_DHCP6) {
 			dhcp6_find_delegates(ifp);
 
-		if ((!(ifo->options & DHCPCD_IPV6RS) ||
-		    ifo->options & (DHCPCD_IA_FORCED | DHCPCD_INFORM6)) &&
-		    ifp->active == IF_ACTIVE_USER)
-		{
-			ssize_t nolease;
+			if (ifp->active == IF_ACTIVE_USER) {
+				enum DH6S d6_state;
 
-			if (ifo->options & DHCPCD_IA_FORCED)
-				nolease = dhcp6_start(ifp, DH6S_INIT);
-			else if (ifo->options & DHCPCD_INFORM6)
-				nolease = dhcp6_start(ifp, DH6S_INFORM);
-			else {
-				nolease = 0;
-				/* Enabling the below doesn't really make
-				 * sense as there is currently no standard
-				 * to push routes via DHCPv6.
-				 * (There is an expired working draft,
-				 * maybe abandoned?)
-				 * You can also get it to work by forcing
-				 * an IA as shown above. */
-#if 0
-				/* With no RS or delegates we might
-				 * as well try and solicit a DHCPv6 address */
-				if (nolease == 0)
-					nolease = dhcp6_start(ifp, DH6S_INIT);
-#endif
+				if (ifo->options & DHCPCD_IA_FORCED)
+					d6_state = DH6S_INIT;
+				else if (ifo->options & DHCPCD_INFORM6)
+					d6_state = DH6S_INFORM;
+				else
+					d6_state = DH6S_CONFIRM;
+				if (dhcp6_start(ifp, d6_state) == -1)
+					logerr("%s: dhcp6_start", ifp->name);
 			}
-			if (nolease == -1)
-			        logerr("%s: dhcp6_start", ifp->name);
 		}
 	}
 
@@ -1668,6 +1653,20 @@ printpidfile:
 		logerr("%s: eloop_init", __func__);
 		goto exit_failure;
 	}
+#ifdef USE_SIGNALS
+	/* Save signal mask, block and redirect signals to our handler */
+	if (eloop_signal_set_cb(ctx.eloop,
+	    dhcpcd_signals, dhcpcd_signals_len,
+	    signal_cb, &ctx) == -1)
+	{
+		logerr("%s: eloop_signal_set_cb", __func__);
+		goto exit_failure;
+	}
+	if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) {
+		logerr("%s: eloop_signal_mask", __func__);
+		goto exit_failure;
+	}
+#endif
 
 	if (ctx.options & DHCPCD_DUMPLEASE) {
 		/* Open sockets so we can dump something about
@@ -1828,21 +1827,6 @@ printpidfile:
 		goto exit_failure;
 	}
 
-#ifdef USE_SIGNALS
-	if (eloop_signal_set_cb(ctx.eloop,
-	    dhcpcd_signals, dhcpcd_signals_len,
-	    signal_cb, &ctx) == -1)
-	{
-		logerr("%s: eloop_signal_set_cb", __func__);
-		goto exit_failure;
-	}
-	/* Save signal mask, block and redirect signals to our handler */
-	if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) {
-		logerr("%s: eloop_signal_mask", __func__);
-		goto exit_failure;
-	}
-#endif
-
 	/* When running dhcpcd against a single interface, we need to retain
 	 * the old behaviour of waiting for an IP address */
 	if (ctx.ifc == 1 && !(ctx.options & DHCPCD_BACKGROUND))

Reply via email to