From a4024ac51f80963a984dd0a7bfcf33a91640d547 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 19 Oct 2023 10:30:45 -0400 Subject: [PATCH] MT#57371 add --nftables-status option Change-Id: I9925c8c593850729095647b3749fb4b9835b37a4 --- daemon/main.c | 14 +++++++++++--- daemon/nftables.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ docs/rtpengine.md | 6 ++++++ include/nftables.h | 1 + 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/daemon/main.c b/daemon/main.c index 108268150..5bc9786e2 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -491,6 +491,7 @@ static void options(int *argc, char ***argv) { #ifndef WITHOUT_NFTABLES bool nftables_start = false; bool nftables_stop = false; + bool nftables_status = false; AUTO_CLEANUP_GBUF(nftables_family); #endif @@ -506,6 +507,7 @@ static void options(int *argc, char ***argv) { { "nftables-family",0,0, G_OPTION_ARG_STRING, &nftables_family, "Address family/ies to manage via nftables", "ip|ip6|ip,ip6" }, { "nftables-start",0,0, G_OPTION_ARG_NONE, &nftables_start, "Just add nftables rules and exit", NULL }, { "nftables-stop",0, 0, G_OPTION_ARG_NONE, &nftables_stop, "Just remove nftables rules and exit", NULL }, + { "nftables-status",0, 0, G_OPTION_ARG_NONE, &nftables_status, "Check nftables rules, print result and exit", NULL }, #endif { "interface", 'i', 0, G_OPTION_ARG_STRING_ARRAY,&if_a, "Local interface for RTP", "[NAME/]IP[!IP]"}, { "save-interface-ports",'S', 0, G_OPTION_ARG_NONE, &rtpe_config.save_interface_ports, "Bind ports only on first available interface of desired family", NULL }, @@ -684,14 +686,20 @@ static void options(int *argc, char ***argv) { } #ifndef WITHOUT_NFTABLES - if (nftables_start || nftables_stop) { + int nftables_actions = nftables_start + nftables_stop + nftables_status; + if (nftables_actions) { if (!rtpe_config.nftables_chain || !rtpe_config.nftables_chain[0]) die("Cannot do nftables setup without knowing which nftables chain (--nftables-chain=...)"); if (rtpe_config.kernel_table < 0) die("Cannot do nftables setup without configured kernel table number"); - if (nftables_start && nftables_stop) - die("Cannot do both --nftables-start and --nftables-stop"); + if (nftables_actions > 1) + die("Cannot do more than one of --nftables-start, --nftables-stop or --nftables-status"); const char *err; + if (nftables_status) { + int xv = nftables_check(rtpe_config.nftables_chain, rtpe_config.nftables_base_chain, + (nftables_args){.family = rtpe_config.nftables_family}); + exit(xv); + } if (nftables_start) err = nftables_setup(rtpe_config.nftables_chain, rtpe_config.nftables_base_chain, (nftables_args) {.table = rtpe_config.kernel_table, diff --git a/daemon/nftables.c b/daemon/nftables.c index 34b1e74c8..408d5ee28 100644 --- a/daemon/nftables.c +++ b/daemon/nftables.c @@ -646,6 +646,40 @@ static const char *nftables_do(const char *chain, const char *base_chain, } +static const char *nftables_check_family(struct mnl_socket *nl, int family, uint32_t *seq, + const char *chain, const char *base_chain, nftables_args *dummy) +{ + // look for our custom module rule in the specified chain + + struct iterate_callbacks callbacks = { + .parse_expr = match_rtpe, + }; + + iterate_rules(nl, family, chain, seq, &callbacks); + + if (!callbacks.rule_scratch.match_immediate) + return "RTPENGINE rule not found"; + + // look for a rule to jump from a base chain to our custom chain + + callbacks = (__typeof__(callbacks)) { + .parse_expr = match_immediate, + .chain = chain, + }; + + iterate_rules(nl, family, "INPUT", seq, &callbacks); + iterate_rules(nl, family, "input", seq, &callbacks); + + if (base_chain && strcmp(base_chain, "none")) + iterate_rules(nl, family, base_chain, seq, &callbacks); + + if (!callbacks.rule_scratch.match_immediate) + return "immediate-goto rule not found"; + + return NULL; +} + + const char *nftables_setup(const char *chain, const char *base_chain, nftables_args args) { return nftables_do(chain, base_chain, nftables_setup_family, &args); } @@ -653,3 +687,14 @@ const char *nftables_setup(const char *chain, const char *base_chain, nftables_a const char *nftables_shutdown(const char *chain, const char *base_chain, nftables_args args) { return nftables_do(chain, base_chain, nftables_shutdown_family, &args); } + +int nftables_check(const char *chain, const char *base_chain, nftables_args args) { + const char *err = nftables_do(chain, base_chain, nftables_check_family, &args); + if (err) { + printf("Netfilter rules check NOT successful: %s\n", err); + return 1; + } + + printf("Netfilter rules check SUCCESSFUL\n"); + return 0; +} diff --git a/docs/rtpengine.md b/docs/rtpengine.md index 1c45ec7da..fab4579f7 100644 --- a/docs/rtpengine.md +++ b/docs/rtpengine.md @@ -138,6 +138,12 @@ at the command line. See the __\-\-config-file__ option below for details. from a script (typically in combination with an empty __nftables-chain=__ in the main config file). +- __\-\-nftables-status__ + + Instructs __rtpengine__ to check for the existence of the managed netfilter + rules and chains, print the result of check, and exit. The process will + exit with code 0 if the check was successful, and 1 otherwise. + - __-F__, __\-\-no-fallback__ Will prevent fallback to userspace-only operation if the kernel module is diff --git a/include/nftables.h b/include/nftables.h index 68ccfa458..8b0dce28e 100644 --- a/include/nftables.h +++ b/include/nftables.h @@ -11,5 +11,6 @@ typedef struct { const char *nftables_setup(const char *chain, const char *base_chain, nftables_args); const char *nftables_shutdown(const char *chain, const char *base_chain, nftables_args); +int nftables_check(const char *chain, const char *base_chain, nftables_args); #endif