Module Name: src
Committed By: roy
Date: Wed Jul 24 09:57:43 UTC 2019
Modified Files:
src/external/bsd/dhcpcd/dist/hooks: 20-resolv.conf 50-ntp.conf
src/external/bsd/dhcpcd/dist/src: bpf.c dhcp.c dhcp6.c dhcpcd.c
if-bsd.c if-options.c ipv6nd.c
Log Message:
Sync
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/dhcpcd/dist/hooks/20-resolv.conf \
src/external/bsd/dhcpcd/dist/hooks/50-ntp.conf
cvs rdiff -u -r1.9 -r1.10 src/external/bsd/dhcpcd/dist/src/bpf.c
cvs rdiff -u -r1.19 -r1.20 src/external/bsd/dhcpcd/dist/src/dhcp.c
cvs rdiff -u -r1.8 -r1.9 src/external/bsd/dhcpcd/dist/src/dhcp6.c \
src/external/bsd/dhcpcd/dist/src/if-bsd.c
cvs rdiff -u -r1.20 -r1.21 src/external/bsd/dhcpcd/dist/src/dhcpcd.c
cvs rdiff -u -r1.14 -r1.15 src/external/bsd/dhcpcd/dist/src/if-options.c
cvs rdiff -u -r1.7 -r1.8 src/external/bsd/dhcpcd/dist/src/ipv6nd.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/hooks/20-resolv.conf
diff -u src/external/bsd/dhcpcd/dist/hooks/20-resolv.conf:1.2 src/external/bsd/dhcpcd/dist/hooks/20-resolv.conf:1.3
--- src/external/bsd/dhcpcd/dist/hooks/20-resolv.conf:1.2 Sat Sep 22 13:17:46 2018
+++ src/external/bsd/dhcpcd/dist/hooks/20-resolv.conf Wed Jul 24 09:57:43 2019
@@ -19,6 +19,7 @@ build_resolv_conf()
interfaces=$(list_interfaces "$resolv_conf_dir")
# Build the resolv.conf
+ header=
if [ -n "$interfaces" ]; then
# Build the header
for x in ${interfaces}; do
@@ -69,30 +70,26 @@ build_resolv_conf()
}
# Extract any ND DNS options from the RA
-# For now, we ignore the lifetime of the DNS options unless they
-# are absent or zero.
-# In this case they are removed from consideration.
-# See draft-gont-6man-slaac-dns-config-issues-01 for issues
-# regarding DNS option lifetime in ND messages.
+# Obey the lifetimes
eval_nd_dns()
{
- eval ltime=\$nd${i}_rdnss${j}_lifetime
- if [ -z "$ltime" ] || [ "$ltime" = 0 ]; then
- rdnss=
- else
+
+ eval rdnsstime=\$nd${i}_rdnss${j}_lifetime
+ [ -z "$rdnsstime" ] && return 1
+ ltime=$(($rdnsstime - $offset))
+ if [ "$ltime" -gt 0 ]; then
eval rdnss=\$nd${i}_rdnss${j}_servers
+ [ -n "$rdnss" ] && new_rdnss="$new_rdnss${new_rdnss:+ }$rdnss"
fi
- eval ltime=\$nd${i}_dnssl${j}_lifetime
- if [ -z "$ltime" ] || [ "$ltime" = 0 ]; then
- dnssl=
- else
+
+ eval dnssltime=\$nd${i}_dnssl${j}_lifetime
+ [ -z "$dnssltime" ] && return 1
+ ltime=$(($dnssltime - $offset))
+ if [ "$ltime" -gt 0 ]; then
eval dnssl=\$nd${i}_dnssl${j}_search
+ [ -n "$dnssl" ] && new_dnssl="$new_dnssl${new_dnssl:+ }$dnssl"
fi
- [ -z "${rdnss}${dnssl}" ] && return 1
-
- [ -n "$rdnss" ] && new_rdnss="$new_rdnss${new_rdnss:+ }$rdnss"
- [ -n "$dnssl" ] && new_dnssl="$new_dnssl${new_dnssl:+ }$dnssl"
j=$(($j + 1))
return 0
}
@@ -106,12 +103,16 @@ add_resolv_conf()
i=1
j=1
while true; do
+ eval acquired=\$nd${i}_acquired
+ [ -z "$acquired" ] && break
+ eval now=\$nd${i}_now
+ [ -z "$now" ] && break
+ offset=$(($now - $acquired))
while true; do
eval_nd_dns || break
done
i=$(($i + 1))
j=1
- eval_nd_dns || break
done
[ -n "$new_rdnss" ] && \
new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$new_rdnss"
Index: src/external/bsd/dhcpcd/dist/hooks/50-ntp.conf
diff -u src/external/bsd/dhcpcd/dist/hooks/50-ntp.conf:1.2 src/external/bsd/dhcpcd/dist/hooks/50-ntp.conf:1.3
--- src/external/bsd/dhcpcd/dist/hooks/50-ntp.conf:1.2 Sat Sep 22 13:17:46 2018
+++ src/external/bsd/dhcpcd/dist/hooks/50-ntp.conf Wed Jul 24 09:57:43 2019
@@ -62,6 +62,7 @@ build_ntp_conf()
# Build a list of interfaces
interfaces=$(list_interfaces "$ntp_conf_dir")
+ header=
servers=
if [ -n "$interfaces" ]; then
# Build the header
Index: src/external/bsd/dhcpcd/dist/src/bpf.c
diff -u src/external/bsd/dhcpcd/dist/src/bpf.c:1.9 src/external/bsd/dhcpcd/dist/src/bpf.c:1.10
--- src/external/bsd/dhcpcd/dist/src/bpf.c:1.9 Sat May 4 09:42:15 2019
+++ src/external/bsd/dhcpcd/dist/src/bpf.c Wed Jul 24 09:57:43 2019
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
/*
* dhcpcd: BPF arp and bootp filtering
* Copyright (c) 2006-2019 Roy Marples <[email protected]>
@@ -84,7 +85,7 @@ size_t
bpf_frame_header_len(const struct interface *ifp)
{
- switch(ifp->family) {
+ switch (ifp->family) {
case ARPHRD_ETHER:
return sizeof(struct ether_header);
default:
@@ -92,6 +93,23 @@ bpf_frame_header_len(const struct interf
}
}
+static const uint8_t etherbroadcastaddr[] =
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+int
+bpf_frame_bcast(const struct interface *ifp, const char *frame)
+{
+
+ switch (ifp->family) {
+ case ARPHRD_ETHER:
+ return memcmp(frame +
+ offsetof(struct ether_header, ether_dhost),
+ etherbroadcastaddr, sizeof(etherbroadcastaddr));
+ default:
+ return -1;
+ }
+}
+
#ifndef __linux__
/* Linux is a special snowflake for opening, attaching and reading BPF.
* See if-linux.c for the Linux specific BPF functions. */
@@ -227,8 +245,12 @@ bpf_read(struct interface *ifp, int fd,
if (state->buffer_pos + packet.bh_caplen + packet.bh_hdrlen >
state->buffer_len)
goto next; /* Packet beyond buffer, drop. */
- payload = state->buffer + state->buffer_pos +
- packet.bh_hdrlen + fl;
+ payload = state->buffer + state->buffer_pos + packet.bh_hdrlen;
+ if (bpf_frame_bcast(ifp, payload) == 0)
+ *flags |= BPF_BCAST;
+ else
+ *flags &= ~BPF_BCAST;
+ payload += fl;
bytes = (ssize_t)packet.bh_caplen - fl;
if ((size_t)bytes > len)
bytes = (ssize_t)len;
Index: src/external/bsd/dhcpcd/dist/src/dhcp.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp.c:1.19 src/external/bsd/dhcpcd/dist/src/dhcp.c:1.20
--- src/external/bsd/dhcpcd/dist/src/dhcp.c:1.19 Sat May 4 09:42:15 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp.c Wed Jul 24 09:57:43 2019
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
/*
* dhcpcd - DHCP client daemon
* Copyright (c) 2006-2019 Roy Marples <[email protected]>
@@ -47,6 +48,7 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -124,8 +126,9 @@ static const char * const dhcp_params[]
};
static int dhcp_openbpf(struct interface *);
+static void dhcp_start1(void *);
#ifdef ARP
-static void dhcp_arp_conflicted(struct arp_state *, const struct arp_msg *);
+static void dhcp_arp_found(struct arp_state *, const struct arp_msg *);
#endif
static void dhcp_handledhcp(struct interface *, struct bootp *, size_t,
const struct in_addr *);
@@ -339,23 +342,25 @@ get_option_uint8(struct dhcpcd_ctx *ctx,
}
ssize_t
-decode_rfc3442(char *out, size_t len, const uint8_t *p, size_t pl)
+print_rfc3442(FILE *fp, const uint8_t *data, size_t data_len)
{
- const uint8_t *e;
- size_t bytes = 0, ocets;
- int b;
+ const uint8_t *p = data, *e;
+ size_t ocets;
uint8_t cidr;
struct in_addr addr;
- char *o = out;
/* Minimum is 5 -first is CIDR and a router length of 4 */
- if (pl < 5) {
+ if (data_len < 5) {
errno = EINVAL;
return -1;
}
- e = p + pl;
+ e = p + data_len;
while (p < e) {
+ if (p != data) {
+ if (fputc(' ', fp) == EOF)
+ return -1;
+ }
cidr = *p++;
if (cidr > 32) {
errno = EINVAL;
@@ -366,45 +371,29 @@ decode_rfc3442(char *out, size_t len, co
errno = ERANGE;
return -1;
}
- if (!out) {
- p += 4 + ocets;
- bytes += ((4 * 4) * 2) + 4;
- continue;
- }
- if ((((4 * 4) * 2) + 4) > len) {
- errno = ENOBUFS;
- return -1;
- }
- if (o != out) {
- *o++ = ' ';
- len--;
- }
/* If we have ocets then we have a destination and netmask */
+ addr.s_addr = 0;
if (ocets > 0) {
- addr.s_addr = 0;
memcpy(&addr.s_addr, p, ocets);
- b = snprintf(o, len, "%s/%d", inet_ntoa(addr), cidr);
p += ocets;
- } else
- b = snprintf(o, len, "0.0.0.0/0");
- o += b;
- len -= (size_t)b;
+ }
+ if (fprintf(fp, "%s/%d", inet_ntoa(addr), cidr) == -1)
+ return -1;
/* Finally, snag the router */
memcpy(&addr.s_addr, p, 4);
p += 4;
- b = snprintf(o, len, " %s", inet_ntoa(addr));
- o += b;
- len -= (size_t)b;
+ if (fprintf(fp, " %s", inet_ntoa(addr)) == -1)
+ return -1;
}
- if (out)
- return o - out;
- return (ssize_t)bytes;
+ if (fputc('\0', fp) == EOF)
+ return -1;
+ return 1;
}
static int
-decode_rfc3442_rt(struct rt_head *routes, struct interface *ifp,
+decode_rfc3442_rt(rb_tree_t *routes, struct interface *ifp,
const uint8_t *data, size_t dl, const struct bootp *bootp)
{
const uint8_t *p = data;
@@ -467,22 +456,18 @@ decode_rfc3442_rt(struct rt_head *routes
sa_in_init(&rt->rt_dest, &dest);
sa_in_init(&rt->rt_netmask, &netmask);
sa_in_init(&rt->rt_gateway, &gateway);
-
- TAILQ_INSERT_TAIL(routes, rt, rt_next);
- n++;
+ if (rt_proto_add(routes, rt))
+ n = 1;
}
return n;
}
-char *
-decode_rfc3361(const uint8_t *data, size_t dl)
+ssize_t
+print_rfc3361(FILE *fp, const uint8_t *data, size_t dl)
{
uint8_t enc;
- size_t l;
- ssize_t r;
- char *sip = NULL;
+ char sip[NS_MAXDNAME];
struct in_addr addr;
- char *p;
if (dl < 2) {
errno = EINVAL;
@@ -493,13 +478,10 @@ decode_rfc3361(const uint8_t *data, size
dl--;
switch (enc) {
case 0:
- if ((r = decode_rfc1035(NULL, 0, data, dl)) > 0) {
- l = (size_t)r + 1;
- sip = malloc(l);
- if (sip == NULL)
- return 0;
- decode_rfc1035(sip, l, data, dl);
- }
+ if (decode_rfc1035(sip, sizeof(sip), data, dl) == -1)
+ return -1;
+ if (efprintf(fp, "%s", sip) == -1)
+ return -1;
break;
case 1:
if (dl == 0 || dl % 4 != 0) {
@@ -507,25 +489,27 @@ decode_rfc3361(const uint8_t *data, size
break;
}
addr.s_addr = INADDR_BROADCAST;
- l = ((dl / sizeof(addr.s_addr)) * ((4 * 4) + 1)) + 1;
- sip = p = malloc(l);
- if (sip == NULL)
- return 0;
- while (dl != 0) {
+ for (;
+ dl != 0;
+ data += sizeof(addr.s_addr), dl -= sizeof(addr.s_addr))
+ {
memcpy(&addr.s_addr, data, sizeof(addr.s_addr));
- data += sizeof(addr.s_addr);
- p += snprintf(p, l - (size_t)(p - sip),
- "%s ", inet_ntoa(addr));
- dl -= sizeof(addr.s_addr);
+ if (fprintf(fp, "%s", inet_ntoa(addr)) == -1)
+ return -1;
+ if (dl != 0) {
+ if (fputc(' ', fp) == EOF)
+ return -1;
+ }
}
- *--p = '\0';
+ if (fputc('\0', fp) == EOF)
+ return -1;
break;
default:
errno = EINVAL;
return 0;
}
- return sip;
+ return 1;
}
static char *
@@ -581,7 +565,7 @@ route_netmask(uint32_t ip_in)
* If we have a CSR then we only use that.
* Otherwise we add static routes and then routers. */
static int
-get_option_routes(struct rt_head *routes, struct interface *ifp,
+get_option_routes(rb_tree_t *routes, struct interface *ifp,
const struct bootp *bootp, size_t bootp_len)
{
struct if_options *ifo = ifp->options;
@@ -656,9 +640,8 @@ get_option_routes(struct rt_head *routes
sa_in_init(&rt->rt_dest, &dest);
sa_in_init(&rt->rt_netmask, &netmask);
sa_in_init(&rt->rt_gateway, &gateway);
-
- TAILQ_INSERT_TAIL(routes, rt, rt_next);
- n++;
+ if (rt_proto_add(routes, rt))
+ n++;
}
}
@@ -667,7 +650,7 @@ get_option_routes(struct rt_head *routes
p = get_option(ifp->ctx, bootp, bootp_len, DHO_ROUTER, &len);
else
p = NULL;
- if (p) {
+ if (p && len % 4 == 0) {
e = p + len;
dest.s_addr = INADDR_ANY;
netmask.s_addr = INADDR_ANY;
@@ -679,8 +662,8 @@ get_option_routes(struct rt_head *routes
sa_in_init(&rt->rt_dest, &dest);
sa_in_init(&rt->rt_netmask, &netmask);
sa_in_init(&rt->rt_gateway, &gateway);
- TAILQ_INSERT_TAIL(routes, rt, rt_next);
- n++;
+ if (rt_proto_add(routes, rt))
+ n++;
}
}
@@ -707,7 +690,7 @@ dhcp_get_mtu(const struct interface *ifp
/* Grab our routers from the DHCP message and apply any MTU value
* the message contains */
int
-dhcp_get_routes(struct rt_head *routes, struct interface *ifp)
+dhcp_get_routes(rb_tree_t *routes, struct interface *ifp)
{
const struct dhcp_state *state;
@@ -1299,9 +1282,8 @@ dhcp_getoption(struct dhcpcd_ctx *ctx,
}
ssize_t
-dhcp_env(char **env, const char *prefix,
- const struct bootp *bootp, size_t bootp_len,
- const struct interface *ifp)
+dhcp_env(FILE *fenv, const char *prefix, const struct interface *ifp,
+ const struct bootp *bootp, size_t bootp_len)
{
const struct if_options *ifo;
const uint8_t *p;
@@ -1309,109 +1291,73 @@ dhcp_env(char **env, const char *prefix,
struct in_addr net;
struct in_addr brd;
struct dhcp_opt *opt, *vo;
- size_t e, i, pl;
- char **ep;
- char cidr[4], safe[(BOOTP_FILE_LEN * 4) + 1];
+ size_t i, pl;
+ char safe[(BOOTP_FILE_LEN * 4) + 1];
uint8_t overl = 0;
uint32_t en;
- e = 0;
ifo = ifp->options;
if (get_option_uint8(ifp->ctx, &overl, bootp, bootp_len,
DHO_OPTSOVERLOADED) == -1)
overl = 0;
- if (env == NULL) {
- if (bootp->yiaddr || bootp->ciaddr)
- e += 5;
- if (*bootp->file && !(overl & 1))
- e++;
- if (*bootp->sname && !(overl & 2))
- e++;
- for (i = 0, opt = ifp->ctx->dhcp_opts;
- i < ifp->ctx->dhcp_opts_len;
- i++, opt++)
- {
- if (has_option_mask(ifo->nomask, opt->option))
- continue;
- if (dhcp_getoverride(ifo, opt->option))
- continue;
- p = get_option(ifp->ctx, bootp, bootp_len,
- opt->option, &pl);
- if (!p)
- continue;
- e += dhcp_envoption(ifp->ctx, NULL, NULL, ifp->name,
- opt, dhcp_getoption, p, pl);
- }
- for (i = 0, opt = ifo->dhcp_override;
- i < ifo->dhcp_override_len;
- i++, opt++)
- {
- if (has_option_mask(ifo->nomask, opt->option))
- continue;
- p = get_option(ifp->ctx, bootp, bootp_len,
- opt->option, &pl);
- if (!p)
- continue;
- e += dhcp_envoption(ifp->ctx, NULL, NULL, ifp->name,
- opt, dhcp_getoption, p, pl);
- }
- return (ssize_t)e;
- }
-
- ep = env;
if (bootp->yiaddr || bootp->ciaddr) {
/* Set some useful variables that we derive from the DHCP
* message but are not necessarily in the options */
addr.s_addr = bootp->yiaddr ? bootp->yiaddr : bootp->ciaddr;
- addvar(&ep, prefix, "ip_address", inet_ntoa(addr));
+ if (efprintf(fenv, "%s_ip_address=%s",
+ prefix, inet_ntoa(addr)) == -1)
+ return -1;
if (get_option_addr(ifp->ctx, &net,
- bootp, bootp_len, DHO_SUBNETMASK) == -1)
- {
+ bootp, bootp_len, DHO_SUBNETMASK) == -1) {
net.s_addr = ipv4_getnetmask(addr.s_addr);
- addvar(&ep, prefix,
- "subnet_mask", inet_ntoa(net));
+ if (efprintf(fenv, "%s_subnet_mask=%s",
+ prefix, inet_ntoa(net)) == -1)
+ return -1;
}
- snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net));
- addvar(&ep, prefix, "subnet_cidr", cidr);
+ if (efprintf(fenv, "%s_subnet_cidr=%d",
+ prefix, inet_ntocidr(net))== -1)
+ return -1;
if (get_option_addr(ifp->ctx, &brd,
bootp, bootp_len, DHO_BROADCAST) == -1)
{
brd.s_addr = addr.s_addr | ~net.s_addr;
- addvar(&ep, prefix,
- "broadcast_address", inet_ntoa(brd));
+ if (efprintf(fenv, "%s_broadcast_address=%s",
+ prefix, inet_ntoa(brd)) == -1)
+ return -1;
}
addr.s_addr = bootp->yiaddr & net.s_addr;
- addvar(&ep, prefix,
- "network_number", inet_ntoa(addr));
+ if (efprintf(fenv, "%s_network_number=%s",
+ prefix, inet_ntoa(addr)) == -1)
+ return -1;
}
if (*bootp->file && !(overl & 1)) {
print_string(safe, sizeof(safe), OT_STRING,
bootp->file, sizeof(bootp->file));
- addvar(&ep, prefix, "filename", safe);
+ if (efprintf(fenv, "%s_filename=%s", prefix, safe) == -1)
+ return -1;
}
if (*bootp->sname && !(overl & 2)) {
print_string(safe, sizeof(safe), OT_STRING | OT_DOMAIN,
bootp->sname, sizeof(bootp->sname));
- addvar(&ep, prefix, "server_name", safe);
+ if (efprintf(fenv, "%s_server_name=%s", prefix, safe) == -1)
+ return -1;
}
/* Zero our indexes */
- if (env) {
- for (i = 0, opt = ifp->ctx->dhcp_opts;
- i < ifp->ctx->dhcp_opts_len;
- i++, opt++)
- dhcp_zero_index(opt);
- for (i = 0, opt = ifp->options->dhcp_override;
- i < ifp->options->dhcp_override_len;
- i++, opt++)
- dhcp_zero_index(opt);
- for (i = 0, opt = ifp->ctx->vivso;
- i < ifp->ctx->vivso_len;
- i++, opt++)
- dhcp_zero_index(opt);
- }
+ for (i = 0, opt = ifp->ctx->dhcp_opts;
+ i < ifp->ctx->dhcp_opts_len;
+ i++, opt++)
+ dhcp_zero_index(opt);
+ for (i = 0, opt = ifp->options->dhcp_override;
+ i < ifp->options->dhcp_override_len;
+ i++, opt++)
+ dhcp_zero_index(opt);
+ for (i = 0, opt = ifp->ctx->vivso;
+ i < ifp->ctx->vivso_len;
+ i++, opt++)
+ dhcp_zero_index(opt);
for (i = 0, opt = ifp->ctx->dhcp_opts;
i < ifp->ctx->dhcp_opts_len;
@@ -1424,7 +1370,7 @@ dhcp_env(char **env, const char *prefix,
p = get_option(ifp->ctx, bootp, bootp_len, opt->option, &pl);
if (p == NULL)
continue;
- ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
+ dhcp_envoption(ifp->ctx, fenv, prefix, ifp->name,
opt, dhcp_getoption, p, pl);
if (opt->option != DHO_VIVSO || pl <= (int)sizeof(uint32_t))
@@ -1437,7 +1383,7 @@ dhcp_env(char **env, const char *prefix,
/* Skip over en + total size */
p += sizeof(en) + 1;
pl -= sizeof(en) + 1;
- ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
+ dhcp_envoption(ifp->ctx, fenv, prefix, ifp->name,
vo, dhcp_getoption, p, pl);
}
@@ -1450,11 +1396,11 @@ dhcp_env(char **env, const char *prefix,
p = get_option(ifp->ctx, bootp, bootp_len, opt->option, &pl);
if (p == NULL)
continue;
- ep += dhcp_envoption(ifp->ctx, ep, prefix, ifp->name,
+ dhcp_envoption(ifp->ctx, fenv, prefix, ifp->name,
opt, dhcp_getoption, p, pl);
}
- return ep - env;
+ return 1;
}
static void
@@ -1497,7 +1443,7 @@ get_lease(struct interface *ifp,
}
if (get_option_uint32(ctx, &lease->leasetime,
bootp, len, DHO_LEASETIME) != 0)
- lease->leasetime = ~0U; /* Default to infinite lease */
+ lease->leasetime = DHCP_INFINITE_LIFETIME;
if (get_option_uint32(ctx, &lease->renewaltime,
bootp, len, DHO_RENEWALTIME) != 0)
lease->renewaltime = 0;
@@ -1923,35 +1869,6 @@ dhcp_request(void *arg)
send_request(ifp);
}
-static int
-dhcp_leaseextend(struct interface *ifp)
-{
-
-#ifdef ARP
- if (ifp->options->options & DHCPCD_ARP) {
- const struct dhcp_state *state;
- struct arp_state *astate;
-
- state = D_CSTATE(ifp);
- if ((astate = arp_new(ifp, &state->lease.addr)) == NULL)
- return -1;
- astate->conflicted_cb = dhcp_arp_conflicted;
-
-#ifndef KERNEL_RFC5227
- if (arp_open(ifp) == -1)
- return -1;
-#endif
-
- logwarnx("%s: extending lease until DaD failure or DHCP",
- ifp->name);
- return 0;
- }
-#endif
-
- logwarnx("%s: extending lease", ifp->name);
- return 0;
-}
-
static void
dhcp_expire1(struct interface *ifp)
{
@@ -1970,12 +1887,12 @@ dhcp_expire(void *arg)
{
struct interface *ifp = arg;
- logerrx("%s: DHCP lease expired", ifp->name);
if (ifp->options->options & DHCPCD_LASTLEASE_EXTEND) {
- if (dhcp_leaseextend(ifp) == 0)
- return;
- logerr(__func__);
+ logwarnx("%s: DHCP lease expired, extending lease", ifp->name);
+ return;
}
+
+ logerrx("%s: DHCP lease expired", ifp->name);
dhcp_expire1(ifp);
}
@@ -2041,41 +1958,18 @@ dhcp_rebind(void *arg)
send_rebind(ifp);
}
-#ifdef ARP
static void
-dhcp_arp_probed(struct arp_state *astate)
+dhcp_finish_dad(struct interface *ifp, struct in_addr *ia)
{
- struct interface *ifp;
- struct dhcp_state *state;
- struct if_options *ifo;
+ struct dhcp_state *state = D_STATE(ifp);
- ifp = astate->iface;
- state = D_STATE(ifp);
- ifo = ifp->options;
-#ifdef ARPING
- if (ifo->arping_len && state->arping_index < ifo->arping_len) {
- /* We didn't find a profile for this
- * address or hwaddr, so move to the next
- * arping profile */
- if (++state->arping_index < ifo->arping_len) {
- astate->addr.s_addr =
- ifo->arping[state->arping_index];
- arp_probe(astate);
- return;
- }
- arp_free(astate);
- dhcpcd_startinterface(ifp);
+ if (state->state != DHS_PROBE)
return;
- }
-#endif
-
- /* Already bound so DAD has worked */
- if (state->state == DHS_BOUND)
+ if (state->offer == NULL || state->offer->yiaddr != ia->s_addr)
return;
- logdebugx("%s: DAD completed for %s",
- ifp->name, inet_ntoa(astate->addr));
- if (!(ifo->options & DHCPCD_INFORM))
+ logdebugx("%s: DAD completed for %s", ifp->name, inet_ntoa(*ia));
+ if (!(ifp->options->options & DHCPCD_INFORM))
dhcp_bind(ifp);
#ifndef IN_IFF_DUPLICATED
else {
@@ -2087,7 +1981,7 @@ dhcp_arp_probed(struct arp_state *astate
state->new = state->offer;
state->new_len = state->offer_len;
get_lease(ifp, &state->lease, state->new, state->new_len);
- ipv4_applyaddr(astate->iface);
+ ipv4_applyaddr(ifp);
state->new = bootp;
state->new_len = len;
}
@@ -2102,23 +1996,80 @@ dhcp_arp_probed(struct arp_state *astate
ipv4ll_drop(ifp);
#endif
- if (ifo->options & DHCPCD_INFORM)
+ if (ifp->options->options & DHCPCD_INFORM)
dhcp_inform(ifp);
}
+
+static void
+dhcp_addr_duplicated(struct interface *ifp, struct in_addr *ia)
+{
+ struct dhcp_state *state = D_STATE(ifp);
+#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;
+
+ /* 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)
+ dhcp_decline(ifp);
+#ifdef IN_IFF_DUPLICATED
+ if ((iap = ipv4_iffindaddr(ifp, ia, NULL)) != NULL)
+ ipv4_deladdr(iap, 0);
+#endif
+ eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+ eloop_timeout_add_sec(ifp->ctx->eloop,
+ DHCP_RAND_MAX, dhcp_discover, ifp);
+}
+
+#ifdef ARP
static void
-dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
+dhcp_arp_not_found(struct arp_state *astate)
{
struct interface *ifp;
struct dhcp_state *state;
-#ifdef ARPING
struct if_options *ifo;
-#endif
ifp = astate->iface;
state = D_STATE(ifp);
+ ifo = ifp->options;
+#ifdef ARPING
+ if (ifo->arping_len && state->arping_index < ifo->arping_len) {
+ /* We didn't find a profile for this
+ * address or hwaddr, so move to the next
+ * arping profile */
+ if (++state->arping_index < ifo->arping_len) {
+ astate->addr.s_addr =
+ ifo->arping[state->arping_index];
+ arp_probe(astate);
+ return;
+ }
+ arp_free(astate);
+ dhcpcd_startinterface(ifp);
+ return;
+ }
+#endif
+ dhcp_finish_dad(ifp, &astate->addr);
+}
+
+static void
+dhcp_arp_found(struct arp_state *astate, const struct arp_msg *amsg)
+{
+ struct in_addr addr;
#ifdef ARPING
+ struct interface *ifp;
+ struct dhcp_state *state;
+ struct if_options *ifo;
+
+ ifp = astate->iface;
+ state = D_STATE(ifp);
+
ifo = ifp->options;
if (state->arping_index != -1 &&
state->arping_index < ifo->arping_len &&
@@ -2127,17 +2078,14 @@ dhcp_arp_conflicted(struct arp_state *as
{
char buf[HWADDR_LEN * 3];
- astate->failed.s_addr = ifo->arping[state->arping_index];
- arp_report_conflicted(astate, amsg);
hwaddr_ntoa(amsg->sha, ifp->hwlen, buf, sizeof(buf));
if (dhcpcd_selectprofile(ifp, buf) == -1 &&
- dhcpcd_selectprofile(ifp,
- inet_ntoa(astate->failed)) == -1)
+ dhcpcd_selectprofile(ifp, inet_ntoa(amsg->sip)) == -1)
{
/* We didn't find a profile for this
* address or hwaddr, so move to the next
* arping profile */
- dhcp_arp_probed(astate);
+ dhcp_arp_not_found(astate);
return;
}
arp_free(astate);
@@ -2147,65 +2095,20 @@ dhcp_arp_conflicted(struct arp_state *as
}
#endif
- /* RFC 2131 3.1.5, Client-server interaction
- * NULL amsg means IN_IFF_DUPLICATED */
- if (amsg == NULL || (state->offer &&
- (amsg->sip.s_addr == state->offer->yiaddr ||
- (amsg->sip.s_addr == 0 &&
- amsg->tip.s_addr == state->offer->yiaddr))))
- {
-#ifdef IN_IFF_DUPLICATED
- struct ipv4_addr *ia;
-#endif
-
- if (amsg)
- astate->failed.s_addr = state->offer->yiaddr;
- else
- astate->failed = astate->addr;
- arp_report_conflicted(astate, amsg);
- unlink(state->leasefile);
-#ifdef ARP
- if (!(ifp->options->options & DHCPCD_STATIC) &&
- !state->lease.frominfo)
- dhcp_decline(ifp);
-#endif
-#ifdef IN_IFF_DUPLICATED
- if ((ia = ipv4_iffindaddr(ifp, &astate->addr, NULL)) != NULL)
- ipv4_deladdr(ia, 1);
-#endif
- arp_free(astate);
- eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
- eloop_timeout_add_sec(ifp->ctx->eloop,
- DHCP_RAND_MAX, dhcp_discover, ifp);
- return;
- }
-
- /* Bound address */
- if (amsg && state->addr &&
- amsg->sip.s_addr == state->addr->addr.s_addr)
- {
- astate->failed = state->addr->addr;
- arp_report_conflicted(astate, amsg);
- if (state->state == DHS_BOUND) {
- /* For now, just report the duplicated address */
- } else {
- arp_free(astate);
- dhcp_expire1(ifp);
- }
- return;
- }
+ addr = astate->addr;
+ arp_free(astate);
+ dhcp_addr_duplicated(ifp, &addr);
}
+#ifdef KERNEL_RFC5227
static void
dhcp_arp_announced(struct arp_state *state)
{
-// TODO: DHCP addresses handle ACD?
-//#ifdef KERNEL_RFC5227
arp_free(state);
-//#endif
}
-#endif
+#endif /* KERNEL_RFC5227 */
+#endif /* ARP */
void
dhcp_bind(struct interface *ifp)
@@ -2232,17 +2135,17 @@ dhcp_bind(struct interface *ifp)
loginfox("%s: using static address %s/%d",
ifp->name, inet_ntoa(lease->addr),
inet_ntocidr(lease->mask));
- lease->leasetime = ~0U;
+ lease->leasetime = DHCP_INFINITE_LIFETIME;
state->reason = "STATIC";
} else if (ifo->options & DHCPCD_INFORM) {
loginfox("%s: received approval for %s",
ifp->name, inet_ntoa(lease->addr));
- lease->leasetime = ~0U;
+ lease->leasetime = DHCP_INFINITE_LIFETIME;
state->reason = "INFORM";
} else {
if (lease->frominfo)
state->reason = "TIMEOUT";
- if (lease->leasetime == ~0U) {
+ if (lease->leasetime == DHCP_INFINITE_LIFETIME) {
lease->renewaltime =
lease->rebindtime =
lease->leasetime;
@@ -2305,7 +2208,7 @@ dhcp_bind(struct interface *ifp)
else
state->reason = "BOUND";
}
- if (lease->leasetime == ~0U)
+ if (lease->leasetime == DHCP_INFINITE_LIFETIME)
lease->renewaltime = lease->rebindtime = lease->leasetime;
else {
eloop_timeout_add_sec(ctx->eloop,
@@ -2359,12 +2262,6 @@ dhcp_lastlease(void *arg)
if (ifp->ctx->options & DHCPCD_FORKED)
return;
state->interval = 0;
- if (ifp->options->options & DHCPCD_LASTLEASE_EXTEND &&
- dhcp_leaseextend(ifp) == -1)
- {
- logerr("%s: %s", ifp->name, __func__);
- dhcp_expire(ifp);
- }
dhcp_discover(ifp);
}
@@ -2397,17 +2294,32 @@ dhcp_message_new(struct bootp **bootp,
}
#ifdef ARP
+#ifndef KERNEL_RFC5227
+static void
+dhcp_arp_defend_failed(struct arp_state *astate)
+{
+
+ dhcp_drop(astate->iface, "EXPIRED");
+ dhcp_start1(astate->iface);
+}
+#endif
+
static struct arp_state *
dhcp_arp_new(struct interface *ifp, struct in_addr *addr)
{
struct arp_state *astate;
+
astate = arp_new(ifp, addr);
if (astate == NULL)
return NULL;
- astate->probed_cb = dhcp_arp_probed;
- astate->conflicted_cb = dhcp_arp_conflicted;
+ astate->found_cb = dhcp_arp_found;
+ astate->not_found_cb = dhcp_arp_not_found;
+#ifdef KERNEL_RFC5227
astate->announced_cb = dhcp_arp_announced;
+#else
+ astate->defend_failed_cb = dhcp_arp_defend_failed;
+#endif
return astate;
}
@@ -2417,7 +2329,6 @@ dhcp_arp_address(struct interface *ifp)
struct dhcp_state *state;
struct in_addr addr;
struct ipv4_addr *ia;
- struct arp_state *astate;
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
@@ -2427,10 +2338,6 @@ dhcp_arp_address(struct interface *ifp)
/* If the interface already has the address configured
* then we can't ARP for duplicate detection. */
ia = ipv4_iffindaddr(ifp, &addr, NULL);
- astate = dhcp_arp_new(ifp, &addr);
- if (astate == NULL)
- return -1;
-
#ifdef IN_IFF_NOTUSEABLE
if (ia == NULL || ia->addr_flags & IN_IFF_NOTUSEABLE) {
state->state = DHS_PROBE;
@@ -2439,7 +2346,8 @@ dhcp_arp_address(struct interface *ifp)
get_lease(ifp, &l, state->offer, state->offer_len);
/* Add the address now, let the kernel handle DAD. */
- ipv4_addaddr(ifp, &l.addr, &l.mask, &l.brd);
+ ipv4_addaddr(ifp, &l.addr, &l.mask, &l.brd,
+ l.leasetime, l.rebindtime);
} else
loginfox("%s: waiting for DAD on %s",
ifp->name, inet_ntoa(addr));
@@ -2447,8 +2355,13 @@ dhcp_arp_address(struct interface *ifp)
}
#else
if (ifp->options->options & DHCPCD_ARP && ia == NULL) {
+ struct arp_state *astate;
struct dhcp_lease l;
+ astate = dhcp_arp_new(ifp, &addr);
+ if (astate == NULL)
+ return -1;
+
state->state = DHS_PROBE;
get_lease(ifp, &l, state->offer, state->offer_len);
loginfox("%s: probing address %s/%d",
@@ -2705,9 +2618,14 @@ dhcp_drop(struct interface *ifp, const c
return;
}
+#ifdef ARP
+ if (state->addr != NULL)
+ arp_freeaddr(ifp, &state->addr->addr);
+#endif
#ifdef ARPING
state->arping_index = -1;
#endif
+
if (ifp->options->options & DHCPCD_RELEASE &&
!(ifp->options->options & DHCPCD_INFORM))
{
@@ -3653,15 +3571,9 @@ dhcp_init(struct interface *ifp)
const struct if_options *ifo;
uint8_t len;
char buf[(sizeof(ifo->clientid) - 1) * 3];
- int r;
- r = dhcp_initstate(ifp);
- if (r == -1)
+ if (dhcp_initstate(ifp) == -1)
return -1;
- else if (r == 1) {
- /* Now is a good time to find IPv4 routes */
- if_initrt(ifp->ctx, AF_INET);
- }
state = D_STATE(ifp);
state->state = DHS_INIT;
@@ -3771,7 +3683,7 @@ dhcp_start1(void *arg)
astate = dhcp_arp_new(ifp, NULL);
if (astate)
- dhcp_arp_probed(astate);
+ dhcp_arp_not_found(astate);
return;
}
#endif
@@ -3848,7 +3760,7 @@ dhcp_start1(void *arg)
state->offer = NULL;
state->offer_len = 0;
} else if (!(ifo->options & DHCPCD_LASTLEASE_EXTEND) &&
- state->lease.leasetime != ~0U &&
+ state->lease.leasetime != DHCP_INFINITE_LIFETIME &&
stat(state->leasefile, &st) == 0)
{
time_t now;
@@ -4023,8 +3935,10 @@ dhcp_handleifa(int cmd, struct ipv4_addr
return;
#ifdef IN_IFF_NOTUSEABLE
- if (ia->addr_flags & IN_IFF_NOTUSEABLE)
- return;
+ 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);
#endif
ifo = ifp->options;
Index: src/external/bsd/dhcpcd/dist/src/dhcp6.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.8 src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.9
--- src/external/bsd/dhcpcd/dist/src/dhcp6.c:1.8 Wed Jun 26 17:47:47 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcp6.c Wed Jul 24 09:57:43 2019
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
/*
* dhcpcd - DHCP client daemon
* Copyright (c) 2006-2019 Roy Marples <[email protected]>
@@ -582,10 +583,14 @@ dhcp6_delegateaddr(struct in6_addr *addr
#define BIT(n) (1UL << (n))
#define BIT_MASK(len) (BIT(len) - 1)
- if (ia->sla_max == 0)
+ if (ia->sla_max == 0) {
/* Work out the real sla_max from our bits used */
- ia->sla_max = (uint32_t)BIT_MASK(asla.prefix_len -
- prefix->prefix_len);
+ bits = asla.prefix_len - prefix->prefix_len;
+ /* Make static analysis happy.
+ * Bits cannot be bigger than 32 thanks to fls32. */
+ assert(bits <= 32);
+ ia->sla_max = (uint32_t)BIT_MASK(bits);
+ }
}
if (ipv6_userprefix(&prefix->prefix, prefix->prefix_len,
@@ -2845,26 +2850,11 @@ dhcp6_delegate_prefix(struct interface *
struct dhcp6_state *s = D6_STATE(ifd);
ipv6_addaddrs(&s->addrs);
-
- /*
- * Can't add routes here because that will trigger
- * interface sorting which may break the current
- * enumeration.
- * This doesn't really matter thanks to DaD because
- * calling the script will be delayed and routes
- * will get re-built if needed first.
- * This only cause minor confusion when dhcpcd is
- * restarted and confirms a lease where prior delegation
- * has already been assigned, because it will log it
- * added routes after the script has run.
- * The routes should still be there and fine though.
- */
dhcp6_script_try_run(ifd, 1);
}
}
/* Now all addresses have been added, rebuild the routing table. */
- if_initrt(ifp->ctx, AF_INET6);
rt_build(ifp->ctx, AF_INET6);
}
@@ -2929,7 +2919,6 @@ dhcp6_find_delegates(struct interface *i
state = D6_STATE(ifp);
state->state = DH6S_DELEGATED;
ipv6_addaddrs(&state->addrs);
- if_initrt(ifp->ctx, AF_INET6);
rt_build(ifp->ctx, AF_INET6);
dhcp6_script_try_run(ifp, 1);
}
@@ -3167,7 +3156,6 @@ dhcp6_bind(struct interface *ifp, const
else
lognewinfo("%s: expire in %"PRIu32" seconds",
ifp->name, state->expire);
- if_initrt(ifp->ctx, AF_INET6);
rt_build(ifp->ctx, AF_INET6);
if (!timed_out)
dhcp6_writelease(ifp);
@@ -3971,24 +3959,22 @@ dhcp6_handleifa(int cmd, struct ipv6_add
}
ssize_t
-dhcp6_env(char **env, const char *prefix, const struct interface *ifp,
+dhcp6_env(FILE *fp, const char *prefix, const struct interface *ifp,
const struct dhcp6_message *m, size_t len)
{
const struct if_options *ifo;
struct dhcp_opt *opt, *vo;
const uint8_t *p;
struct dhcp6_option o;
- size_t i, n;
+ size_t i;
char *pfx;
uint32_t en;
const struct dhcpcd_ctx *ctx;
#ifndef SMALL
const struct dhcp6_state *state;
const struct ipv6_addr *ap;
- char *v, *val;
#endif
- n = 0;
if (m == NULL)
goto delegated;
@@ -4003,28 +3989,20 @@ dhcp6_env(char **env, const char *prefix
ctx = ifp->ctx;
/* Zero our indexes */
- if (env) {
- for (i = 0, opt = ctx->dhcp6_opts;
- i < ctx->dhcp6_opts_len;
- i++, opt++)
- dhcp_zero_index(opt);
- for (i = 0, opt = ifp->options->dhcp6_override;
- i < ifp->options->dhcp6_override_len;
- i++, opt++)
- dhcp_zero_index(opt);
- for (i = 0, opt = ctx->vivso;
- i < ctx->vivso_len;
- i++, opt++)
- dhcp_zero_index(opt);
- i = strlen(prefix) + strlen("_dhcp6") + 1;
- pfx = malloc(i);
- if (pfx == NULL) {
- logerr(__func__);
- return -1;
- }
- snprintf(pfx, i, "%s_dhcp6", prefix);
- } else
- pfx = NULL;
+ for (i = 0, opt = ctx->dhcp6_opts;
+ i < ctx->dhcp6_opts_len;
+ i++, opt++)
+ dhcp_zero_index(opt);
+ for (i = 0, opt = ifp->options->dhcp6_override;
+ i < ifp->options->dhcp6_override_len;
+ i++, opt++)
+ dhcp_zero_index(opt);
+ for (i = 0, opt = ctx->vivso;
+ i < ctx->vivso_len;
+ i++, opt++)
+ dhcp_zero_index(opt);
+ if (asprintf(&pfx, "%s_dhcp6", prefix) == -1)
+ return -1;
/* Unlike DHCP, DHCPv6 options *may* occur more than once.
* There is also no provision for option concatenation unlike DHCP. */
@@ -4070,15 +4048,13 @@ dhcp6_env(char **env, const char *prefix
opt = NULL;
}
if (opt) {
- n += dhcp_envoption(ifp->ctx,
- env == NULL ? NULL : &env[n],
- pfx, ifp->name,
+ dhcp_envoption(ifp->ctx,
+ fp, pfx, ifp->name,
opt, dhcp6_getoption, p, o.len);
}
if (vo) {
- n += dhcp_envoption(ifp->ctx,
- env == NULL ? NULL : &env[n],
- pfx, ifp->name,
+ dhcp_envoption(ifp->ctx,
+ fp, pfx, ifp->name,
vo, dhcp6_getoption,
p + sizeof(en),
o.len - sizeof(en));
@@ -4090,38 +4066,29 @@ delegated:
#ifndef SMALL
/* Needed for Delegated Prefixes */
state = D6_CSTATE(ifp);
- i = 0;
TAILQ_FOREACH(ap, &state->addrs, next) {
- if (ap->delegating_prefix) {
- i += strlen(ap->saddr) + 1;
- }
+ if (ap->delegating_prefix)
+ break;
}
- if (env && i) {
- i += strlen(prefix) + strlen("_delegated_dhcp6_prefix=");
- v = val = env[n] = malloc(i);
- if (v == NULL) {
- logerr(__func__);
- return -1;
- }
- v += snprintf(val, i, "%s_delegated_dhcp6_prefix=", prefix);
- TAILQ_FOREACH(ap, &state->addrs, next) {
- if (ap->delegating_prefix) {
- /* Can't use stpcpy(3) due to "security" */
- const char *sap = ap->saddr;
-
- do
- *v++ = *sap;
- while (*++sap != '\0');
- *v++ = ' ';
- }
+ if (ap == NULL)
+ return 1;
+ if (fprintf(fp, "%s_delegated_dhcp6_prefix=", prefix) == -1)
+ return -1;
+ TAILQ_FOREACH(ap, &state->addrs, next) {
+ if (ap->delegating_prefix == NULL)
+ continue;
+ if (ap != TAILQ_FIRST(&state->addrs)) {
+ if (fputc(' ', fp) == EOF)
+ return -1;
}
- *--v = '\0';
+ if (fprintf(fp, "%s", ap->saddr) == -1)
+ return -1;
}
- if (i)
- n++;
+ if (fputc('\0', fp) == EOF)
+ return -1;
#endif
- return (ssize_t)n;
+ return 1;
}
int
Index: src/external/bsd/dhcpcd/dist/src/if-bsd.c
diff -u src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.8 src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.9
--- src/external/bsd/dhcpcd/dist/src/if-bsd.c:1.8 Wed Jun 26 17:47:47 2019
+++ src/external/bsd/dhcpcd/dist/src/if-bsd.c Wed Jul 24 09:57:43 2019
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
/*
* BSD interface driver for dhcpcd
* Copyright (c) 2006-2019 Roy Marples <[email protected]>
@@ -496,6 +497,8 @@ if_route(unsigned char cmd, const struct
bool gateway_unspec;
assert(rt != NULL);
+ assert(rt->rt_ifp != NULL);
+ assert(rt->rt_ifp->ctx != NULL);
ctx = rt->rt_ifp->ctx;
#define ADDSA(sa) do { \
@@ -695,15 +698,13 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct
}
int
-if_initrt(struct dhcpcd_ctx *ctx, int af)
+if_initrt(struct dhcpcd_ctx *ctx, rb_tree_t *kroutes, int af)
{
struct rt_msghdr *rtm;
int mib[6];
size_t needed;
char *buf, *p, *end;
- struct rt rt;
-
- rt_headclear(&ctx->kroutes, af);
+ struct rt rt, *rtn;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
@@ -730,10 +731,15 @@ if_initrt(struct dhcpcd_ctx *ctx, int af
errno = EINVAL;
break;
}
- if (if_copyrt(ctx, &rt, rtm) == 0) {
- rt.rt_dflags |= RTDF_INIT;
- rt_recvrt(RTM_ADD, &rt, rtm->rtm_pid);
+ if (if_copyrt(ctx, &rt, rtm) != 0)
+ continue;
+ if ((rtn = rt_new(rt.rt_ifp)) == NULL) {
+ logerr(__func__);
+ break;
}
+ memcpy(rtn, &rt, sizeof(*rtn));
+ if (rb_tree_insert_node(kroutes, rtn) != rtn)
+ rt_free(rtn);
}
free(buf);
return p == end ? 0 : -1;
@@ -1063,7 +1069,7 @@ if_rtm(struct dhcpcd_ctx *ctx, const str
return 0;
if (if_copyrt(ctx, &rt, rtm) == -1)
- return errno == ENOTSUP ? 0 : -1;
+ return -1;
#ifdef INET6
/*
@@ -1306,7 +1312,6 @@ if_dispatch(struct dhcpcd_ctx *ctx, cons
#ifdef RTM_DESYNC
case RTM_DESYNC:
dhcpcd_linkoverflow(ctx);
- return 0;
#endif
}
@@ -1326,12 +1331,13 @@ if_handlelink(struct dhcpcd_ctx *ctx)
return -1;
if (len == 0)
return 0;
- if ((size_t)len < offsetof(struct rt_msghdr, rtm_index) ||
- len < rtm.hdr.rtm_msglen)
- {
+ if (len < rtm.hdr.rtm_msglen) {
errno = EINVAL;
return -1;
}
+ /* We generally treat rtm.hdr has an array so we can easily
+ * access the following data. */
+ /* coverity[callee_ptr_arith] */
return if_dispatch(ctx, &rtm.hdr);
}
Index: src/external/bsd/dhcpcd/dist/src/dhcpcd.c
diff -u src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.20 src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.21
--- src/external/bsd/dhcpcd/dist/src/dhcpcd.c:1.20 Wed Jun 26 17:47:47 2019
+++ src/external/bsd/dhcpcd/dist/src/dhcpcd.c Wed Jul 24 09:57:43 2019
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
/*
* dhcpcd - DHCP client daemon
* Copyright (c) 2006-2019 Roy Marples <[email protected]>
@@ -738,9 +739,6 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
#ifdef INET
dhcp_abort(ifp);
#endif
-#ifdef INET6
- ipv6nd_expire(ifp, 0);
-#endif
#ifdef DHCP6
dhcp6_abort(ifp);
#endif
@@ -785,7 +783,7 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *
/* Set any IPv6 Routers we remembered to expire
* faster than they would normally as we
* maybe on a new network. */
- ipv6nd_expire(ifp, RTR_CARRIER_EXPIRE);
+ ipv6nd_startexpire(ifp);
#endif
/* RFC4941 Section 3.5 */
ipv6_gentempifid(ifp);
@@ -1003,6 +1001,7 @@ dhcpcd_handleinterface(void *arg, int ac
struct if_head *ifs;
struct interface *ifp, *iff;
const char * const argv[] = { ifname };
+ int e;
ctx = arg;
if (action == -1) {
@@ -1026,13 +1025,17 @@ dhcpcd_handleinterface(void *arg, int ac
logerr(__func__);
return -1;
}
+
ifp = if_find(ifs, ifname);
if (ifp == NULL) {
/* This can happen if an interface is quickly added
* and then removed. */
errno = ENOENT;
- return -1;
+ e = -1;
+ goto out;
}
+ e = 1;
+
/* Check if we already have the interface */
iff = if_find(ctx->ifaces, ifp->name);
@@ -1061,6 +1064,7 @@ dhcpcd_handleinterface(void *arg, int ac
dhcpcd_prestartinterface(iff);
}
+out:
/* Free our discovered list */
while ((ifp = TAILQ_FIRST(ifs))) {
TAILQ_REMOVE(ifs, ifp, next);
@@ -1068,7 +1072,7 @@ dhcpcd_handleinterface(void *arg, int ac
}
free(ifs);
- return 1;
+ return e;
}
static void
@@ -1081,7 +1085,8 @@ dhcpcd_handlelink(void *arg)
dhcpcd_linkoverflow(ctx);
return;
}
- logerr(__func__);
+ if (errno != ENOTSUP)
+ logerr(__func__);
}
}
@@ -1093,6 +1098,22 @@ dhcpcd_checkcarrier(void *arg)
dhcpcd_handlecarrier(ifp->ctx, LINK_UNKNOWN, ifp->flags, ifp->name);
}
+#ifndef SMALL
+static void
+dhcpcd_setlinkrcvbuf(struct dhcpcd_ctx *ctx)
+{
+ socklen_t socklen;
+
+ if (ctx->link_rcvbuf == 0)
+ return;
+
+ socklen = sizeof(ctx->link_rcvbuf);
+ if (setsockopt(ctx->link_fd, SOL_SOCKET,
+ SO_RCVBUF, &ctx->link_rcvbuf, socklen) == -1)
+ logerr(__func__);
+}
+#endif
+
void
dhcpcd_linkoverflow(struct dhcpcd_ctx *ctx)
{
@@ -1113,10 +1134,17 @@ dhcpcd_linkoverflow(struct dhcpcd_ctx *c
eloop_exit(ctx->eloop, EXIT_FAILURE);
return;
}
+#ifndef SMALL
+ dhcpcd_setlinkrcvbuf(ctx);
+#endif
eloop_event_add(ctx->eloop, ctx->link_fd, dhcpcd_handlelink, ctx);
/* Work out the current interfaces. */
ifaces = if_discover(ctx, &ifaddrs, ctx->ifc, ctx->ifv);
+ if (ifaces == NULL) {
+ logerr(__func__);
+ return;
+ }
/* Punt departed interfaces */
TAILQ_FOREACH_SAFE(ifp, ctx->ifaces, next, ifn) {
@@ -1126,21 +1154,23 @@ dhcpcd_linkoverflow(struct dhcpcd_ctx *c
}
/* Add new interfaces */
- TAILQ_FOREACH_SAFE(ifp, ifaces, next, ifn) {
+ while ((ifp = TAILQ_FIRST(ifaces)) != NULL ) {
+ TAILQ_REMOVE(ifaces, ifp, next);
ifp1 = if_find(ctx->ifaces, ifp->name);
if (ifp1 != NULL) {
/* If the interface already exists,
* check carrier state. */
eloop_timeout_add_sec(ctx->eloop, 0,
dhcpcd_checkcarrier, ifp1);
+ if_free(ifp);
continue;
}
- TAILQ_REMOVE(ifaces, ifp, next);
TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
if (ifp->active)
eloop_timeout_add_sec(ctx->eloop, 0,
dhcpcd_prestartinterface, ifp);
}
+ free(ifaces);
/* Update address state. */
if_markaddrsstale(ctx->ifaces);
@@ -1958,6 +1988,9 @@ printpidfile:
logerr("%s: if_opensockets", __func__);
goto exit_failure;
}
+#ifndef SMALL
+ dhcpcd_setlinkrcvbuf(&ctx);
+#endif
/* When running dhcpcd against a single interface, we need to retain
* the old behaviour of waiting for an IP address */
@@ -2057,7 +2090,6 @@ printpidfile:
free_options(&ctx, ifo);
ifo = NULL;
- if_sortinterfaces(&ctx);
TAILQ_FOREACH(ifp, ctx.ifaces, next) {
if (ifp->active)
eloop_timeout_add_sec(ctx.eloop, 0,
@@ -2114,5 +2146,11 @@ exit1:
if (ctx.options & DHCPCD_FORKED)
_exit(i); /* so atexit won't remove our pidfile */
#endif
+#ifdef HAVE_OPEN_MEMSTREAM
+ if (ctx.script_fp)
+ fclose(ctx.script_fp);
+#endif
+ free(ctx.script_buf);
+ free(ctx.script_env);
return i;
}
Index: src/external/bsd/dhcpcd/dist/src/if-options.c
diff -u src/external/bsd/dhcpcd/dist/src/if-options.c:1.14 src/external/bsd/dhcpcd/dist/src/if-options.c:1.15
--- src/external/bsd/dhcpcd/dist/src/if-options.c:1.14 Sat May 4 09:42:15 2019
+++ src/external/bsd/dhcpcd/dist/src/if-options.c Wed Jul 24 09:57:43 2019
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
/*
* dhcpcd - DHCP client daemon
* Copyright (c) 2006-2019 Roy Marples <[email protected]>
@@ -64,7 +65,7 @@
#define O_IPV6RS O_BASE + 4
#define O_NOIPV6RS O_BASE + 5
#define O_IPV6RA_FORK O_BASE + 6
-// unused O_BASE + 7
+#define O_LINK_RCVBUF O_BASE + 7
// unused O_BASE + 8
#define O_NOALIAS O_BASE + 9
#define O_IA_NA O_BASE + 10
@@ -204,6 +205,7 @@ const struct option cf_options[] = {
{"lastleaseextend", no_argument, NULL, O_LASTLEASE_EXTEND},
{"inactive", no_argument, NULL, O_INACTIVE},
{"mudurl", required_argument, NULL, O_MUDURL},
+ {"link_rcvbuf", required_argument, NULL, O_LINK_RCVBUF},
{NULL, 0, NULL, '\0'}
};
@@ -724,8 +726,9 @@ parse_option(struct dhcpcd_ctx *ctx, con
logerr(__func__);
return -1;
}
- parse_str(ifo->script, dl, arg, PARSE_STRING_NULL);
- if (ifo->script[0] == '\0' ||
+ s = parse_str(ifo->script, dl, arg, PARSE_STRING_NULL);
+ if (s == -1 ||
+ ifo->script[0] == '\0' ||
strcmp(ifo->script, "/dev/null") == 0)
{
free(ifo->script);
@@ -1122,16 +1125,14 @@ parse_option(struct dhcpcd_ctx *ctx, con
*fp = ' ';
return -1;
}
- if ((rt = rt_new0(ctx)) == NULL) {
- *fp = ' ';
+ *fp = ' ';
+ if ((rt = rt_new0(ctx)) == NULL)
return -1;
- }
sa_in_init(&rt->rt_dest, &addr);
sa_in_init(&rt->rt_netmask, &addr2);
sa_in_init(&rt->rt_gateway, &addr3);
- TAILQ_INSERT_TAIL(&ifo->routes, rt, rt_next);
- *fp = ' ';
- add_environ(&ifo->config, arg, 0);
+ if (rt_proto_add_ctx(&ifo->routes, rt, ctx))
+ add_environ(&ifo->config, arg, 0);
} else if (strncmp(arg, "routers=", strlen("routers=")) == 0) {
if (parse_addr(&addr, NULL, p) == -1)
return -1;
@@ -1141,8 +1142,8 @@ parse_option(struct dhcpcd_ctx *ctx, con
sa_in_init(&rt->rt_dest, &addr2);
sa_in_init(&rt->rt_netmask, &addr2);
sa_in_init(&rt->rt_gateway, &addr);
- TAILQ_INSERT_TAIL(&ifo->routes, rt, rt_next);
- add_environ(&ifo->config, arg, 0);
+ if (rt_proto_add_ctx(&ifo->routes, rt, ctx))
+ add_environ(&ifo->config, arg, 0);
} else if (strncmp(arg, "interface_mtu=",
strlen("interface_mtu=")) == 0 ||
strncmp(arg, "mtu=", strlen("mtu=")) == 0)
@@ -1868,6 +1869,7 @@ err_sla:
ifo->vivco_len + 1, sizeof(*ifo->vivco));
if (vivco == NULL) {
logerr( __func__);
+ free(np);
return -1;
}
ifo->vivco = vivco;
@@ -2160,6 +2162,16 @@ err_sla:
}
*ifo->mudurl = (uint8_t)s;
break;
+ case O_LINK_RCVBUF:
+#ifndef SMALL
+ ARG_REQUIRED;
+ ctx->link_rcvbuf = (int)strtoi(arg, NULL, 0, 0, INT32_MAX, &e);
+ if (e) {
+ logerrx("failed to convert link_rcvbuf %s", arg);
+ return -1;
+ }
+#endif
+ break;
default:
return 0;
}
@@ -2269,7 +2281,7 @@ default_config(struct dhcpcd_ctx *ctx)
ifo->script = UNCONST(default_script);
ifo->metric = -1;
ifo->auth.options |= DHCPCD_AUTH_REQUIRE;
- TAILQ_INIT(&ifo->routes);
+ rb_tree_init(&ifo->routes, &rt_compare_proto_ops);
#ifdef AUTH
TAILQ_INIT(&ifo->auth.tokens);
#endif
@@ -2327,6 +2339,9 @@ read_config(struct dhcpcd_ctx *ctx,
buf = NULL;
buflen = 0;
+ /* Reset route order */
+ ctx->rt_order = 0;
+
/* Parse our embedded options file */
if (ifname == NULL && !(ctx->options & DHCPCD_PRINT_PIDFILE)) {
/* Space for initial estimates */
Index: src/external/bsd/dhcpcd/dist/src/ipv6nd.c
diff -u src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.7 src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.8
--- src/external/bsd/dhcpcd/dist/src/ipv6nd.c:1.7 Wed Jun 26 17:47:47 2019
+++ src/external/bsd/dhcpcd/dist/src/ipv6nd.c Wed Jul 24 09:57:43 2019
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
/*
* dhcpcd - IPv6 ND handling
* Copyright (c) 2006-2019 Roy Marples <[email protected]>
@@ -105,6 +106,9 @@ __CTASSERT(sizeof(struct nd_opt_rdnss) =
#define RTPREF_RESERVED (-2)
#define RTPREF_INVALID (-3) /* internal */
+#define EXPIRED_MAX 5 /* Remember 5 expired routers to avoid
+ logspam. */
+
#define MIN_RANDOM_FACTOR 500 /* millisecs */
#define MAX_RANDOM_FACTOR 1500 /* millisecs */
#define MIN_RANDOM_FACTOR_U MIN_RANDOM_FACTOR * 1000 /* usecs */
@@ -462,7 +466,6 @@ ipv6nd_advertise(struct ipv6_addr *ia)
return;
ctx = ia->iface->ctx;
- if_sortinterfaces(ctx);
/* Find the most preferred address to advertise. */
iaf = NULL;
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
@@ -483,7 +486,8 @@ ipv6nd_advertise(struct ipv6_addr *ia)
iap->addr_flags & IN6_IFF_NOTUSEABLE)
continue;
- if (iaf == NULL)
+ if (iaf == NULL ||
+ iaf->iface->metric > iap->iface->metric)
iaf = iap;
}
}
@@ -523,46 +527,34 @@ ipv6nd_advertise(struct ipv6_addr *ia)
ipv6nd_sendadvertisement(iaf);
}
-void
-ipv6nd_expire(struct interface *ifp, uint32_t seconds)
+static void
+ipv6nd_expire(void *arg)
{
+ struct interface *ifp = arg;
struct ra *rap;
- struct timespec now;
- uint32_t vltime = seconds;
- uint32_t pltime = seconds / 2;
+ struct ipv6_addr *ia;
+ struct timespec now = { .tv_sec = 1 };
if (ifp->ctx->ra_routers == NULL)
return;
- clock_gettime(CLOCK_MONOTONIC, &now);
-
TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
- if (rap->iface == ifp) {
- rap->acquired = now;
- rap->expired = seconds ? 0 : 1;
- if (seconds) {
- struct ipv6_addr *ia;
-
- rap->lifetime = seconds;
- TAILQ_FOREACH(ia, &rap->addrs, next) {
- if (ia->prefix_pltime > pltime ||
- ia->prefix_vltime > vltime)
- {
- ia->acquired = now;
- if (ia->prefix_pltime != 0)
- ia->prefix_pltime =
- pltime;
- ia->prefix_vltime = vltime;
- }
- }
- ipv6_addaddrs(&rap->addrs);
- }
+ if (rap->iface == ifp)
+ continue;
+ rap->acquired = now;
+ TAILQ_FOREACH(ia, &rap->addrs, next) {
+ ia->acquired = now;
}
}
- if (seconds)
- ipv6nd_expirera(ifp);
- else
- rt_build(ifp->ctx, AF_INET6);
+ ipv6nd_expirera(ifp);
+}
+
+void
+ipv6nd_startexpire(struct interface *ifp)
+{
+
+ eloop_timeout_add_sec(ifp->ctx->eloop, RTR_CARRIER_EXPIRE,
+ ipv6nd_expire, ifp);
}
static void
@@ -1228,6 +1220,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
break;
case ND_OPT_MTU:
+ if (len < sizeof(mtu)) {
+ logerrx("%s: short MTU option", ifp->name);
+ break;
+ }
memcpy(&mtu, p, sizeof(mtu));
mtu.nd_opt_mtu_mtu = ntohl(mtu.nd_opt_mtu_mtu);
if (mtu.nd_opt_mtu_mtu < IPV6_MMTU) {
@@ -1239,6 +1235,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
break;
case ND_OPT_RDNSS:
+ if (len < sizeof(rdnss)) {
+ logerrx("%s: short RDNSS option", ifp->name);
+ break;
+ }
memcpy(&rdnss, p, sizeof(rdnss));
if (rdnss.nd_opt_rdnss_lifetime &&
rdnss.nd_opt_rdnss_len > 1)
@@ -1278,11 +1278,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
ipv6_addtempaddrs(ifp, &rap->acquired);
#endif
- /* Find any freshly added routes, such as the subnet route.
- * We do this because we cannot rely on recieving the kernel
- * notification right now via our link socket. */
- if_initrt(ifp->ctx, AF_INET6);
-
rt_build(ifp->ctx, AF_INET6);
if (ipv6nd_scriptrun(rap))
return;
@@ -1390,11 +1385,11 @@ ipv6nd_getoption(struct dhcpcd_ctx *ctx,
}
ssize_t
-ipv6nd_env(char **env, const char *prefix, const struct interface *ifp)
+ipv6nd_env(FILE *fp, const struct interface *ifp)
{
size_t i, j, n, len, olen;
struct ra *rap;
- char ndprefix[32], abuf[24];
+ char ndprefix[32];
struct dhcp_opt *opt;
uint8_t *p;
struct nd_opt_hdr ndo;
@@ -1407,34 +1402,25 @@ ipv6nd_env(char **env, const char *prefi
if (rap->iface != ifp)
continue;
i++;
- if (prefix != NULL)
- snprintf(ndprefix, sizeof(ndprefix),
- "%s_nd%zu", prefix, i);
- else
- snprintf(ndprefix, sizeof(ndprefix),
- "nd%zu", i);
- if (env)
- setvar(&env[n], ndprefix, "from", rap->sfrom);
- n++;
- if (env)
- setvard(&env[n], ndprefix, "acquired",
- (size_t)rap->acquired.tv_sec);
- n++;
- if (env)
- setvard(&env[n], ndprefix, "now", (size_t)now.tv_sec);
- n++;
+ snprintf(ndprefix, sizeof(ndprefix), "nd%zu", i);
+ if (efprintf(fp, "%s_from=%s", ndprefix, rap->sfrom) == -1)
+ return -1;
+ if (efprintf(fp, "%s_acquired=%lld", ndprefix,
+ (long long)rap->acquired.tv_sec) == -1)
+ return -1;
+ if (efprintf(fp, "%s_now=%lld", ndprefix,
+ (long long)now.tv_sec) == -1)
+ return -1;
/* Zero our indexes */
- if (env) {
- for (j = 0, opt = rap->iface->ctx->nd_opts;
- j < rap->iface->ctx->nd_opts_len;
- j++, opt++)
- dhcp_zero_index(opt);
- for (j = 0, opt = rap->iface->options->nd_override;
- j < rap->iface->options->nd_override_len;
- j++, opt++)
- dhcp_zero_index(opt);
- }
+ for (j = 0, opt = rap->iface->ctx->nd_opts;
+ j < rap->iface->ctx->nd_opts_len;
+ j++, opt++)
+ dhcp_zero_index(opt);
+ for (j = 0, opt = rap->iface->options->nd_override;
+ j < rap->iface->options->nd_override_len;
+ j++, opt++)
+ dhcp_zero_index(opt);
/* Unlike DHCP, ND6 options *may* occur more than once.
* There is also no provision for option concatenation
@@ -1467,34 +1453,31 @@ ipv6nd_env(char **env, const char *prefi
if (j == rap->iface->ctx->nd_opts_len)
opt = NULL;
}
- if (opt) {
- n += dhcp_envoption(rap->iface->ctx,
- env == NULL ? NULL : &env[n],
- ndprefix, rap->iface->name,
- opt, ipv6nd_getoption,
- p + sizeof(ndo), olen - sizeof(ndo));
- }
+ if (opt == NULL)
+ continue;
+ dhcp_envoption(rap->iface->ctx, fp,
+ ndprefix, rap->iface->name,
+ opt, ipv6nd_getoption,
+ p + sizeof(ndo), olen - sizeof(ndo));
}
/* We need to output the addresses we actually made
* from the prefix information options as well. */
j = 0;
TAILQ_FOREACH(ia, &rap->addrs, next) {
- if (!(ia->flags & IPV6_AF_AUTOCONF)
+ if (!(ia->flags & IPV6_AF_AUTOCONF) ||
#ifdef IPV6_AF_TEMPORARY
- || ia->flags & IPV6_AF_TEMPORARY
+ ia->flags & IPV6_AF_TEMPORARY ||
#endif
- )
+ !(ia->flags & IPV6_AF_ADDED) ||
+ ia->prefix_vltime == 0)
continue;
- j++;
- if (env) {
- snprintf(abuf, sizeof(abuf), "addr%zu", j);
- setvar(&env[n], ndprefix, abuf, ia->saddr);
- }
- n++;
+ if (efprintf(fp, "%s_addr%zu=%s",
+ ndprefix, j++, ia->saddr) == -1)
+ return -1;
}
}
- return (ssize_t)n;
+ return 1;
}
void
@@ -1522,6 +1505,16 @@ ipv6nd_expirera(void *arg)
struct timespec now, lt, expire, next;
bool expired, valid, validone;
struct ipv6_addr *ia;
+ size_t len, olen;
+ uint8_t *p;
+ struct nd_opt_hdr ndo;
+#if 0
+ struct nd_opt_prefix_info pi;
+#endif
+ struct nd_opt_dnssl dnssl;
+ struct nd_opt_rdnss rdnss;
+ uint32_t ltime;
+ size_t nexpired = 0;
ifp = arg;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -1536,8 +1529,7 @@ ipv6nd_expirera(void *arg)
lt.tv_sec = (time_t)rap->lifetime;
lt.tv_nsec = 0;
timespecadd(&rap->acquired, <, &expire);
- if (rap->lifetime == 0 || timespeccmp(&now, &expire, >))
- {
+ if (timespeccmp(&now, &expire, >)) {
if (!rap->expired) {
logwarnx("%s: %s: router expired",
ifp->name, rap->sfrom);
@@ -1588,14 +1580,79 @@ ipv6nd_expirera(void *arg)
}
}
- /* XXX FixMe!
- * We need to extract the lifetime from each option and check
- * if that has expired or not.
- * If it has, zero the option out in the returned data. */
-
- /* No valid lifetimes are left on the RA, so we might
- * as well punt it. */
- if (!valid && !validone)
+ /* Work out expiry for ND options */
+ len = rap->data_len - sizeof(struct nd_router_advert);
+ for (p = rap->data + sizeof(struct nd_router_advert);
+ len >= sizeof(ndo);
+ p += olen, len -= olen)
+ {
+ memcpy(&ndo, p, sizeof(ndo));
+ olen = (size_t)(ndo.nd_opt_len * 8);
+ if (olen > len) {
+ errno = EINVAL;
+ break;
+ }
+
+ if (has_option_mask(rap->iface->options->nomasknd,
+ ndo.nd_opt_type))
+ continue;
+
+ switch (ndo.nd_opt_type) {
+ /* Prefix info is already checked in the above loop. */
+#if 0
+ case ND_OPT_PREFIX_INFORMATION:
+ if (len < sizeof(pi))
+ break;
+ memcpy(&pi, p, sizeof(pi));
+ ltime = pi.nd_opt_pi_valid_time;
+ break;
+#endif
+ case ND_OPT_DNSSL:
+ if (len < sizeof(dnssl))
+ continue;
+ memcpy(&dnssl, p, sizeof(dnssl));
+ ltime = dnssl.nd_opt_dnssl_lifetime;
+ break;
+ case ND_OPT_RDNSS:
+ if (len < sizeof(rdnss))
+ continue;
+ memcpy(&rdnss, p, sizeof(rdnss));
+ ltime = rdnss.nd_opt_rdnss_lifetime;
+ break;
+ default:
+ continue;
+ }
+
+ if (ltime == 0)
+ continue;
+ if (ltime == ND6_INFINITE_LIFETIME) {
+ validone = true;
+ continue;
+ }
+
+ lt.tv_sec = (time_t)ntohl(ltime);
+ lt.tv_nsec = 0;
+ timespecadd(&rap->acquired, <, &expire);
+ if (timespeccmp(&now, &expire, >)) {
+ expired = true;
+ continue;
+ }
+
+ timespecsub(&expire, &now, <);
+ if (!timespecisset(&next) ||
+ timespeccmp(&next, <, >))
+ {
+ next = lt;
+ validone = true;
+ }
+ }
+
+ if (valid || validone)
+ continue;
+
+ /* Router has expired. Let's not keep a lot of them.
+ * We should work out if all the options have expired .... */
+ if (++nexpired > EXPIRED_MAX)
ipv6nd_free_ra(rap);
}
@@ -1603,6 +1660,7 @@ ipv6nd_expirera(void *arg)
eloop_timeout_add_tv(ifp->ctx->eloop,
&next, ipv6nd_expirera, ifp);
if (expired) {
+ logwarnx("%s: part of Router Advertisement expired", ifp->name);
rt_build(ifp->ctx, AF_INET6);
script_runreason(ifp, "ROUTERADVERT");
}