diff options
| author | Roy Marples <roy@marples.name> | 2016-02-02 23:55:52 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2016-02-02 23:55:52 +0000 |
| commit | 07be0a6fa9095641cb2038c2a0d7dc4cf231ae64 (patch) | |
| tree | d02c68b45bd450fdf5bedc5278ea60ffac3f4867 /ipv6.c | |
| parent | 96695efe835951c667acb6017d2c169e0320574c (diff) | |
| download | dhcpcd-07be0a6fa9095641cb2038c2a0d7dc4cf231ae64.tar.xz | |
Fix Prefix Delegation assigning the SLA in the correct place.
Diffstat (limited to 'ipv6.c')
| -rw-r--r-- | ipv6.c | 28 |
1 files changed, 20 insertions, 8 deletions
@@ -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 */ |
