1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <unistd.h>
4 
5 #include "firewall-util.h"
6 #include "firewall-util-private.h"
7 #include "log.h"
8 #include "random-util.h"
9 #include "socket-util.h"
10 #include "tests.h"
11 
test_v6(FirewallContext * ctx)12 static void test_v6(FirewallContext *ctx) {
13         union in_addr_union u1, u2, u3;
14         uint8_t prefixlen;
15         int r;
16 
17         assert_se(ctx);
18 
19         log_info("/* %s(backend=%s) */", __func__, firewall_backend_to_string(ctx->backend));
20 
21         if (!socket_ipv6_is_supported())
22                 return log_info("IPv6 is not supported by kernel, skipping tests.");
23 
24         assert_se(in_addr_from_string(AF_INET6, "dead::beef", &u1) >= 0);
25         assert_se(in_addr_from_string(AF_INET6, "1c3::c01d", &u2) >= 0);
26 
27         prefixlen = random_u64_range(128 + 1 - 8) + 8;
28         pseudo_random_bytes(&u3, sizeof(u3));
29 
30         assert_se(fw_add_masquerade(&ctx, true, AF_INET6, &u1, 128) >= 0);
31         assert_se(fw_add_masquerade(&ctx, false, AF_INET6, &u1, 128) >= 0);
32         assert_se(fw_add_masquerade(&ctx, true, AF_INET6, &u1, 64) >= 0);
33         assert_se(fw_add_masquerade(&ctx, false, AF_INET6, &u1, 64) >= 0);
34         assert_se(fw_add_masquerade(&ctx, true, AF_INET6, &u3, prefixlen) >= 0);
35         assert_se(fw_add_masquerade(&ctx, false, AF_INET6, &u3, prefixlen) >= 0);
36 
37         r = fw_add_local_dnat(&ctx, true, AF_INET6, IPPROTO_TCP, 4711, &u1, 815, NULL);
38         if (r == -EOPNOTSUPP) {
39                 log_info("IPv6 DNAT seems not supported, skipping the following tests.");
40                 return;
41         }
42         assert_se(r >= 0);
43 
44         assert_se(fw_add_local_dnat(&ctx, true, AF_INET6, IPPROTO_TCP, 4711, &u2, 815, &u1) >= 0);
45         assert_se(fw_add_local_dnat(&ctx, false, AF_INET6, IPPROTO_TCP, 4711, &u2, 815, NULL) >= 0);
46 
47 }
48 
parse_addr(const char * str,union in_addr_union * u)49 static union in_addr_union *parse_addr(const char *str, union in_addr_union *u) {
50         assert_se(str);
51         assert_se(u);
52         assert_se(in_addr_from_string(AF_INET, str, u) >= 0);
53         return u;
54 }
55 
test_v4(FirewallContext * ctx)56 static bool test_v4(FirewallContext *ctx) {
57         union in_addr_union u, v;
58         int r;
59 
60         assert_se(ctx);
61 
62         log_info("/* %s(backend=%s) */", __func__, firewall_backend_to_string(ctx->backend));
63 
64 #if HAVE_LIBIPTC
65         if (ctx->backend == FW_BACKEND_IPTABLES && fw_iptables_init_nat(NULL) < 0) {
66                 log_debug("iptables backend is used, but nat table is not enabled, skipping tests");
67                 return false;
68         }
69 #endif
70 
71         assert_se(fw_add_masquerade(&ctx, true, AF_INET, NULL, 0) == -EINVAL);
72         assert_se(fw_add_masquerade(&ctx, true, AF_INET, parse_addr("10.1.2.0", &u), 0) == -EINVAL);
73 
74         r = fw_add_masquerade(&ctx, true, AF_INET, parse_addr("10.1.2.3", &u), 32);
75         if (r < 0) {
76                 bool ignore = IN_SET(r, -EPERM, -EOPNOTSUPP, -ENOPROTOOPT);
77 
78                 log_full_errno(ignore ? LOG_DEBUG : LOG_ERR, r,
79                                "Failed to add IPv4 masquerade%s: %m",
80                                ignore ? ", skipping following tests" : "");
81 
82                 if (ignore)
83                         return false;
84         }
85         assert_se(r >= 0);
86 
87         assert_se(fw_add_masquerade(&ctx, true, AF_INET, parse_addr("10.0.2.0", &u), 28) >= 0);
88         assert_se(fw_add_masquerade(&ctx, false, AF_INET, parse_addr("10.0.2.0", &u), 28) >= 0);
89         assert_se(fw_add_masquerade(&ctx, false, AF_INET, parse_addr("10.1.2.3", &u), 32) >= 0);
90         assert_se(fw_add_local_dnat(&ctx, true, AF_INET, IPPROTO_TCP, 4711, parse_addr("1.2.3.4", &u), 815, NULL) >= 0);
91         assert_se(fw_add_local_dnat(&ctx, true, AF_INET, IPPROTO_TCP, 4711, parse_addr("1.2.3.4", &u), 815, NULL) >= 0);
92         assert_se(fw_add_local_dnat(&ctx, true, AF_INET, IPPROTO_TCP, 4711, parse_addr("1.2.3.5", &u), 815, parse_addr("1.2.3.4", &v)) >= 0);
93         assert_se(fw_add_local_dnat(&ctx, false, AF_INET, IPPROTO_TCP, 4711, parse_addr("1.2.3.5", &u), 815, NULL) >= 0);
94 
95         return true;
96 }
97 
main(int argc,char * argv[])98 int main(int argc, char *argv[]) {
99         _cleanup_(fw_ctx_freep) FirewallContext *ctx = NULL;
100 
101         test_setup_logging(LOG_DEBUG);
102 
103         if (getuid() != 0)
104                 return log_tests_skipped("not root");
105 
106         assert_se(fw_ctx_new(&ctx) >= 0);
107         assert_se(ctx);
108 
109         if (ctx->backend == FW_BACKEND_NONE)
110                 return EXIT_TEST_SKIP;
111 
112         if (test_v4(ctx) && ctx->backend == FW_BACKEND_NFTABLES)
113                 test_v6(ctx);
114 
115 #if HAVE_LIBIPTC
116         if (ctx->backend != FW_BACKEND_IPTABLES) {
117                 ctx->backend = FW_BACKEND_IPTABLES;
118                 test_v4(ctx);
119         }
120 #endif
121 
122         return 0;
123 }
124