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))