]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
add ipv6 range element creation test cases 18007/head
authorFlorian Westphal <fw@strlen.de>
Tue, 22 Dec 2020 11:57:00 +0000 (12:57 +0100)
committerFlorian Westphal <fw@strlen.de>
Tue, 19 Jan 2021 15:38:56 +0000 (16:38 +0100)
The nft set backend doesn't support network masks, it works with
ranges.  Inputs like dead::/64 thus need to be translated to two
'start' and 'end' elements.

The 'start' element is the first element in the range (i.e., dead::).
The 'stop' element is the first element *past* the range, (dead:0:0100::
in the example).

This adds a few test cases.

src/shared/firewall-util-nft.c
src/test/test-firewall-util.c

index 22c0dc0980c7737c1b9f0dd545dd5200d3a4b8bf..0259a80914a4ecf4730a8fc5b5d5c9d793a098a5 100644 (file)
@@ -30,6 +30,9 @@
 
 #define UDP_DPORT_OFFSET 2
 
+void nft_in6addr_to_range(const union in_addr_union *source, unsigned int prefixlen,
+                          struct in6_addr *start, struct in6_addr *end);
+
 static int nfnl_netlink_sendv(sd_netlink *nfnl,
                               sd_netlink_message *messages[],
                               size_t msgcount) {
@@ -845,8 +848,8 @@ static int fw_nftables_recreate_table(sd_netlink *nfnl, int af, sd_netlink_messa
         return 0;
 }
 
-static void nft_in6addr_to_range(const union in_addr_union *source, unsigned int prefixlen,
-                                 struct in6_addr *ret_start, struct in6_addr *ret_end) {
+void nft_in6addr_to_range(const union in_addr_union *source, unsigned int prefixlen,
+                          struct in6_addr *ret_start, struct in6_addr *ret_end) {
         uint8_t carry = 0;
         int i, j;
 
index 4cb43cc585f3dc10173309a96f8d6cc2cb978cd8..d5501b807d17eb80120202f715c9fda018d34230 100644 (file)
@@ -9,10 +9,25 @@
 
 #define MAKE_IN_ADDR_UNION(a,b,c,d) (union in_addr_union) { .in.s_addr = htobe32((uint32_t) (a) << 24 | (uint32_t) (b) << 16 | (uint32_t) (c) << 8 | (uint32_t) (d))}
 
+void nft_in6addr_to_range(const union in_addr_union *source, unsigned int prefixlen,
+                          struct in6_addr *start, struct in6_addr *end);
+
 static void make_in6_addr_union(const char *addr, union in_addr_union *u) {
         assert_se(inet_pton(AF_INET6, addr, &u->in6) >= 0);
 }
 
+static bool test_in6_eq(const char *addr, const union in_addr_union *u) {
+        union in_addr_union tmp;
+
+        make_in6_addr_union(addr, &tmp);
+
+        return memcmp(&tmp.in6, &u->in6, sizeof(tmp.in6)) == 0;
+}
+
+static void assert_in6_eq(const union in_addr_union *a, const union in_addr_union *b) {
+        assert_se(memcmp(&a->in6, &b->in6, sizeof(a->in6)) == 0);
+}
+
 static void test_v6(FirewallContext **ctx) {
         union in_addr_union u = {}, u2 = {};
         uint8_t prefixlen;
@@ -62,6 +77,52 @@ static void test_v6(FirewallContext **ctx) {
                 log_error_errno(r, "Failed to modify ipv6 firewall: %m");
 }
 
+static void test_v6_range(void) {
+        unsigned int prefixlen = 64;
+        union in_addr_union a, b, s;
+
+        make_in6_addr_union("dead:0:0:beef::", &s);
+
+        nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
+
+        assert_in6_eq(&s, &a);
+        assert_se(test_in6_eq("dead:0:0:bef0::", &b));
+
+        make_in6_addr_union("2001::", &s);
+        prefixlen = 56;
+        nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
+        assert_in6_eq(&s, &a);
+        assert_se(test_in6_eq("2001:0:0:0100::", &b));
+
+        prefixlen = 48;
+        nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
+        assert_in6_eq(&s, &a);
+
+        assert_se(test_in6_eq("2001:0:0001::", &b));
+
+        prefixlen = 65;
+        nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
+        assert_se(test_in6_eq("2001::", &a));
+
+        assert_se(test_in6_eq("2001::8000:0:0:0", &b));
+
+        prefixlen = 66;
+        nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
+        assert_in6_eq(&s, &a);
+
+        assert_se(test_in6_eq("2001::4000:0:0:0", &b));
+
+        prefixlen = 127;
+        nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
+        assert_in6_eq(&s, &a);
+        assert_se(test_in6_eq("2001::0002", &b));
+
+        make_in6_addr_union("dead:beef::1", &s);
+        prefixlen = 64;
+        nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
+        assert_se(test_in6_eq("dead:beef::", &a));
+}
+
 int main(int argc, char *argv[]) {
         _cleanup_(fw_ctx_freep) FirewallContext *ctx;
         int r;
@@ -114,6 +175,7 @@ int main(int argc, char *argv[]) {
                 log_error_errno(r, "Failed to modify firewall: %m");
 
         test_v6(&ctx);
+        test_v6_range();
 
         return 0;
 }