From be0d1c027a08c8958fb0bfecade7edc7bb1e28c6 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 9 Aug 2018 13:20:07 -0500 Subject: [PATCH] common/ipaddr: add network_contains() helper Signed-off-by: Sage Weil --- src/common/ipaddr.cc | 37 +++++++++++++++++++++++++++++++++++++ src/include/ipaddr.h | 6 ++++++ src/test/test_ipaddr.cc | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/src/common/ipaddr.cc b/src/common/ipaddr.cc index 3d03aef6b54cc..7e4112fbe5673 100644 --- a/src/common/ipaddr.cc +++ b/src/common/ipaddr.cc @@ -178,3 +178,40 @@ bool parse_network(const char *s, } return ret; } + +bool network_contains( + const struct entity_addr_t& network, + unsigned int prefix_len, + const struct entity_addr_t& addr) +{ + if (addr.get_family() != network.get_family()) { + return false; + } + switch (network.get_family()) { + case AF_INET: + { + struct in_addr a, b; + netmask_ipv4( + &((const sockaddr_in*)network.get_sockaddr())->sin_addr, prefix_len, &a); + netmask_ipv4( + &((const sockaddr_in*)addr.get_sockaddr())->sin_addr, prefix_len, &b); + if (memcmp(&a, &b, sizeof(a)) == 0) { + return true; + } + } + break; + case AF_INET6: + { + struct in6_addr a, b; + netmask_ipv6( + &((const sockaddr_in6*)network.get_sockaddr())->sin6_addr, prefix_len, &a); + netmask_ipv6( + &((const sockaddr_in6*)addr.get_sockaddr())->sin6_addr, prefix_len, &b); + if (memcmp(&a, &b, sizeof(a)) == 0) { + return true; + } + } + break; + } + return false; +} diff --git a/src/include/ipaddr.h b/src/include/ipaddr.h index 3ec822534f0d4..2f72f40ef4b8d 100644 --- a/src/include/ipaddr.h +++ b/src/include/ipaddr.h @@ -38,4 +38,10 @@ void netmask_ipv6(const struct in6_addr *addr, void netmask_ipv4(const struct in_addr *addr, unsigned int prefix_len, struct in_addr *out); + +bool network_contains( + const struct entity_addr_t& network, + unsigned int prefix_len, + const struct entity_addr_t& addr); + #endif diff --git a/src/test/test_ipaddr.cc b/src/test/test_ipaddr.cc index ffd7b7911350a..e8e61c17ff033 100644 --- a/src/test/test_ipaddr.cc +++ b/src/test/test_ipaddr.cc @@ -542,6 +542,42 @@ TEST(CommonIPAddr, ParseNetwork_IPv6_9000) ASSERT_EQ(0, memcmp(want.sin6_addr.s6_addr, network.sin6_addr.s6_addr, sizeof(network.sin6_addr.s6_addr))); } +TEST(CommonIPAddr, network_contains) +{ + entity_addr_t network, addr; + unsigned int prefix; + bool ok; + + ok = parse_network("2001:1234:5678:90ab::dead:beef/32", &network, &prefix); + ASSERT_TRUE(ok); + ASSERT_EQ(32U, prefix); + ok = addr.parse("2001:1234:5678:90ab::dead:beef", nullptr); + ASSERT_TRUE(ok); + ASSERT_TRUE(network_contains(network, prefix, addr)); + ok = addr.parse("2001:1334:5678:90ab::dead:beef", nullptr); + ASSERT_TRUE(ok); + ASSERT_FALSE(network_contains(network, prefix, addr)); + ok = addr.parse("127.0.0.1", nullptr); + ASSERT_TRUE(ok); + ASSERT_FALSE(network_contains(network, prefix, addr)); + + ok = parse_network("10.1.2.3/16", &network, &prefix); + ASSERT_TRUE(ok); + ASSERT_EQ(16U, prefix); + ok = addr.parse("2001:1234:5678:90ab::dead:beef", nullptr); + ASSERT_TRUE(ok); + ASSERT_FALSE(network_contains(network, prefix, addr)); + ok = addr.parse("1.2.3.4", nullptr); + ASSERT_TRUE(ok); + ASSERT_FALSE(network_contains(network, prefix, addr)); + ok = addr.parse("10.1.22.44", nullptr); + ASSERT_TRUE(ok); + ASSERT_TRUE(network_contains(network, prefix, addr)); + ok = addr.parse("10.2.22.44", nullptr); + ASSERT_TRUE(ok); + ASSERT_FALSE(network_contains(network, prefix, addr)); +} + TEST(pick_address, find_ip_in_subnet_list) { struct ifaddrs one, two, three; -- 2.39.5