Sync
This commit is contained in:
parent
b4e670c413
commit
b6fb16d89c
|
@ -1,11 +0,0 @@
|
|||
# setup chroot mounts
|
||||
|
||||
if [ "$reason" = CHROOT ] && [ -n "$chroot" ]; then
|
||||
for d in /dev /proc /sys /run/udev; do
|
||||
[ -d "$d" ] || continue
|
||||
if ! mountpoint -q "$chroot$d"; then
|
||||
mkdir -p "$chroot$d"
|
||||
mount --bind $d "$chroot$d"
|
||||
fi
|
||||
done
|
||||
fi
|
|
@ -1,8 +0,0 @@
|
|||
# Just echo our DHCP options we have
|
||||
|
||||
case "$reason" in
|
||||
DUMP|DUMP6)
|
||||
set | sed -ne 's/^new_//p' | sort
|
||||
exit 0
|
||||
;;
|
||||
esac
|
|
@ -2301,7 +2301,7 @@ dhcp_bind(struct interface *ifp)
|
|||
if (!state->lease.frominfo &&
|
||||
!(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)))
|
||||
if (write_lease(ifp, state->new, state->new_len) == -1)
|
||||
logerr(__func__);
|
||||
logerr("write_lease: %s", state->leasefile);
|
||||
|
||||
/* Close the BPF filter as we can now receive DHCP messages
|
||||
* on a UDP socket. */
|
||||
|
@ -3370,7 +3370,7 @@ is_packet_udp_bootp(void *packet, size_t plen)
|
|||
memcpy(&udp, (char *)ip + ip_hlen, sizeof(udp));
|
||||
if (ntohs(udp.uh_ulen) < sizeof(udp))
|
||||
return false;
|
||||
if (ip_hlen + (size_t)ntohs(udp.uh_ulen) > plen)
|
||||
if (ip_hlen + ntohs(udp.uh_ulen) > plen)
|
||||
return false;
|
||||
|
||||
/* Check it's to and from the right ports. */
|
||||
|
|
|
@ -2503,10 +2503,8 @@ dhcp6_writelease(const struct interface *ifp)
|
|||
logdebugx("%s: writing lease `%s'", ifp->name, state->leasefile);
|
||||
|
||||
fd = open(state->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd == -1) {
|
||||
logerr(__func__);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
}
|
||||
bytes = write(fd, state->new, state->new_len);
|
||||
close(fd);
|
||||
return bytes;
|
||||
|
@ -2710,7 +2708,7 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
|
|||
vl |= sla->suffix;
|
||||
be64enc(daddr.s6_addr + 8, vl);
|
||||
} else {
|
||||
dadcounter = ipv6_makeaddr(&daddr, ifp, &addr, pfxlen);
|
||||
dadcounter = ipv6_makeaddr(&daddr, ifp, &addr, pfxlen, 0);
|
||||
if (dadcounter == -1) {
|
||||
logerrx("%s: error adding slaac to prefix_len %d",
|
||||
ifp->name, pfxlen);
|
||||
|
@ -3162,7 +3160,8 @@ dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom)
|
|||
ifp->name, state->expire);
|
||||
rt_build(ifp->ctx, AF_INET6);
|
||||
if (!confirmed && !timedout)
|
||||
dhcp6_writelease(ifp);
|
||||
if (dhcp6_writelease(ifp) == -1)
|
||||
logerr("dhcp6_writelease: %s",state->leasefile);
|
||||
#ifndef SMALL
|
||||
dhcp6_delegate_prefix(ifp);
|
||||
#endif
|
||||
|
|
|
@ -781,8 +781,10 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
|
|||
* maybe on a new network. */
|
||||
ipv6nd_startexpire(ifp);
|
||||
#endif
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
/* RFC4941 Section 3.5 */
|
||||
ipv6_gentempifid(ifp);
|
||||
ipv6_regentempaddrs(ifp);
|
||||
#endif
|
||||
#endif
|
||||
dhcpcd_startinterface(ifp);
|
||||
}
|
||||
|
@ -1552,26 +1554,39 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
|
|||
ctx->options |= DHCPCD_DUMPLEASE;
|
||||
size_t nifaces = 0;
|
||||
|
||||
for (oi = optind; oi < argc; oi++) {
|
||||
if ((ifp = if_find(ctx->ifaces, argv[oi])) == NULL)
|
||||
continue;
|
||||
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
|
||||
if (!ifp->active)
|
||||
continue;
|
||||
opt = send_interface(NULL, ifp, af);
|
||||
if (opt != -1)
|
||||
for (oi = optind; oi < argc; oi++) {
|
||||
if (strcmp(ifp->name, argv[oi]) == 0)
|
||||
break;
|
||||
}
|
||||
if (optind == argc || oi < argc) {
|
||||
opt = send_interface(NULL, ifp, af);
|
||||
if (opt == -1)
|
||||
goto dumperr;
|
||||
nifaces += (size_t)opt;
|
||||
}
|
||||
}
|
||||
if (write(fd->fd, &nifaces, sizeof(nifaces)) != sizeof(nifaces))
|
||||
return -1;
|
||||
for (oi = optind; oi < argc; oi++) {
|
||||
if ((ifp = if_find(ctx->ifaces, argv[oi])) == NULL)
|
||||
continue;
|
||||
goto dumperr;
|
||||
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
|
||||
if (!ifp->active)
|
||||
continue;
|
||||
send_interface(fd, ifp, af);
|
||||
for (oi = optind; oi < argc; oi++) {
|
||||
if (strcmp(ifp->name, argv[oi]) == 0)
|
||||
break;
|
||||
}
|
||||
if (optind == argc || oi < argc) {
|
||||
if (send_interface(fd, ifp, af) == -1)
|
||||
goto dumperr;
|
||||
}
|
||||
}
|
||||
ctx->options &= ~DHCPCD_DUMPLEASE;
|
||||
return 0;
|
||||
dumperr:
|
||||
ctx->options &= ~DHCPCD_DUMPLEASE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Only privileged users can control dhcpcd via the socket. */
|
||||
|
@ -1618,14 +1633,20 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char *dumpskip[] = {
|
||||
"PATH=",
|
||||
"pid=",
|
||||
"chroot=",
|
||||
};
|
||||
|
||||
static int
|
||||
dhcpcd_readdump(struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
int error = 0;
|
||||
size_t nifaces, buflen = 0, dlen;
|
||||
size_t nifaces, buflen = 0, dlen, i;
|
||||
ssize_t len;
|
||||
char *buf = NULL, *dp, *de;
|
||||
bool print;
|
||||
const char *skip;
|
||||
|
||||
again1:
|
||||
len = read(ctx->control_fd, &nifaces, sizeof(nifaces));
|
||||
|
@ -1660,6 +1681,11 @@ again2:
|
|||
buf = nbuf;
|
||||
buflen = dlen;
|
||||
}
|
||||
if (dlen == 0) {
|
||||
errno = EINVAL;
|
||||
error = -1;
|
||||
goto out;
|
||||
}
|
||||
again3:
|
||||
if (read(ctx->control_fd, buf, dlen) != (ssize_t)dlen) {
|
||||
if (errno == EAGAIN)
|
||||
|
@ -1669,28 +1695,23 @@ again3:
|
|||
}
|
||||
dp = buf;
|
||||
de = dp + dlen;
|
||||
if (*(dp - 1) != '\0') {
|
||||
errno = EINVAL;
|
||||
error = -1;
|
||||
goto out;
|
||||
}
|
||||
while (dp < de) {
|
||||
if (dp + 6 >= de) /* _new and = something */
|
||||
break;
|
||||
if (dp[0] == 'n' && dp[3] == '_') {
|
||||
if (dp[1] == 'e' && dp[2] == 'w') {
|
||||
print = true;
|
||||
dp += 4;
|
||||
} else if (dp[1] == 'd' &&
|
||||
isdigit((unsigned char)dp[2]))
|
||||
print = true;
|
||||
else
|
||||
print = false;
|
||||
} else
|
||||
print = false;
|
||||
while (dp < de && *dp != '\0') {
|
||||
if (print)
|
||||
putchar(*dp);
|
||||
dp++;
|
||||
for (i = 0; i < __arraycount(dumpskip); i++) {
|
||||
skip = dumpskip[i];
|
||||
if (strncmp(dp, skip, strlen(skip)) == 0)
|
||||
break;
|
||||
}
|
||||
if (print)
|
||||
putchar('\n');
|
||||
dp++;
|
||||
if (i == __arraycount(dumpskip)) {
|
||||
if (strncmp(dp, "new_", 4) == 0)
|
||||
dp += 4;
|
||||
printf("%s\n", dp);
|
||||
}
|
||||
dp += strlen(dp) + 1;
|
||||
}
|
||||
fflush(stdout);
|
||||
if (nifaces != 1)
|
||||
|
@ -2107,16 +2128,11 @@ printpidfile:
|
|||
}
|
||||
#endif
|
||||
|
||||
logdebugx(PACKAGE "-" VERSION " starting");
|
||||
loginfox(PACKAGE "-" VERSION " starting");
|
||||
freopen(_PATH_DEVNULL, "r", stdin);
|
||||
|
||||
#ifdef PRIVSEP
|
||||
if (ps_init(&ctx) == -1) {
|
||||
if (errno != 0) {
|
||||
logerr("ps_init");
|
||||
goto exit_failure;
|
||||
}
|
||||
} else
|
||||
if (ps_init(&ctx) == 0)
|
||||
script_runchroot(&ctx, ifo->script);
|
||||
#endif
|
||||
|
||||
|
@ -2169,7 +2185,7 @@ printpidfile:
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSD
|
||||
#if defined(BSD) && defined(INET6)
|
||||
/* Disable the kernel RTADV sysctl as early as possible. */
|
||||
if (ctx.options & DHCPCD_IPV6 && ctx.options & DHCPCD_IPV6RS)
|
||||
if_disable_rtadv();
|
||||
|
|
|
@ -1037,7 +1037,7 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia)
|
|||
if (ia->addr_flags & IN6_IFF_TENTATIVE)
|
||||
ifa.ifra_flags |= IN6_IFF_TENTATIVE;
|
||||
#endif
|
||||
#ifdef IPV6_MANGETEMPADDR
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
if (ia->flags & IPV6_AF_TEMPORARY)
|
||||
ifa.ifra_flags |= IN6_IFF_TEMPORARY;
|
||||
#endif
|
||||
|
@ -1524,6 +1524,8 @@ if_missfilter0(struct dhcpcd_ctx *ctx, struct interface *ifp,
|
|||
#ifdef INET6
|
||||
if (sa->sa_family == AF_INET6)
|
||||
ifa_setscope(satosin6(sa), ifp->index);
|
||||
#else
|
||||
UNUSED(ifp);
|
||||
#endif
|
||||
|
||||
cp = ctx->rt_missfilter + ctx->rt_missfilterlen;
|
||||
|
@ -1728,14 +1730,14 @@ int
|
|||
ip6_temp_preferred_lifetime(__unused const char *ifname)
|
||||
{
|
||||
|
||||
return ND6_PRIV_PREFERRED_LIFETIME;
|
||||
return TEMP_PREFERRED_LIFETIME;
|
||||
}
|
||||
|
||||
int
|
||||
ip6_temp_valid_lifetime(__unused const char *ifname)
|
||||
{
|
||||
|
||||
return ND6_PRIV_VALID_LIFETIME;
|
||||
return TEMP_VALID_LIFETIME;
|
||||
}
|
||||
|
||||
#else /* __OpenBSD__ */
|
||||
|
|
|
@ -573,6 +573,8 @@ set_option_space(struct dhcpcd_ctx *ctx,
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
UNUSED(arg);
|
||||
#endif
|
||||
|
||||
#ifdef INET
|
||||
|
@ -1275,6 +1277,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
memset(ifo->nomask6, 0xff, sizeof(ifo->nomask6));
|
||||
|
||||
/* Allow the bare minimum through */
|
||||
#ifdef INET
|
||||
del_option_mask(ifo->nomask, DHO_SUBNETMASK);
|
||||
del_option_mask(ifo->nomask, DHO_CSR);
|
||||
del_option_mask(ifo->nomask, DHO_ROUTER);
|
||||
|
@ -1286,11 +1289,14 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
|
|||
del_option_mask(ifo->nomask, DHO_RENEWALTIME);
|
||||
del_option_mask(ifo->nomask, DHO_REBINDTIME);
|
||||
del_option_mask(ifo->nomask, DHO_DNSSEARCH);
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
del_option_mask(ifo->nomask6, D6_OPTION_DNS_SERVERS);
|
||||
del_option_mask(ifo->nomask6, D6_OPTION_DOMAIN_LIST);
|
||||
del_option_mask(ifo->nomask6, D6_OPTION_SOL_MAX_RT);
|
||||
del_option_mask(ifo->nomask6, D6_OPTION_INF_MAX_RT);
|
||||
#endif
|
||||
|
||||
break;
|
||||
#ifdef INET
|
||||
|
|
|
@ -121,10 +121,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
static void ipv6_regentempifid(void *);
|
||||
static void ipv6_regentempaddr(void *);
|
||||
#else
|
||||
#define ipv6_regentempifid(a) {}
|
||||
#endif
|
||||
|
||||
int
|
||||
|
@ -181,7 +178,7 @@ ipv6_readsecret(struct dhcpcd_ctx *ctx)
|
|||
}
|
||||
|
||||
/* Ensure that only the dhcpcd user can read the secret.
|
||||
* Write permission is also denied as chaning it would remove
|
||||
* Write permission is also denied as changing it would remove
|
||||
* it's stability. */
|
||||
if ((fp = fopen(SECRET, "w")) == NULL ||
|
||||
chmod(SECRET, S_IRUSR) == -1)
|
||||
|
@ -217,7 +214,7 @@ static const struct reslowhigh {
|
|||
{ 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }
|
||||
};
|
||||
|
||||
static int
|
||||
static bool
|
||||
ipv6_reserved(const struct in6_addr *addr)
|
||||
{
|
||||
uint64_t id, low, high;
|
||||
|
@ -227,37 +224,42 @@ ipv6_reserved(const struct in6_addr *addr)
|
|||
id = be64dec(addr->s6_addr + sizeof(id));
|
||||
if (id == 0) /* RFC4291 */
|
||||
return 1;
|
||||
for (i = 0; i < sizeof(reslowhigh) / sizeof(reslowhigh[0]); i++) {
|
||||
for (i = 0; i < __arraycount(reslowhigh); i++) {
|
||||
r = &reslowhigh[i];
|
||||
low = be64dec(r->low);
|
||||
high = be64dec(r->high);
|
||||
if (id >= low && id <= high)
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* RFC7217 */
|
||||
static int
|
||||
ipv6_makestableprivate1(struct in6_addr *addr,
|
||||
const struct in6_addr *prefix, int prefix_len,
|
||||
ipv6_makestableprivate1(struct dhcpcd_ctx *ctx,
|
||||
struct in6_addr *addr, const struct in6_addr *prefix, int prefix_len,
|
||||
const unsigned char *netiface, size_t netiface_len,
|
||||
const unsigned char *netid, size_t netid_len,
|
||||
unsigned short vlanid,
|
||||
uint32_t *dad_counter,
|
||||
const unsigned char *secret, size_t secret_len)
|
||||
uint32_t *dad_counter)
|
||||
{
|
||||
unsigned char buf[2048], *p, digest[SHA256_DIGEST_LENGTH];
|
||||
size_t len, l;
|
||||
SHA256_CTX ctx;
|
||||
SHA256_CTX sha_ctx;
|
||||
|
||||
if (prefix_len < 0 || prefix_len > 120) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctx->secret_len == 0) {
|
||||
if (ipv6_readsecret(ctx) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
l = (size_t)(ROUNDUP8(prefix_len) / NBBY);
|
||||
len = l + netiface_len + netid_len + sizeof(*dad_counter) + secret_len;
|
||||
len = l + netiface_len + netid_len + sizeof(*dad_counter) +
|
||||
ctx->secret_len;
|
||||
if (vlanid != 0)
|
||||
len += sizeof(vlanid);
|
||||
if (len > sizeof(buf)) {
|
||||
|
@ -282,15 +284,15 @@ ipv6_makestableprivate1(struct in6_addr *addr,
|
|||
}
|
||||
memcpy(p, dad_counter, sizeof(*dad_counter));
|
||||
p += sizeof(*dad_counter);
|
||||
memcpy(p, secret, secret_len);
|
||||
memcpy(p, ctx->secret, ctx->secret_len);
|
||||
|
||||
/* Make an address using the digest of the above.
|
||||
* RFC7217 Section 5.1 states that we shouldn't use MD5.
|
||||
* Pity as we use that for HMAC-MD5 which is still deemed OK.
|
||||
* SHA-256 is recommended */
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, buf, len);
|
||||
SHA256_Final(digest, &ctx);
|
||||
SHA256_Init(&sha_ctx);
|
||||
SHA256_Update(&sha_ctx, buf, len);
|
||||
SHA256_Final(digest, &sha_ctx);
|
||||
|
||||
p = addr->s6_addr;
|
||||
memcpy(p, prefix, l);
|
||||
|
@ -320,29 +322,52 @@ ipv6_makestableprivate(struct in6_addr *addr,
|
|||
uint32_t dad;
|
||||
int r;
|
||||
|
||||
if (ifp->ctx->secret_len == 0) {
|
||||
if (ipv6_readsecret(ifp->ctx) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
dad = (uint32_t)*dad_counter;
|
||||
|
||||
/* For our implementation, we shall set the hardware address
|
||||
* as the interface identifier */
|
||||
r = ipv6_makestableprivate1(addr, prefix, prefix_len,
|
||||
r = ipv6_makestableprivate1(ifp->ctx, addr, prefix, prefix_len,
|
||||
ifp->hwaddr, ifp->hwlen,
|
||||
ifp->ssid, ifp->ssid_len,
|
||||
ifp->vlanid, &dad,
|
||||
ifp->ctx->secret, ifp->ctx->secret_len);
|
||||
ifp->vlanid, &dad);
|
||||
|
||||
if (r == 0)
|
||||
*dad_counter = (int)dad;
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef IPV6_AF_TEMPORARY
|
||||
static int
|
||||
ipv6_maketemporaryaddress(struct in6_addr *addr,
|
||||
const struct in6_addr *prefix, int prefix_len,
|
||||
const struct interface *ifp)
|
||||
{
|
||||
struct in6_addr mask;
|
||||
struct interface *ifpn;
|
||||
|
||||
if (ipv6_mask(&mask, prefix_len) == -1)
|
||||
return -1;
|
||||
*addr = *prefix;
|
||||
|
||||
again:
|
||||
addr->s6_addr32[2] |= (arc4random() & ~mask.s6_addr32[2]);
|
||||
addr->s6_addr32[3] |= (arc4random() & ~mask.s6_addr32[3]);
|
||||
|
||||
TAILQ_FOREACH(ifpn, ifp->ctx->ifaces, next) {
|
||||
if (ipv6_iffindaddr(ifpn, addr, 0) != NULL)
|
||||
break;
|
||||
}
|
||||
if (ifpn != NULL)
|
||||
goto again;
|
||||
if (ipv6_reserved(addr))
|
||||
goto again;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
ipv6_makeaddr(struct in6_addr *addr, struct interface *ifp,
|
||||
const struct in6_addr *prefix, int prefix_len)
|
||||
const struct in6_addr *prefix, int prefix_len, unsigned int flags)
|
||||
{
|
||||
const struct ipv6_addr *ap;
|
||||
int dad;
|
||||
|
@ -352,6 +377,13 @@ ipv6_makeaddr(struct in6_addr *addr, struct interface *ifp,
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef IPV6_AF_TEMPORARY
|
||||
if (flags & IPV6_AF_TEMPORARY)
|
||||
return ipv6_maketemporaryaddress(addr, prefix, prefix_len, ifp);
|
||||
#else
|
||||
UNUSED(flags);
|
||||
#endif
|
||||
|
||||
if (ifp->options->options & DHCPCD_SLAACPRIVATE) {
|
||||
dad = 0;
|
||||
if (ipv6_makestableprivate(addr,
|
||||
|
@ -1052,11 +1084,6 @@ ipv6_getstate(struct interface *ifp)
|
|||
}
|
||||
TAILQ_INIT(&state->addrs);
|
||||
TAILQ_INIT(&state->ll_callbacks);
|
||||
|
||||
/* Regenerate new ids */
|
||||
if (ifp->options &&
|
||||
ip6_use_tempaddr(ifp->name))
|
||||
ipv6_regentempifid(ifp);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -1523,7 +1550,9 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
|
|||
|
||||
/* If adding a new DHCP / RA derived address, check current flags
|
||||
* from an existing address. */
|
||||
if (flags & IPV6_AF_AUTOCONF)
|
||||
if (tempaddr)
|
||||
iaf = NULL;
|
||||
else if (flags & IPV6_AF_AUTOCONF)
|
||||
iaf = ipv6nd_iffindprefix(ifp, addr, prefix_len);
|
||||
else
|
||||
iaf = ipv6_iffindaddr(ifp, addr, 0);
|
||||
|
@ -1551,14 +1580,15 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
|
|||
|
||||
if (prefix_len == 128)
|
||||
goto makepfx;
|
||||
else if (ia->flags & IPV6_AF_AUTOCONF && !tempaddr) {
|
||||
else if (ia->flags & IPV6_AF_AUTOCONF) {
|
||||
ia->prefix = *addr;
|
||||
if (iaf != NULL)
|
||||
memcpy(&ia->addr, &iaf->addr, sizeof(ia->addr));
|
||||
else {
|
||||
ia->dadcounter = ipv6_makeaddr(&ia->addr, ifp,
|
||||
&ia->prefix,
|
||||
ia->prefix_len);
|
||||
ia->prefix_len,
|
||||
ia->flags);
|
||||
if (ia->dadcounter == -1)
|
||||
goto err;
|
||||
}
|
||||
|
@ -1736,12 +1766,6 @@ ipv6_start(struct interface *ifp)
|
|||
if (ipv6_tryaddlinklocal(ifp) == -1)
|
||||
return -1;
|
||||
|
||||
if (IPV6_CSTATE(ifp)) {
|
||||
/* Regenerate new ids */
|
||||
if (ip6_use_tempaddr(ifp->name))
|
||||
ipv6_regentempifid(ifp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1838,31 +1862,8 @@ ipv6_handleifa_addrs(int cmd,
|
|||
}
|
||||
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
static const struct ipv6_addr *
|
||||
ipv6_findaddrid(struct dhcpcd_ctx *ctx, uint8_t *addr)
|
||||
{
|
||||
const struct interface *ifp;
|
||||
const struct ipv6_state *state;
|
||||
const struct ipv6_addr *ia;
|
||||
|
||||
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
|
||||
if ((state = IPV6_CSTATE(ifp))) {
|
||||
TAILQ_FOREACH(ia, &state->addrs, next) {
|
||||
if (memcmp(&ia->addr.s6_addr[8], addr, 8) == 0)
|
||||
return ia;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const uint8_t nullid[8];
|
||||
static const uint8_t anycastid[8] = {
|
||||
0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 };
|
||||
static const uint8_t isatapid[4] = { 0x00, 0x00, 0x5e, 0xfe };
|
||||
|
||||
static void
|
||||
ipv6_regen_desync(struct interface *ifp, int force)
|
||||
ipv6_regen_desync(struct interface *ifp, bool force)
|
||||
{
|
||||
struct ipv6_state *state;
|
||||
unsigned int max, pref;
|
||||
|
@ -1871,7 +1872,7 @@ ipv6_regen_desync(struct interface *ifp, int force)
|
|||
|
||||
/* RFC4941 Section 5 states that DESYNC_FACTOR must never be
|
||||
* greater than TEMP_VALID_LIFETIME - REGEN_ADVANCE.
|
||||
* I believe this is an error and it should be never be greateter than
|
||||
* I believe this is an error and it should be never be greater than
|
||||
* TEMP_PREFERRED_LIFETIME - REGEN_ADVANCE. */
|
||||
pref = (unsigned int)ip6_temp_preferred_lifetime(ifp->name);
|
||||
max = pref - REGEN_ADVANCE;
|
||||
|
@ -1881,63 +1882,7 @@ ipv6_regen_desync(struct interface *ifp, int force)
|
|||
state->desync_factor =
|
||||
arc4random_uniform(MIN(MAX_DESYNC_FACTOR, max));
|
||||
max = pref - state->desync_factor - REGEN_ADVANCE;
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop, max, ipv6_regentempifid, ifp);
|
||||
}
|
||||
|
||||
void
|
||||
ipv6_gentempifid(struct interface *ifp)
|
||||
{
|
||||
struct ipv6_state *state;
|
||||
MD5_CTX md5;
|
||||
uint8_t seed[16], digest[16];
|
||||
int retry;
|
||||
|
||||
if ((state = IPV6_STATE(ifp)) == NULL)
|
||||
return;
|
||||
|
||||
retry = 0;
|
||||
if (memcmp(nullid, state->randomseed0, sizeof(nullid)) == 0) {
|
||||
uint32_t r;
|
||||
|
||||
r = arc4random();
|
||||
memcpy(seed, &r, sizeof(r));
|
||||
r = arc4random();
|
||||
memcpy(seed + sizeof(r), &r, sizeof(r));
|
||||
} else
|
||||
memcpy(seed, state->randomseed0, sizeof(state->randomseed0));
|
||||
|
||||
memcpy(seed + sizeof(state->randomseed0),
|
||||
state->randomseed1, sizeof(state->randomseed1));
|
||||
|
||||
again:
|
||||
MD5Init(&md5);
|
||||
MD5Update(&md5, seed, sizeof(seed));
|
||||
MD5Final(digest, &md5);
|
||||
|
||||
/* RFC4941 Section 3.2.1.1
|
||||
* Take the left-most 64bits and set bit 6 to zero */
|
||||
memcpy(state->randomid, digest, sizeof(state->randomid));
|
||||
state->randomid[0] = (uint8_t)(state->randomid[0] & ~EUI64_UBIT);
|
||||
|
||||
/* RFC4941 Section 3.2.1.4
|
||||
* Reject reserved or existing id's */
|
||||
if (memcmp(nullid, state->randomid, sizeof(nullid)) == 0 ||
|
||||
(memcmp(anycastid, state->randomid, 7) == 0 &&
|
||||
(anycastid[7] & state->randomid[7]) == anycastid[7]) ||
|
||||
memcmp(isatapid, state->randomid, sizeof(isatapid)) == 0 ||
|
||||
ipv6_findaddrid(ifp->ctx, state->randomid))
|
||||
{
|
||||
if (++retry < GEN_TEMPID_RETRY_MAX) {
|
||||
memcpy(seed, digest + 8, 8);
|
||||
goto again;
|
||||
}
|
||||
memset(state->randomid, 0, sizeof(state->randomid));
|
||||
}
|
||||
|
||||
/* RFC4941 Section 3.2.1.6
|
||||
* Save the right-most 64bits of the digest */
|
||||
memcpy(state->randomseed0, digest + 8,
|
||||
sizeof(state->randomseed0));
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop, max, ipv6_regentempaddrs, ifp);
|
||||
}
|
||||
|
||||
/* RFC4941 Section 3.3.7 */
|
||||
|
@ -1970,75 +1915,27 @@ struct ipv6_addr *
|
|||
ipv6_createtempaddr(struct ipv6_addr *ia0, const struct timespec *now)
|
||||
{
|
||||
struct ipv6_state *state;
|
||||
const struct ipv6_state *cstate;
|
||||
int genid;
|
||||
struct in6_addr addr, mask;
|
||||
uint32_t randid[2];
|
||||
const struct interface *ifp;
|
||||
const struct ipv6_addr *ap;
|
||||
struct interface *ifp = ia0->iface;
|
||||
struct ipv6_addr *ia;
|
||||
uint32_t i, trylimit;
|
||||
uint32_t i;
|
||||
|
||||
trylimit = TEMP_IDGEN_RETRIES;
|
||||
state = IPV6_STATE(ia0->iface);
|
||||
genid = 0;
|
||||
|
||||
addr = ia0->addr;
|
||||
ipv6_mask(&mask, ia0->prefix_len);
|
||||
/* clear the old ifid */
|
||||
for (i = 0; i < 4; i++)
|
||||
addr.s6_addr32[i] &= mask.s6_addr32[i];
|
||||
|
||||
again:
|
||||
if (memcmp(state->randomid, nullid, sizeof(nullid)) == 0)
|
||||
genid = 1;
|
||||
if (genid) {
|
||||
memcpy(state->randomseed1, &ia0->addr.s6_addr[8],
|
||||
sizeof(state->randomseed1));
|
||||
ipv6_gentempifid(ia0->iface);
|
||||
if (memcmp(state->randomid, nullid, sizeof(nullid)) == 0) {
|
||||
errno = EFAULT;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
memcpy(&randid[0], state->randomid, sizeof(randid[0]));
|
||||
memcpy(&randid[1], state->randomid + sizeof(randid[1]),
|
||||
sizeof(randid[2]));
|
||||
addr.s6_addr32[2] |= randid[0] & ~mask.s6_addr32[2];
|
||||
addr.s6_addr32[3] |= randid[1] & ~mask.s6_addr32[3];
|
||||
|
||||
/* Ensure we don't already have it */
|
||||
TAILQ_FOREACH(ifp, ia0->iface->ctx->ifaces, next) {
|
||||
cstate = IPV6_CSTATE(ifp);
|
||||
if (cstate) {
|
||||
TAILQ_FOREACH(ap, &cstate->addrs, next) {
|
||||
if (IN6_ARE_ADDR_EQUAL(&ap->addr, &addr)) {
|
||||
if (--trylimit == 0) {
|
||||
errno = EEXIST;
|
||||
return NULL;
|
||||
}
|
||||
genid = 1;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ia = ipv6_newaddr(ia0->iface, &addr, ia0->prefix_len,
|
||||
ia = ipv6_newaddr(ifp, &ia0->prefix, ia0->prefix_len,
|
||||
IPV6_AF_AUTOCONF | IPV6_AF_TEMPORARY);
|
||||
/* Must be made tentative, for our DaD to work */
|
||||
ia->addr_flags = IN6_IFF_TENTATIVE;
|
||||
if (ia == NULL)
|
||||
return NULL;
|
||||
|
||||
ia->dadcallback = ipv6_tempdadcallback;
|
||||
ia->created = ia->acquired = now ? *now : ia0->acquired;
|
||||
|
||||
/* Ensure desync is still valid */
|
||||
ipv6_regen_desync(ia->iface, 0);
|
||||
ipv6_regen_desync(ifp, false);
|
||||
|
||||
/* RFC4941 Section 3.3.4 */
|
||||
i = (uint32_t)ip6_temp_preferred_lifetime(ia0->iface->name) -
|
||||
state = IPV6_STATE(ia->iface);
|
||||
i = (uint32_t)ip6_temp_preferred_lifetime(ifp->name) -
|
||||
state->desync_factor;
|
||||
ia->prefix_pltime = MIN(ia0->prefix_pltime, i);
|
||||
i = (uint32_t)ip6_temp_valid_lifetime(ia0->iface->name);
|
||||
i = (uint32_t)ip6_temp_valid_lifetime(ifp->name);
|
||||
ia->prefix_vltime = MIN(ia0->prefix_vltime, i);
|
||||
if (ia->prefix_pltime <= REGEN_ADVANCE ||
|
||||
ia->prefix_pltime > ia0->prefix_vltime)
|
||||
|
@ -2089,7 +1986,7 @@ ipv6_settemptime(struct ipv6_addr *ia, int flags)
|
|||
}
|
||||
|
||||
/* Ensure desync is still valid */
|
||||
ipv6_regen_desync(ap->iface, 0);
|
||||
ipv6_regen_desync(ap->iface, false);
|
||||
|
||||
/* RFC4941 Section 3.3.2
|
||||
* Extend temporary times, but ensure that they
|
||||
|
@ -2147,31 +2044,44 @@ ipv6_addtempaddrs(struct interface *ifp, const struct timespec *now)
|
|||
}
|
||||
|
||||
static void
|
||||
ipv6_regentempaddr(void *arg)
|
||||
ipv6_regentempaddr0(struct ipv6_addr *ia, struct timespec *tv)
|
||||
{
|
||||
struct ipv6_addr *ia = arg, *ia1;
|
||||
struct timespec tv;
|
||||
struct ipv6_addr *ia1;
|
||||
|
||||
logdebugx("%s: regen temp addr %s", ia->iface->name, ia->saddr);
|
||||
clock_gettime(CLOCK_MONOTONIC, &tv);
|
||||
ia1 = ipv6_createtempaddr(ia, &tv);
|
||||
ia1 = ipv6_createtempaddr(ia, tv);
|
||||
if (ia1)
|
||||
ipv6_addaddr(ia1, &tv);
|
||||
ipv6_addaddr(ia1, tv);
|
||||
else
|
||||
logerr(__func__);
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6_regentempifid(void *arg)
|
||||
ipv6_regentempaddr(void *arg)
|
||||
{
|
||||
struct timespec tv;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &tv);
|
||||
ipv6_regentempaddr0(arg, &tv);
|
||||
}
|
||||
|
||||
void
|
||||
ipv6_regentempaddrs(void *arg)
|
||||
{
|
||||
struct interface *ifp = arg;
|
||||
struct timespec tv;
|
||||
struct ipv6_state *state;
|
||||
struct ipv6_addr *ia;
|
||||
|
||||
ipv6_regen_desync(ifp, true);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &tv);
|
||||
state = IPV6_STATE(ifp);
|
||||
if (memcmp(state->randomid, nullid, sizeof(state->randomid)))
|
||||
ipv6_gentempifid(ifp);
|
||||
|
||||
ipv6_regen_desync(ifp, 1);
|
||||
TAILQ_FOREACH(ia, &state->addrs, next) {
|
||||
if (ia->flags & IPV6_AF_TEMPORARY &&
|
||||
!(ia->flags & IPV6_AF_STALE))
|
||||
ipv6_regentempaddr0(ia, &tv);
|
||||
}
|
||||
}
|
||||
#endif /* IPV6_MANAGETEMPADDR */
|
||||
|
||||
|
@ -2343,6 +2253,9 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
|
|||
rt = inet6_makeprefix(rap->iface, rap, addr);
|
||||
if (rt) {
|
||||
rt->rt_dflags |= RTDF_RA;
|
||||
#ifdef HAVE_ROUTE_PREF
|
||||
rt->rt_pref = ipv6nd_rtpref(rap);
|
||||
#endif
|
||||
rt_proto_add(routes, rt);
|
||||
}
|
||||
}
|
||||
|
@ -2354,6 +2267,9 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
|
|||
if (rt == NULL)
|
||||
continue;
|
||||
rt->rt_dflags |= RTDF_RA;
|
||||
#ifdef HAVE_ROUTE_PREF
|
||||
rt->rt_pref = ipv6nd_rtpref(rap);
|
||||
#endif
|
||||
rt_proto_add(routes, rt);
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -59,9 +59,7 @@
|
|||
#define TEMP_PREFERRED_LIFETIME 86400 /* 1 day */
|
||||
#define REGEN_ADVANCE 5 /* seconds */
|
||||
#define MAX_DESYNC_FACTOR 600 /* 10 minutes */
|
||||
|
||||
#define TEMP_IDGEN_RETRIES 3
|
||||
#define GEN_TEMPID_RETRY_MAX 5
|
||||
|
||||
/* RFC7217 constants */
|
||||
#define IDGEN_RETRIES 3
|
||||
|
@ -245,9 +243,6 @@ struct ipv6_state {
|
|||
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
uint32_t desync_factor;
|
||||
uint8_t randomseed0[8]; /* upper 64 bits of MD5 digest */
|
||||
uint8_t randomseed1[8]; /* lower 64 bits */
|
||||
uint8_t randomid[8];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -259,11 +254,10 @@ struct ipv6_state {
|
|||
|
||||
|
||||
int ipv6_init(struct dhcpcd_ctx *);
|
||||
int ipv6_makestableprivate(struct in6_addr *addr,
|
||||
const struct in6_addr *prefix, int prefix_len,
|
||||
const struct interface *ifp, int *dad_counter);
|
||||
int ipv6_makestableprivate(struct in6_addr *,
|
||||
const struct in6_addr *, int, const struct interface *, int *);
|
||||
int ipv6_makeaddr(struct in6_addr *, struct interface *,
|
||||
const struct in6_addr *, int);
|
||||
const struct in6_addr *, int, unsigned int);
|
||||
int ipv6_mask(struct in6_addr *, int);
|
||||
uint8_t ipv6_prefixlen(const struct in6_addr *);
|
||||
int ipv6_userprefix( const struct in6_addr *, short prefix_len,
|
||||
|
@ -301,14 +295,11 @@ void ipv6_freedrop(struct interface *, int);
|
|||
#define ipv6_drop(ifp) ipv6_freedrop((ifp), 2)
|
||||
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
void ipv6_gentempifid(struct interface *);
|
||||
struct ipv6_addr *ipv6_createtempaddr(struct ipv6_addr *,
|
||||
const struct timespec *);
|
||||
struct ipv6_addr *ipv6_settemptime(struct ipv6_addr *, int);
|
||||
void ipv6_addtempaddrs(struct interface *, const struct timespec *);
|
||||
#else
|
||||
#define ipv6_gentempifid(a) {}
|
||||
#define ipv6_settempstale(a) {}
|
||||
void ipv6_regentempaddrs(void *);
|
||||
#endif
|
||||
|
||||
int ipv6_start(struct interface *);
|
||||
|
|
|
@ -101,13 +101,6 @@ __CTASSERT(sizeof(struct nd_opt_rdnss) == 8);
|
|||
#define ND_RA_FLAG_RTPREF_RSV 0x10
|
||||
#endif
|
||||
|
||||
/* RTPREF_MEDIUM has to be 0! */
|
||||
#define RTPREF_HIGH 1
|
||||
#define RTPREF_MEDIUM 0
|
||||
#define RTPREF_LOW (-1)
|
||||
#define RTPREF_RESERVED (-2)
|
||||
#define RTPREF_INVALID (-3) /* internal */
|
||||
|
||||
#define EXPIRED_MAX 5 /* Remember 5 expired routers to avoid
|
||||
logspam. */
|
||||
|
||||
|
@ -580,7 +573,7 @@ ipv6nd_startexpire(struct interface *ifp)
|
|||
RTR_CARRIER_EXPIRE, ipv6nd_expire, ifp);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
ipv6nd_rtpref(struct ra *rap)
|
||||
{
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ if_printoptions(void)
|
|||
}
|
||||
|
||||
pid_t
|
||||
script_exec(const struct dhcpcd_ctx *ctx, char *const *argv, char *const *env)
|
||||
script_exec(char *const *argv, char *const *env)
|
||||
{
|
||||
pid_t pid = 0;
|
||||
posix_spawnattr_t attr;
|
||||
|
@ -105,11 +105,10 @@ script_exec(const struct dhcpcd_ctx *ctx, char *const *argv, char *const *env)
|
|||
flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF;
|
||||
posix_spawnattr_setflags(&attr, flags);
|
||||
sigemptyset(&defsigs);
|
||||
posix_spawnattr_setsigmask(&attr, &defsigs);
|
||||
for (i = 0; i < dhcpcd_signals_len; i++)
|
||||
sigaddset(&defsigs, dhcpcd_signals[i]);
|
||||
posix_spawnattr_setsigdefault(&attr, &defsigs);
|
||||
sigemptyset(&defsigs);
|
||||
posix_spawnattr_setsigmask(&attr, &defsigs);
|
||||
#endif
|
||||
errno = 0;
|
||||
r = posix_spawn(&pid, argv[0], NULL, &attr, argv, env);
|
||||
|
@ -658,7 +657,7 @@ script_run(struct dhcpcd_ctx *ctx, char **argv)
|
|||
pid_t pid;
|
||||
int status = 0;
|
||||
|
||||
pid = script_exec(ctx, argv, ctx->script_env);
|
||||
pid = script_exec(argv, ctx->script_env);
|
||||
if (pid == -1)
|
||||
logerr("%s: %s", __func__, argv[0]);
|
||||
else if (pid != 0) {
|
||||
|
|
Loading…
Reference in New Issue