summaryrefslogtreecommitdiff
path: root/sbin/slaacd
diff options
context:
space:
mode:
authorPeter Hessler <phessler@cvs.openbsd.org>2018-03-08 17:41:16 +0000
committerPeter Hessler <phessler@cvs.openbsd.org>2018-03-08 17:41:16 +0000
commitb26642ac81224442054c381497fcb9acb96203fe (patch)
treeaeccfe3edcc6bd80abdd708e312afeed4ba6aeb1 /sbin/slaacd
parent476455807d82f86f6f690898300e0c76fa8f5812 (diff)
Back in the history of time, IPv4 had classes of addresses. This was widely
acknowledged as a failure. At the same time IPv4 classes were declared a failure, IPv6 decided to add them back because using a mac address for IP address configuration was easy. Now that we have RFC7217 support we can remove this artificial limitation: allow non-/64 prefixes to be configured by SLAAC. Of course, if you have fewer bits for the hosts part of the address you have fewer bits for privacy and fewer bits to avoid collisions. OK florian@
Diffstat (limited to 'sbin/slaacd')
-rw-r--r--sbin/slaacd/engine.c69
1 files changed, 30 insertions, 39 deletions
diff --git a/sbin/slaacd/engine.c b/sbin/slaacd/engine.c
index 2fce94a2bf5..f473e3d0b80 100644
--- a/sbin/slaacd/engine.c
+++ b/sbin/slaacd/engine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: engine.c,v 1.21 2018/03/07 18:26:28 florian Exp $ */
+/* $OpenBSD: engine.c,v 1.22 2018/03/08 17:41:15 phessler Exp $ */
/*
* Copyright (c) 2017 Florian Obser <florian@openbsd.org>
@@ -1235,7 +1235,7 @@ gen_addr(struct slaacd_iface *iface, struct radv_prefix *prefix, struct
address_proposal *addr_proposal, int privacy)
{
SHA2_CTX ctx;
- struct in6_addr priv_in6;
+ struct in6_addr iid;
int dad_counter = 0; /* XXX not used */
u_int8_t digest[SHA512_DIGEST_LENGTH];
@@ -1263,43 +1263,33 @@ gen_addr(struct slaacd_iface *iface, struct radv_prefix *prefix, struct
addr_proposal->mask.s6_addr32[3];
if (privacy) {
- arc4random_buf(&priv_in6.s6_addr, sizeof(priv_in6.s6_addr));
- addr_proposal->addr.sin6_addr.s6_addr32[0] |=
- (priv_in6.s6_addr32[0] & ~addr_proposal->mask.s6_addr32[0]);
- addr_proposal->addr.sin6_addr.s6_addr32[1] |=
- (priv_in6.s6_addr32[1] & ~addr_proposal->mask.s6_addr32[1]);
- addr_proposal->addr.sin6_addr.s6_addr32[2] |=
- (priv_in6.s6_addr32[2] & ~addr_proposal->mask.s6_addr32[2]);
- addr_proposal->addr.sin6_addr.s6_addr32[3] |=
- (priv_in6.s6_addr32[3] & ~addr_proposal->mask.s6_addr32[3]);
+ arc4random_buf(&iid.s6_addr, sizeof(iid.s6_addr));
+ } else if (iface->soii) {
+ SHA512Init(&ctx);
+ SHA512Update(&ctx, &prefix->prefix,
+ sizeof(prefix->prefix));
+ SHA512Update(&ctx, &iface->hw_address,
+ sizeof(iface->hw_address));
+ SHA512Update(&ctx, &dad_counter, sizeof(dad_counter));
+ SHA512Update(&ctx, addr_proposal->soiikey,
+ sizeof(addr_proposal->soiikey));
+ SHA512Final(digest, &ctx);
+
+ memcpy(&iid.s6_addr, digest, sizeof(iid.s6_addr));
} else {
- if (iface->soii) {
- SHA512Init(&ctx);
- SHA512Update(&ctx, &prefix->prefix,
- sizeof(prefix->prefix));
- SHA512Update(&ctx, &iface->hw_address,
- sizeof(iface->hw_address));
- SHA512Update(&ctx, &dad_counter, sizeof(dad_counter));
- SHA512Update(&ctx, addr_proposal->soiikey,
- sizeof(addr_proposal->soiikey));
- SHA512Final(digest, &ctx);
- memcpy(&addr_proposal->addr.sin6_addr.s6_addr[8],
- digest, 8);
- } else {
- addr_proposal->addr.sin6_addr.s6_addr32[0] |=
- (iface->ll_address.sin6_addr.s6_addr32[0] &
- ~addr_proposal->mask.s6_addr32[0]);
- addr_proposal->addr.sin6_addr.s6_addr32[1] |=
- (iface->ll_address.sin6_addr.s6_addr32[1] &
- ~addr_proposal->mask.s6_addr32[1]);
- addr_proposal->addr.sin6_addr.s6_addr32[2] |=
- (iface->ll_address.sin6_addr.s6_addr32[2] &
- ~addr_proposal->mask.s6_addr32[2]);
- addr_proposal->addr.sin6_addr.s6_addr32[3] |=
- (iface->ll_address.sin6_addr.s6_addr32[3] &
- ~addr_proposal->mask.s6_addr32[3]);
- }
+ /* This is safe, because we have a 64 prefix len */
+ memcpy(&iid.s6_addr, &iface->ll_address.sin6_addr,
+ sizeof(iid.s6_addr));
}
+
+ addr_proposal->addr.sin6_addr.s6_addr32[0] |=
+ (iid.s6_addr32[0] & ~addr_proposal->mask.s6_addr32[0]);
+ addr_proposal->addr.sin6_addr.s6_addr32[1] |=
+ (iid.s6_addr32[1] & ~addr_proposal->mask.s6_addr32[1]);
+ addr_proposal->addr.sin6_addr.s6_addr32[2] |=
+ (iid.s6_addr32[2] & ~addr_proposal->mask.s6_addr32[2]);
+ addr_proposal->addr.sin6_addr.s6_addr32[3] |=
+ (iid.s6_addr32[3] & ~addr_proposal->mask.s6_addr32[3]);
#undef s6_addr32
}
@@ -1661,7 +1651,6 @@ void update_iface_ra(struct slaacd_iface *iface, struct radv *ra)
LIST_FOREACH(prefix, &ra->prefixes, entries) {
if (!prefix->autonomous || prefix->vltime == 0 ||
prefix->pltime > prefix->vltime ||
- prefix->prefix_len != 64 ||
IN6_IS_ADDR_LINKLOCAL(&prefix->prefix))
continue;
found = 0;
@@ -1743,10 +1732,12 @@ void update_iface_ra(struct slaacd_iface *iface, struct radv *ra)
}
}
- if (!found)
+ if (!found &&
+ (iface->soii || prefix->prefix_len <= 64))
/* new proposal */
gen_address_proposal(iface, ra, prefix, 0);
+ /* privacy addresses do not depend on eui64 */
if (!found_privacy && iface->autoconfprivacy) {
if (prefix->pltime <
ND6_PRIV_MAX_DESYNC_FACTOR) {