Hi,
The IPv6 address assignment was basically copied from the IPv4
code. Instead of working on the last 32-bits, it actually worked
on the fourth byte. Thus it modified the network bits instead of
the host bits.
This diff fixes the code so that we can have at least a 32-bit
address pool space by using the current IPv4 code. In the future
it might be nice to be able to leverage all host bits.
Is there a saner way to access the last 32-bits of an IPv6 address?
Another possibility would be
*((uint32_t *)&in6->sin6_addr.s6_addr[12]) = ...;
but I'm not sure that's any better.
Patrick
diff --git sbin/iked/ikev2.c sbin/iked/ikev2.c
index d4c4290..dbce512 100644
--- sbin/iked/ikev2.c
+++ sbin/iked/ikev2.c
@@ -5092,15 +5092,13 @@ ikev2_cp_setaddr(struct iked *env, struct iked_sa *sa,
sa_family_t family)
return (-1);
}
- /* truncate prefixlen in the v6 case */
- mask = prefixlen2mask(ikecfg->cfg.address.addr_mask);
-
switch (addr.addr_af) {
case AF_INET:
cfg4 = (struct sockaddr_in *)&ikecfg->cfg.address.addr;
in4 = (struct sockaddr_in *)&addr.addr;
in4->sin_family = AF_INET;
in4->sin_len = sizeof(*in4);
+ mask = prefixlen2mask(ikecfg->cfg.address.addr_mask);
lower = ntohl(cfg4->sin_addr.s_addr & ~mask);
key.sa_addrpool = &addr;
break;
@@ -5109,7 +5107,11 @@ ikev2_cp_setaddr(struct iked *env, struct iked_sa *sa,
sa_family_t family)
in6 = (struct sockaddr_in6 *)&addr.addr;
in6->sin6_family = AF_INET6;
in6->sin6_len = sizeof(*in6);
- lower = cfg6->sin6_addr.s6_addr[3];
+ /* truncate prefixlen to get a 32-bit space */
+ mask = (ikecfg->cfg.address.addr_mask >= 96)
+ ? prefixlen2mask(ikecfg->cfg.address.addr_mask - 96)
+ : prefixlen2mask(0);
+ lower = ntohl(cfg6->sin6_addr.__u6_addr.__u6_addr32[3] & ~mask);
key.sa_addrpool6 = &addr;
break;
default:
@@ -5133,7 +5135,7 @@ ikev2_cp_setaddr(struct iked *env, struct iked_sa *sa,
sa_family_t family)
break;
case AF_INET6:
memcpy(in6, cfg6, sizeof(*in6));
- in6->sin6_addr.s6_addr[3] = htonl(host);
+ in6->sin6_addr.__u6_addr.__u6_addr32[3] = htonl(host);
break;
}
if ((addr.addr_af == AF_INET &&