]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
in-addr-util: introduce in_addr_prefix_range()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 17 Feb 2021 13:55:01 +0000 (22:55 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 17 Feb 2021 13:57:37 +0000 (22:57 +0900)
This will replace nft_in6addr_to_range() in later commit.

src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/test/test-in-addr-util.c

index aa681b7bb79528f8f968809fe33c5c41d00f3e8e..641c5de7a37acbd0511a72368d360835a5c7dddc 100644 (file)
@@ -350,6 +350,43 @@ int in_addr_random_prefix(
         return -EAFNOSUPPORT;
 }
 
+int in_addr_prefix_range(
+                int family,
+                const union in_addr_union *in,
+                unsigned prefixlen,
+                union in_addr_union *ret_start,
+                union in_addr_union *ret_end) {
+
+        union in_addr_union start, end;
+        int r;
+
+        assert(in);
+
+        if (!IN_SET(family, AF_INET, AF_INET6))
+                return -EAFNOSUPPORT;
+
+        if (ret_start) {
+                start = *in;
+                r = in_addr_prefix_nth(family, &start, prefixlen, 0);
+                if (r < 0)
+                        return r;
+        }
+
+        if (ret_end) {
+                end = *in;
+                r = in_addr_prefix_nth(family, &end, prefixlen, 1);
+                if (r < 0)
+                        return r;
+        }
+
+        if (ret_start)
+                *ret_start = start;
+        if (ret_end)
+                *ret_end = end;
+
+        return 0;
+}
+
 int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
         _cleanup_free_ char *x = NULL;
         size_t l;
index 24308b702e26e678843325bce94cb137585fb89a..a5ce8258fd9dd3ce1a37f93b57de708c70087950 100644 (file)
@@ -41,6 +41,12 @@ int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned
 int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
 int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, uint64_t nth);
 int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen);
+int in_addr_prefix_range(
+                int family,
+                const union in_addr_union *in,
+                unsigned prefixlen,
+                union in_addr_union *ret_start,
+                union in_addr_union *ret_end);
 int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
 int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret);
 int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret);
index c2cf26d7206046d33319ce569df61ad9bfe3c03c..509ea7e31e58bd253d0f6e9a06c0b1787f971c49 100644 (file)
@@ -314,6 +314,47 @@ static void test_in_addr_prefix_nth(void) {
         test_in_addr_prefix_nth_one(AF_INET6, "1234:5678:90ab:cdef:1234:5678:90ab:cdef", 12, 1, "1240::");
 }
 
+static void test_in_addr_prefix_range_one(
+                int family,
+                const char *in,
+                unsigned prefixlen,
+                const char *expected_start,
+                const char *expected_end) {
+
+        union in_addr_union a, s, e;
+
+        log_info("/* %s(%s, prefixlen=%u) */", __func__, in, prefixlen);
+
+        assert_se(in_addr_from_string(family, in, &a) >= 0);
+        assert_se((in_addr_prefix_range(family, &a, prefixlen, &s, &e) >= 0) == !!expected_start);
+
+        if (expected_start) {
+                union in_addr_union es;
+
+                assert_se(in_addr_from_string(family, expected_start, &es) >= 0);
+                assert_se(in_addr_equal(family, &s, &es) > 0);
+        }
+        if (expected_end) {
+                union in_addr_union ee;
+
+                assert_se(in_addr_from_string(family, expected_end, &ee) >= 0);
+                assert_se(in_addr_equal(family, &e, &ee) > 0);
+        }
+}
+
+static void test_in_addr_prefix_range(void) {
+        test_in_addr_prefix_range_one(AF_INET, "192.168.123.123", 24, "192.168.123.0", "192.168.124.0");
+        test_in_addr_prefix_range_one(AF_INET, "192.168.123.123", 16, "192.168.0.0", "192.169.0.0");
+
+        test_in_addr_prefix_range_one(AF_INET6, "dead:beef::", 64, "dead:beef::", "dead:beef:0:1::");
+        test_in_addr_prefix_range_one(AF_INET6, "dead:0:0:beef::", 64, "dead:0:0:beef::", "dead:0:0:bef0::");
+        test_in_addr_prefix_range_one(AF_INET6, "2001::",  48, "2001::", "2001:0:1::");
+        test_in_addr_prefix_range_one(AF_INET6, "2001::",  56, "2001::", "2001:0:0:0100::");
+        test_in_addr_prefix_range_one(AF_INET6, "2001::",  65, "2001::", "2001::8000:0:0:0");
+        test_in_addr_prefix_range_one(AF_INET6, "2001::",  66, "2001::", "2001::4000:0:0:0");
+        test_in_addr_prefix_range_one(AF_INET6, "2001::", 127, "2001::", "2001::2");
+}
+
 static void test_in_addr_to_string_one(int f, const char *addr) {
         union in_addr_union ua;
         _cleanup_free_ char *r = NULL;
@@ -342,6 +383,7 @@ int main(int argc, char *argv[]) {
         test_in_addr_prefix_intersect();
         test_in_addr_prefix_next();
         test_in_addr_prefix_nth();
+        test_in_addr_prefix_range();
         test_in_addr_to_string();
 
         return 0;