diff options
Diffstat (limited to 'src/test/test-firewall-util.c')
-rw-r--r-- | src/test/test-firewall-util.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/test/test-firewall-util.c b/src/test/test-firewall-util.c new file mode 100644 index 0000000..3f47a30 --- /dev/null +++ b/src/test/test-firewall-util.c @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include <unistd.h> + +#include "firewall-util.h" +#include "firewall-util-private.h" +#include "log.h" +#include "random-util.h" +#include "socket-util.h" +#include "tests.h" + +static void test_v6(FirewallContext *ctx) { + union in_addr_union u1, u2, u3; + uint8_t prefixlen; + int r; + + assert_se(ctx); + + log_info("/* %s(backend=%s) */", __func__, firewall_backend_to_string(ctx->backend)); + + if (!socket_ipv6_is_supported()) + return log_info("IPv6 is not supported by kernel, skipping tests."); + + assert_se(in_addr_from_string(AF_INET6, "dead::beef", &u1) >= 0); + assert_se(in_addr_from_string(AF_INET6, "1c3::c01d", &u2) >= 0); + + prefixlen = random_u64_range(128 + 1 - 8) + 8; + random_bytes(&u3, sizeof(u3)); + + assert_se(fw_add_masquerade(&ctx, true, AF_INET6, &u1, 128) >= 0); + assert_se(fw_add_masquerade(&ctx, false, AF_INET6, &u1, 128) >= 0); + assert_se(fw_add_masquerade(&ctx, true, AF_INET6, &u1, 64) >= 0); + assert_se(fw_add_masquerade(&ctx, false, AF_INET6, &u1, 64) >= 0); + assert_se(fw_add_masquerade(&ctx, true, AF_INET6, &u3, prefixlen) >= 0); + assert_se(fw_add_masquerade(&ctx, false, AF_INET6, &u3, prefixlen) >= 0); + + r = fw_add_local_dnat(&ctx, true, AF_INET6, IPPROTO_TCP, 4711, &u1, 815, NULL); + if (r == -EOPNOTSUPP) { + log_info("IPv6 DNAT seems not supported, skipping the following tests."); + return; + } + assert_se(r >= 0); + + assert_se(fw_add_local_dnat(&ctx, true, AF_INET6, IPPROTO_TCP, 4711, &u2, 815, &u1) >= 0); + assert_se(fw_add_local_dnat(&ctx, false, AF_INET6, IPPROTO_TCP, 4711, &u2, 815, NULL) >= 0); + +} + +static union in_addr_union *parse_addr(const char *str, union in_addr_union *u) { + assert_se(str); + assert_se(u); + assert_se(in_addr_from_string(AF_INET, str, u) >= 0); + return u; +} + +static bool test_v4(FirewallContext *ctx) { + union in_addr_union u, v; + int r; + + assert_se(ctx); + + log_info("/* %s(backend=%s) */", __func__, firewall_backend_to_string(ctx->backend)); + +#if HAVE_LIBIPTC + if (ctx->backend == FW_BACKEND_IPTABLES && fw_iptables_init_nat(NULL) < 0) { + log_debug("iptables backend is used, but nat table is not enabled, skipping tests"); + return false; + } +#endif + + assert_se(fw_add_masquerade(&ctx, true, AF_INET, NULL, 0) == -EINVAL); + assert_se(fw_add_masquerade(&ctx, true, AF_INET, parse_addr("10.1.2.0", &u), 0) == -EINVAL); + + r = fw_add_masquerade(&ctx, true, AF_INET, parse_addr("10.1.2.3", &u), 32); + if (r < 0) { + bool ignore = IN_SET(r, -EPERM, -EOPNOTSUPP, -ENOPROTOOPT); + + log_full_errno(ignore ? LOG_DEBUG : LOG_ERR, r, + "Failed to add IPv4 masquerade%s: %m", + ignore ? ", skipping following tests" : ""); + + if (ignore) + return false; + } + assert_se(r >= 0); + + assert_se(fw_add_masquerade(&ctx, true, AF_INET, parse_addr("10.0.2.0", &u), 28) >= 0); + assert_se(fw_add_masquerade(&ctx, false, AF_INET, parse_addr("10.0.2.0", &u), 28) >= 0); + assert_se(fw_add_masquerade(&ctx, false, AF_INET, parse_addr("10.1.2.3", &u), 32) >= 0); + assert_se(fw_add_local_dnat(&ctx, true, AF_INET, IPPROTO_TCP, 4711, parse_addr("1.2.3.4", &u), 815, NULL) >= 0); + assert_se(fw_add_local_dnat(&ctx, true, AF_INET, IPPROTO_TCP, 4711, parse_addr("1.2.3.4", &u), 815, NULL) >= 0); + 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); + assert_se(fw_add_local_dnat(&ctx, false, AF_INET, IPPROTO_TCP, 4711, parse_addr("1.2.3.5", &u), 815, NULL) >= 0); + + return true; +} + +int main(int argc, char *argv[]) { + _cleanup_(fw_ctx_freep) FirewallContext *ctx = NULL; + + test_setup_logging(LOG_DEBUG); + + if (getuid() != 0) + return log_tests_skipped("not root"); + + assert_se(fw_ctx_new(&ctx) >= 0); + assert_se(ctx); + + if (ctx->backend == FW_BACKEND_NONE) + return log_tests_skipped("no firewall backend supported"); + + if (test_v4(ctx) && ctx->backend == FW_BACKEND_NFTABLES) + test_v6(ctx); + +#if HAVE_LIBIPTC + if (ctx->backend != FW_BACKEND_IPTABLES) { + ctx->backend = FW_BACKEND_IPTABLES; + test_v4(ctx); + } +#endif + + return 0; +} |