diff options
author | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2017-01-18 09:38:20 +0200 |
---|---|---|
committer | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2017-01-20 16:23:18 +0200 |
commit | ba026941a10325f4ac7fff93e4ad579b0b349e05 (patch) | |
tree | f41d10612cc53c0710a0eb8764b7aaa8c0244822 /include | |
parent | d3301aae88aac6ab467a290ac9961aaeaf452e78 (diff) |
net: ipv6: Fix IPv6 prefix comparision
If the prefix length % 8 is not 0, then the remaining
bit length was calculated incorrectly and the prefixes
were claimed to match even though they might not be the
same.
Adding a test cases for testing this properly.
Coverity-CID: 157591
Change-Id: I9cb5a73d5cc211ec183176400fa5e2dfd209e2da
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/net/net_ip.h | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/include/net/net_ip.h b/include/net/net_ip.h index f058bc552..e055d71c9 100644 --- a/include/net/net_ip.h +++ b/include/net/net_ip.h @@ -360,27 +360,36 @@ static inline bool net_is_my_ipv6_maddr(struct in6_addr *maddr) * @param addr2 Second IPv6 address. * @param length Prefix length (max length is 128). * - * @return True if addresses are the same, False otherwise. + * @return True if IPv6 prefixes are the same, False otherwise. */ static inline bool net_is_ipv6_prefix(const uint8_t *addr1, const uint8_t *addr2, uint8_t length) { uint8_t bits = 128 - length; - uint8_t bytes = bits / 8; + uint8_t bytes = length / 8; uint8_t remain = bits % 8; + uint8_t mask; if (length > 128) { return false; } - if (memcmp(addr1, addr2, 16 - bytes)) { + if (memcmp(addr1, addr2, bytes)) { return false; } - return ((addr1[16 - bytes] & ((8 - remain) << 8)) - == - (addr2[16 - bytes] & ((8 - remain) << 8))); + if (!remain) { + /* No remaining bits, the prefixes are the same as first + * bytes are the same. + */ + return true; + } + + /* Create a mask that has remaining most significant bits set */ + mask = ((0xff << (8 - remain)) ^ 0xff) << remain; + + return (addr1[bytes] & mask) == (addr2[bytes] & mask); } /** |