|
|
|
@ -29,7 +29,7 @@ struct iterate_callbacks { |
|
|
|
void (*rule_final)(struct iterate_callbacks *); |
|
|
|
|
|
|
|
// called after all rules have been iterated |
|
|
|
const char *(*iterate_final)(nfapi_socket *nl, int family, const char *chain, |
|
|
|
char *(*iterate_final)(nfapi_socket *nl, int family, const char *chain, |
|
|
|
struct iterate_callbacks *); |
|
|
|
|
|
|
|
// common arguments |
|
|
|
@ -162,7 +162,7 @@ static const char *nftables_do_rule(const int8_t *b, size_t l, void *data) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const char *iterate_rules(nfapi_socket *nl, int family, const char *chain, |
|
|
|
static char *iterate_rules(nfapi_socket *nl, int family, const char *chain, |
|
|
|
struct iterate_callbacks *callbacks) |
|
|
|
{ |
|
|
|
g_autoptr(nfapi_buf) b = nfapi_buf_new(); |
|
|
|
@ -173,31 +173,33 @@ static const char *iterate_rules(nfapi_socket *nl, int family, const char *chain |
|
|
|
nfapi_add_str_attr(b, NFTA_RULE_CHAIN, chain, "chain '%s'", chain); |
|
|
|
|
|
|
|
if (!nfapi_send_buf(nl, b)) |
|
|
|
return "failed to write to netlink socket for iteration"; |
|
|
|
return g_strdup_printf("failed to write to netlink socket trying to read rules (%s)", |
|
|
|
strerror(errno)); |
|
|
|
|
|
|
|
const char *err = nfapi_recv_iter(nl, &(nfapi_callbacks) { .rule = nftables_do_rule }, callbacks); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
return g_strdup_printf("error received from netlink socket reading rules (%s): %s", |
|
|
|
strerror(errno), err); |
|
|
|
|
|
|
|
if (callbacks->iterate_final) |
|
|
|
err = callbacks->iterate_final(nl, family, chain, callbacks); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
if (callbacks->iterate_final) { |
|
|
|
char *e = callbacks->iterate_final(nl, family, chain, callbacks); |
|
|
|
if (e) |
|
|
|
return e; |
|
|
|
} |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool set_rule_handle(nfapi_buf *b, void *data) { |
|
|
|
static void set_rule_handle(nfapi_buf *b, void *data) { |
|
|
|
uint64_t *handle = data; |
|
|
|
nfapi_add_u64_attr(b, NFTA_RULE_HANDLE, *handle, "handle %" PRIu64, *handle); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *delete_rules(nfapi_socket *nl, int family, const char *chain, |
|
|
|
bool (*callback)(nfapi_buf *b, void *data), void *data) |
|
|
|
static char *delete_rules(nfapi_socket *nl, int family, const char *chain, |
|
|
|
void (*callback)(nfapi_buf *b, void *data), void *data) |
|
|
|
{ |
|
|
|
g_autoptr(nfapi_buf) b = nfapi_buf_new(); |
|
|
|
|
|
|
|
@ -207,26 +209,26 @@ static const char *delete_rules(nfapi_socket *nl, int family, const char *chain, |
|
|
|
nfapi_add_str_attr(b, NFTA_RULE_TABLE, "filter", "table 'filter'"); |
|
|
|
nfapi_add_str_attr(b, NFTA_RULE_CHAIN, chain, "chain '%s'", chain); |
|
|
|
|
|
|
|
if (callback) { |
|
|
|
if (!callback(b, data)) |
|
|
|
return "delete rule callback returned error"; |
|
|
|
} |
|
|
|
if (callback) |
|
|
|
callback(b, data); |
|
|
|
|
|
|
|
nfapi_batch_end(b); |
|
|
|
|
|
|
|
if (!nfapi_send_buf(nl, b)) |
|
|
|
return "failed to write to netlink socket for delete rule"; |
|
|
|
return g_strdup_printf("failed to write to netlink socket trying to delete rule (%s)", |
|
|
|
strerror(errno)); |
|
|
|
|
|
|
|
const char *err = nfapi_recv_iter(nl, NULL, NULL); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
return g_strdup_printf("error received from netlink socket trying to delete rule (%s): %s", |
|
|
|
strerror(errno), err); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *iterate_delete_rules(nfapi_socket *nl, int family, const char *chain, |
|
|
|
static char *iterate_delete_rules(nfapi_socket *nl, int family, const char *chain, |
|
|
|
struct iterate_callbacks *callbacks) |
|
|
|
{ |
|
|
|
while (callbacks->iterate_scratch.handles.length) { |
|
|
|
@ -235,7 +237,7 @@ static const char *iterate_delete_rules(nfapi_socket *nl, int family, const char |
|
|
|
uint64_t h = *handle; |
|
|
|
g_free(handle); |
|
|
|
|
|
|
|
const char *err = delete_rules(nl, family, chain, set_rule_handle, &h); |
|
|
|
char *err = delete_rules(nl, family, chain, set_rule_handle, &h); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
} |
|
|
|
@ -281,7 +283,7 @@ static const char *chain_exists(nfapi_socket *nl, int family, const char *chain) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const char *add_chain(nfapi_socket *nl, int family, const char *chain, |
|
|
|
static char *add_chain(nfapi_socket *nl, int family, const char *chain, |
|
|
|
const char *(*callback)(nfapi_buf *)) |
|
|
|
{ |
|
|
|
if (chain_exists(nl, family, chain) == NULL) |
|
|
|
@ -299,23 +301,26 @@ static const char *add_chain(nfapi_socket *nl, int family, const char *chain, |
|
|
|
if (callback) { |
|
|
|
const char *err = callback(b); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
return g_strdup_printf("error returned from callback trying to add chain: %s", |
|
|
|
err); |
|
|
|
} |
|
|
|
|
|
|
|
nfapi_batch_end(b); |
|
|
|
|
|
|
|
if (!nfapi_send_buf(nl, b)) |
|
|
|
return "failed to write to netlink socket for add chain"; |
|
|
|
return g_strdup_printf("failed to write to netlink socket trying to add chain (%s)", |
|
|
|
strerror(errno)); |
|
|
|
|
|
|
|
const char *err = nfapi_recv_iter(nl, NULL, NULL); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
return g_strdup_printf("error received from netlink socket trying to add chain (%s): %s", |
|
|
|
strerror(errno), err); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const char *add_rule(nfapi_socket *nl, int family, |
|
|
|
static char *add_rule(nfapi_socket *nl, int family, |
|
|
|
struct add_rule_callbacks callbacks) |
|
|
|
{ |
|
|
|
g_autoptr(nfapi_buf) b = nfapi_buf_new(); |
|
|
|
@ -329,16 +334,19 @@ static const char *add_rule(nfapi_socket *nl, int family, |
|
|
|
|
|
|
|
const char *err = callbacks.rule_callback(b, family, &callbacks); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
return g_strdup_printf("error returned from callback trying to add table: %s", |
|
|
|
err); |
|
|
|
|
|
|
|
nfapi_batch_end(b); |
|
|
|
|
|
|
|
if (!nfapi_send_buf(nl, b)) |
|
|
|
return "failed to write to netlink socket for add rule"; |
|
|
|
return g_strdup_printf("failed to write to netlink socket trying to add rule (%s)", |
|
|
|
strerror(errno)); |
|
|
|
|
|
|
|
err = nfapi_recv_iter(nl, NULL, NULL); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
return g_strdup_printf("error received from netlink socket trying to add rule (%s): %s", |
|
|
|
strerror(errno), err); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
@ -592,7 +600,7 @@ static const char *rtpe_target_filter(nfapi_buf *b, int family, struct add_rule_ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const char *delete_chain(nfapi_socket *nl, int family, const char *chain) { |
|
|
|
static char *delete_chain(nfapi_socket *nl, int family, const char *chain) { |
|
|
|
g_autoptr(nfapi_buf) b = nfapi_buf_new(); |
|
|
|
|
|
|
|
nfapi_batch_begin(b); |
|
|
|
@ -605,20 +613,22 @@ static const char *delete_chain(nfapi_socket *nl, int family, const char *chain) |
|
|
|
nfapi_batch_end(b); |
|
|
|
|
|
|
|
if (!nfapi_send_buf(nl, b)) |
|
|
|
return "failed to write to netlink socket for delete chain"; |
|
|
|
return g_strdup_printf("failed to write to netlink socket trying to delete chain (%s)", |
|
|
|
strerror(errno)); |
|
|
|
|
|
|
|
const char *err = nfapi_recv_iter(nl, NULL, NULL); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
return g_strdup_printf("error received from netlink socket trying to delete chain (%s): %s", |
|
|
|
strerror(errno), err); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const char *nftables_shutdown_family(nfapi_socket *nl, int family, |
|
|
|
static char *nftables_shutdown_family(nfapi_socket *nl, int family, |
|
|
|
const char *chain, const char *base_chain, nftables_args *args) |
|
|
|
{ |
|
|
|
const char *err; |
|
|
|
char *err; |
|
|
|
|
|
|
|
if (!base_chain || strcmp(base_chain, "none")) { |
|
|
|
// clean up rules in legacy `INPUT` chain |
|
|
|
@ -665,19 +675,21 @@ static const char *nftables_shutdown_family(nfapi_socket *nl, int family, |
|
|
|
if (err) { |
|
|
|
if (errno != ENOENT) // ignore trying to delete stuff that doesn't exist |
|
|
|
return err; |
|
|
|
g_free(err); |
|
|
|
} |
|
|
|
|
|
|
|
err = delete_chain(nl, family, chain); |
|
|
|
if (err) { |
|
|
|
if (errno != ENOENT && errno != EBUSY) // ignore trying to delete stuff that doesn't exist |
|
|
|
return err; |
|
|
|
g_free(err); |
|
|
|
} |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const char *add_table(nfapi_socket *nl, int family) { |
|
|
|
static char *add_table(nfapi_socket *nl, int family) { |
|
|
|
g_autoptr(nfapi_buf) b = nfapi_buf_new(); |
|
|
|
|
|
|
|
nfapi_batch_begin(b); |
|
|
|
@ -689,20 +701,22 @@ static const char *add_table(nfapi_socket *nl, int family) { |
|
|
|
nfapi_batch_end(b); |
|
|
|
|
|
|
|
if (!nfapi_send_buf(nl, b)) |
|
|
|
return "failed to write to netlink socket for add table"; |
|
|
|
return g_strdup_printf("failed to write to netlink socket trying to add table (%s)", |
|
|
|
strerror(errno)); |
|
|
|
|
|
|
|
const char *err = nfapi_recv_iter(nl, NULL, NULL); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
return g_strdup_printf("error received from netlink socket trying to add table (%s): %s", |
|
|
|
strerror(errno), err); |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const char *nftables_setup_family(nfapi_socket *nl, int family, |
|
|
|
static char *nftables_setup_family(nfapi_socket *nl, int family, |
|
|
|
const char *chain, const char *base_chain, nftables_args *args) |
|
|
|
{ |
|
|
|
const char *err = nftables_shutdown_family(nl, family, chain, base_chain, args); |
|
|
|
char *err = nftables_shutdown_family(nl, family, chain, base_chain, args); |
|
|
|
if (err) |
|
|
|
return err; |
|
|
|
|
|
|
|
@ -781,8 +795,8 @@ static const char *nftables_setup_family(nfapi_socket *nl, int family, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const char *nftables_do(const char *chain, const char *base_chain, |
|
|
|
const char *(*do_func)(nfapi_socket *nl, int family, |
|
|
|
static char *nftables_do(const char *chain, const char *base_chain, |
|
|
|
char *(*do_func)(nfapi_socket *nl, int family, |
|
|
|
const char *chain, const char *base_chain, nftables_args *args), |
|
|
|
nftables_args *args) |
|
|
|
{ |
|
|
|
@ -793,9 +807,9 @@ static const char *nftables_do(const char *chain, const char *base_chain, |
|
|
|
|
|
|
|
g_autoptr(nfapi_socket) nl = nfapi_socket_open(); |
|
|
|
if (!nl) |
|
|
|
return "failed to open netlink socket"; |
|
|
|
return g_strdup_printf("failed to open netlink socket (%s)", strerror(errno)); |
|
|
|
|
|
|
|
const char *err = NULL; |
|
|
|
char *err = NULL; |
|
|
|
|
|
|
|
if (args->family == 0 || args->family == NFPROTO_IPV4) |
|
|
|
err = do_func(nl, NFPROTO_IPV4, chain, base_chain, args); |
|
|
|
@ -816,7 +830,7 @@ static const char *nftables_do(const char *chain, const char *base_chain, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const char *nftables_check_family(nfapi_socket *nl, int family, |
|
|
|
static char *nftables_check_family(nfapi_socket *nl, int family, |
|
|
|
const char *chain, const char *base_chain, nftables_args *args) |
|
|
|
{ |
|
|
|
// look for our custom module rule in the specified chain |
|
|
|
@ -827,10 +841,10 @@ static const char *nftables_check_family(nfapi_socket *nl, int family, |
|
|
|
.table = args->table, |
|
|
|
}; |
|
|
|
|
|
|
|
iterate_rules(nl, family, chain, &callbacks); |
|
|
|
g_free( iterate_rules(nl, family, chain, &callbacks) ); |
|
|
|
|
|
|
|
if (!callbacks.iterate_scratch.have_rtpengine_rule) |
|
|
|
return "RTPENGINE rule not found"; |
|
|
|
return g_strdup("rtpengine handler rule not found"); |
|
|
|
|
|
|
|
// look for a rule to jump from a base chain to our custom chain |
|
|
|
|
|
|
|
@ -841,31 +855,37 @@ static const char *nftables_check_family(nfapi_socket *nl, int family, |
|
|
|
.table = args->table, |
|
|
|
}; |
|
|
|
|
|
|
|
iterate_rules(nl, family, "INPUT", &callbacks); |
|
|
|
iterate_rules(nl, family, "input", &callbacks); |
|
|
|
g_free( iterate_rules(nl, family, "INPUT", &callbacks) ); |
|
|
|
g_free( iterate_rules(nl, family, "input", &callbacks) ); |
|
|
|
|
|
|
|
if (base_chain && strcmp(base_chain, "none")) |
|
|
|
iterate_rules(nl, family, base_chain, &callbacks); |
|
|
|
|
|
|
|
if (!callbacks.iterate_scratch.have_imm_jump_rule) |
|
|
|
return "immediate-goto rule not found"; |
|
|
|
g_free( iterate_rules(nl, family, base_chain, &callbacks) ); |
|
|
|
|
|
|
|
if (!callbacks.iterate_scratch.have_imm_jump_rule) { |
|
|
|
if (base_chain && strcmp(base_chain, "none")) |
|
|
|
return g_strdup_printf("immediate-goto rule not found in 'INPUT' or 'input' or '%s'", |
|
|
|
base_chain); |
|
|
|
else |
|
|
|
return g_strdup("immediate-goto rule not found in 'INPUT' or 'input'"); |
|
|
|
} |
|
|
|
|
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const char *nftables_setup(const char *chain, const char *base_chain, nftables_args args) { |
|
|
|
char *nftables_setup(const char *chain, const char *base_chain, nftables_args args) { |
|
|
|
return nftables_do(chain, base_chain, nftables_setup_family, &args); |
|
|
|
} |
|
|
|
|
|
|
|
const char *nftables_shutdown(const char *chain, const char *base_chain, nftables_args args) { |
|
|
|
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); |
|
|
|
char *err = nftables_do(chain, base_chain, nftables_check_family, &args); |
|
|
|
if (err) { |
|
|
|
printf("Netfilter rules check NOT successful: %s\n", err); |
|
|
|
g_free(err); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
|