summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2017-01-18 09:38:20 +0200
committerJukka Rissanen <jukka.rissanen@linux.intel.com>2017-01-20 16:23:18 +0200
commitba026941a10325f4ac7fff93e4ad579b0b349e05 (patch)
treef41d10612cc53c0710a0eb8764b7aaa8c0244822 /include
parentd3301aae88aac6ab467a290ac9961aaeaf452e78 (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.h21
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);
}
/**