diff options
author | Phil Sutter <phil@nwl.cc> | 2021-09-27 16:59:49 +0200 |
---|---|---|
committer | Phil Sutter <phil@nwl.cc> | 2021-10-20 11:32:54 +0200 |
commit | dded8ff3878ba7dccb8573543f2c2c5c8670fa03 (patch) | |
tree | 823493d91909af96a5f9438a057c2bfcb7adaada /iptables/nft-ipv4.c | |
parent | 38e1fe58fe814e4364155085327c0b1e2d9527ee (diff) |
nft: Add family ops callbacks wrapping different nft_cmd_* functions
Commands supporting multiple source/destination addresses need to
iterate over them and call the respective nft_cmd_* function multiple
times. These loops are family-specific though as each family uses a
different data structure within struct iptables_command_state to store
the addresses.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Diffstat (limited to 'iptables/nft-ipv4.c')
-rw-r--r-- | iptables/nft-ipv4.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c index 34f94bd8..febd7673 100644 --- a/iptables/nft-ipv4.c +++ b/iptables/nft-ipv4.c @@ -468,6 +468,95 @@ static int nft_ipv4_xlate(const void *data, struct xt_xlate *xl) return ret; } +static int +nft_ipv4_add_entry(struct nft_handle *h, + const char *chain, const char *table, + struct iptables_command_state *cs, + struct xtables_args *args, bool verbose, + bool append, int rulenum) +{ + unsigned int i, j; + int ret = 1; + + for (i = 0; i < args->s.naddrs; i++) { + cs->fw.ip.src.s_addr = args->s.addr.v4[i].s_addr; + cs->fw.ip.smsk.s_addr = args->s.mask.v4[i].s_addr; + for (j = 0; j < args->d.naddrs; j++) { + cs->fw.ip.dst.s_addr = args->d.addr.v4[j].s_addr; + cs->fw.ip.dmsk.s_addr = args->d.mask.v4[j].s_addr; + + if (append) { + ret = nft_cmd_rule_append(h, chain, table, + cs, NULL, verbose); + } else { + ret = nft_cmd_rule_insert(h, chain, table, + cs, rulenum, verbose); + } + } + } + + return ret; +} + +static int +nft_ipv4_delete_entry(struct nft_handle *h, + const char *chain, const char *table, + struct iptables_command_state *cs, + struct xtables_args *args, bool verbose) +{ + unsigned int i, j; + int ret = 1; + + for (i = 0; i < args->s.naddrs; i++) { + cs->fw.ip.src.s_addr = args->s.addr.v4[i].s_addr; + cs->fw.ip.smsk.s_addr = args->s.mask.v4[i].s_addr; + for (j = 0; j < args->d.naddrs; j++) { + cs->fw.ip.dst.s_addr = args->d.addr.v4[j].s_addr; + cs->fw.ip.dmsk.s_addr = args->d.mask.v4[j].s_addr; + ret = nft_cmd_rule_delete(h, chain, table, cs, verbose); + } + } + + return ret; +} + +static int +nft_ipv4_check_entry(struct nft_handle *h, + const char *chain, const char *table, + struct iptables_command_state *cs, + struct xtables_args *args, bool verbose) +{ + unsigned int i, j; + int ret = 1; + + for (i = 0; i < args->s.naddrs; i++) { + cs->fw.ip.src.s_addr = args->s.addr.v4[i].s_addr; + cs->fw.ip.smsk.s_addr = args->s.mask.v4[i].s_addr; + for (j = 0; j < args->d.naddrs; j++) { + cs->fw.ip.dst.s_addr = args->d.addr.v4[j].s_addr; + cs->fw.ip.dmsk.s_addr = args->d.mask.v4[j].s_addr; + ret = nft_cmd_rule_check(h, chain, table, cs, verbose); + } + } + + return ret; +} + +static int +nft_ipv4_replace_entry(struct nft_handle *h, + const char *chain, const char *table, + struct iptables_command_state *cs, + struct xtables_args *args, bool verbose, + int rulenum) +{ + cs->fw.ip.src.s_addr = args->s.addr.v4->s_addr; + cs->fw.ip.dst.s_addr = args->d.addr.v4->s_addr; + cs->fw.ip.smsk.s_addr = args->s.mask.v4->s_addr; + cs->fw.ip.dmsk.s_addr = args->d.mask.v4->s_addr; + + return nft_cmd_rule_replace(h, chain, table, cs, rulenum, verbose); +} + struct nft_family_ops nft_family_ops_ipv4 = { .add = nft_ipv4_add, .is_same = nft_ipv4_is_same, @@ -484,4 +573,8 @@ struct nft_family_ops nft_family_ops_ipv4 = { .rule_to_cs = nft_rule_to_iptables_command_state, .clear_cs = nft_clear_iptables_command_state, .xlate = nft_ipv4_xlate, + .add_entry = nft_ipv4_add_entry, + .delete_entry = nft_ipv4_delete_entry, + .check_entry = nft_ipv4_check_entry, + .replace_entry = nft_ipv4_replace_entry, }; |