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>
This commit is contained in:
parent
d3301aae88
commit
ba026941a1
2 changed files with 81 additions and 6 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -273,6 +273,71 @@ static bool test_init(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool net_test_cmp_prefix(void)
|
||||
{
|
||||
bool st;
|
||||
|
||||
struct in6_addr prefix1 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
struct in6_addr prefix2 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } };
|
||||
|
||||
st = net_is_ipv6_prefix((uint8_t *)&prefix1, (uint8_t *)&prefix2, 64);
|
||||
if (!st) {
|
||||
TC_ERROR("Prefix /64 compare failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
st = net_is_ipv6_prefix((uint8_t *)&prefix1, (uint8_t *)&prefix2, 65);
|
||||
if (!st) {
|
||||
TC_ERROR("Prefix /65 compare failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set one extra bit in the other prefix for testing /65 */
|
||||
prefix1.s6_addr[8] = 0x80;
|
||||
|
||||
st = net_is_ipv6_prefix((uint8_t *)&prefix1, (uint8_t *)&prefix2, 65);
|
||||
if (st) {
|
||||
TC_ERROR("Prefix /65 compare should have failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set two bits in prefix2, it is now /66 */
|
||||
prefix2.s6_addr[8] = 0xc0;
|
||||
|
||||
st = net_is_ipv6_prefix((uint8_t *)&prefix1, (uint8_t *)&prefix2, 65);
|
||||
if (!st) {
|
||||
TC_ERROR("Prefix /65 compare failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set all remaining bits in prefix2, it is now /128 */
|
||||
memset(&prefix2.s6_addr[8], 0xff, 8);
|
||||
|
||||
st = net_is_ipv6_prefix((uint8_t *)&prefix1, (uint8_t *)&prefix2, 65);
|
||||
if (!st) {
|
||||
TC_ERROR("Prefix /65 compare failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Comparing /64 should be still ok */
|
||||
st = net_is_ipv6_prefix((uint8_t *)&prefix1, (uint8_t *)&prefix2, 64);
|
||||
if (!st) {
|
||||
TC_ERROR("Prefix /64 compare failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* But comparing /66 should should fail */
|
||||
st = net_is_ipv6_prefix((uint8_t *)&prefix1, (uint8_t *)&prefix2, 66);
|
||||
if (st) {
|
||||
TC_ERROR("Prefix /66 compare should have failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool net_test_send_ns_mcast(void)
|
||||
{
|
||||
int ret;
|
||||
|
@ -614,6 +679,7 @@ static const struct {
|
|||
bool (*func)(void);
|
||||
} tests[] = {
|
||||
{ "test init", test_init },
|
||||
{ "IPv6 compare prefix", net_test_cmp_prefix },
|
||||
{ "IPv6 send NS mcast", net_test_send_ns_mcast },
|
||||
{ "IPv6 neighbor lookup fail", net_test_nbr_lookup_fail },
|
||||
{ "IPv6 send NS", net_test_send_ns },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue