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)