summaryrefslogtreecommitdiffstats
path: root/ipv6.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2016-02-02 23:55:52 +0000
committerRoy Marples <roy@marples.name>2016-02-02 23:55:52 +0000
commit07be0a6fa9095641cb2038c2a0d7dc4cf231ae64 (patch)
treed02c68b45bd450fdf5bedc5278ea60ffac3f4867 /ipv6.c
parent96695efe835951c667acb6017d2c169e0320574c (diff)
downloaddhcpcd-07be0a6fa9095641cb2038c2a0d7dc4cf231ae64.tar.xz
Fix Prefix Delegation assigning the SLA in the correct place.
Diffstat (limited to 'ipv6.c')
-rw-r--r--ipv6.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/ipv6.c b/ipv6.c
index ebb616c0..30a36491 100644
--- a/ipv6.c
+++ b/ipv6.c
@@ -524,8 +524,9 @@ ipv6_userprefix(
{
uint64_t vh, vl, user_low, user_high;
- if (prefix_len < 0 || prefix_len > 128 ||
- result_len < 0 || result_len > 128)
+ if (prefix_len < 1 || prefix_len > 128 ||
+ result_len < 1 || result_len > 128 ||
+ user_number == 0)
{
errno = EINVAL;
return -1;
@@ -533,19 +534,30 @@ ipv6_userprefix(
/* Check that the user_number fits inside result_len less prefix_len */
if (result_len < prefix_len ||
- ffs64(user_number) > result_len - prefix_len)
+ fls64(user_number) > result_len - prefix_len)
{
errno = ERANGE;
return -1;
}
- /* virtually shift user number by dest_len, then split at 64 */
- if (result_len >= 64) {
- user_high = user_number << (result_len - 64);
+ /* Shift user_number so it fit's just inside result_len.
+ * Shifting by 0 or sizeof(user_number) is undefined,
+ * so we cater for that. */
+ if (result_len == 128) {
+ user_high = 0;
+ user_low = user_number;
+ } else if (result_len > 64) {
+ if (prefix_len >= 64)
+ user_high = 0;
+ else
+ user_high = user_number >> (result_len - prefix_len);
+ user_low = user_number << (128 - result_len);
+ } else if (result_len == 64) {
+ user_high = user_number;
user_low = 0;
} else {
- user_high = user_number >> (64 - result_len);
- user_low = user_number << result_len;
+ user_high = user_number << (64 - result_len);
+ user_low = 0;
}
/* convert to two 64bit host order values */