From 217f021925872dcbce4187408762845ae3f6f182 Mon Sep 17 00:00:00 2001 From: Giuseppe Longo Date: Mon, 16 Sep 2013 10:58:16 +0200 Subject: xtables: nft-arp: implements is_same op for ARP family The following patch implements the is_same operation for ARP family needed for searching arp rule. Signed-off-by: Giuseppe Longo Signed-off-by: Pablo Neira Ayuso --- iptables/nft-arp.c | 33 ++++++++++++++++++++++++++++++--- iptables/nft-ipv4.c | 7 +++++-- iptables/nft-ipv6.c | 7 +++++-- iptables/nft-shared.h | 4 ++-- iptables/nft.c | 31 +++++++++++++++++++++++++++++++ iptables/nft.h | 2 ++ iptables/xtables-arp.c | 2 +- 7 files changed, 76 insertions(+), 10 deletions(-) diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c index 6ec8a455..494d2c2f 100644 --- a/iptables/nft-arp.c +++ b/iptables/nft-arp.c @@ -15,12 +15,13 @@ #include #include -#include +#include #include #include #include "nft-shared.h" +#include "nft.h" /* a few names */ char *opcodes[] = @@ -334,7 +335,7 @@ static void nft_arp_parse_payload(struct nft_rule_expr_iter *iter, } } -static void nft_rule_to_arpt_entry(struct nft_rule *r, struct arpt_entry *fw) +void nft_rule_to_arpt_entry(struct nft_rule *r, struct arpt_entry *fw) { struct nft_rule_expr_iter *iter; struct nft_rule_expr *expr; @@ -537,9 +538,35 @@ after_devdst: fputc('\n', stdout); } +static bool nft_arp_is_same(const void *data_a, + const void *data_b) +{ + const struct arpt_entry *a = data_a; + const struct arpt_entry *b = data_b; + + if (a->arp.src.s_addr != b->arp.src.s_addr + || a->arp.tgt.s_addr != b->arp.tgt.s_addr + || a->arp.smsk.s_addr != b->arp.tmsk.s_addr + || a->arp.arpro != b->arp.arpro + || a->arp.flags != b->arp.flags + || a->arp.invflags != b->arp.invflags) { + DEBUGP("different src/dst/proto/flags/invflags\n"); + return false; + } + + return is_same_interfaces(a->arp.src_devaddr.addr, + a->arp.tgt_devaddr.addr, + (unsigned char*)a->arp.src_devaddr.mask, + (unsigned char*)a->arp.tgt_devaddr.mask, + b->arp.src_devaddr.addr, + a->arp.tgt_devaddr.addr, + (unsigned char*)b->arp.src_devaddr.mask, + (unsigned char*)b->arp.tgt_devaddr.mask); +} + struct nft_family_ops nft_family_ops_arp = { .add = nft_arp_add, - .is_same = NULL, + .is_same = nft_arp_is_same, .print_payload = NULL, .parse_meta = nft_arp_parse_meta, .parse_payload = nft_arp_parse_payload, diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c index 40340984..71fbc830 100644 --- a/iptables/nft-ipv4.c +++ b/iptables/nft-ipv4.c @@ -66,9 +66,12 @@ static int nft_ipv4_add(struct nft_rule *r, void *data) return cs->fw.ip.flags; } -static bool nft_ipv4_is_same(const struct iptables_command_state *a, - const struct iptables_command_state *b) +static bool nft_ipv4_is_same(const void *data_a, + const void *data_b) { + const struct iptables_command_state *a = data_a; + const struct iptables_command_state *b = data_b; + if (a->fw.ip.src.s_addr != b->fw.ip.src.s_addr || a->fw.ip.dst.s_addr != b->fw.ip.dst.s_addr || a->fw.ip.smsk.s_addr != b->fw.ip.smsk.s_addr diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c index 2efe95e3..3d35290f 100644 --- a/iptables/nft-ipv6.c +++ b/iptables/nft-ipv6.c @@ -49,9 +49,12 @@ static int nft_ipv6_add(struct nft_rule *r, void *data) return cs->fw6.ipv6.flags; } -static bool nft_ipv6_is_same(const struct iptables_command_state *a, - const struct iptables_command_state *b) +static bool nft_ipv6_is_same(const void *data_a, + const void *data_b) { + const struct iptables_command_state *a = data_a; + const struct iptables_command_state *b = data_b; + if (memcmp(a->fw6.ipv6.src.s6_addr, b->fw6.ipv6.src.s6_addr, sizeof(struct in6_addr)) != 0 || memcmp(a->fw6.ipv6.dst.s6_addr, b->fw6.ipv6.dst.s6_addr, diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h index 375c714f..80f2bc6f 100644 --- a/iptables/nft-shared.h +++ b/iptables/nft-shared.h @@ -38,8 +38,8 @@ struct xtables_args; struct nft_family_ops { int (*add)(struct nft_rule *r, void *data); - bool (*is_same)(const struct iptables_command_state *a, - const struct iptables_command_state *b); + bool (*is_same)(const void *data_a, + const void *data_b); void (*print_payload)(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter); void (*parse_meta)(struct nft_rule_expr *e, uint8_t key, diff --git a/iptables/nft.c b/iptables/nft.c index 28c5473d..8ac43c55 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -2660,10 +2660,41 @@ nft_arp_rule_find(struct nft_rule_list *list, const char *chain, found = true; break; } else { + struct xt_entry_target *t_fw, *t_this; + char *targname_fw, *targname_this; + struct xtables_target *target_fw, *target_this; + /* Delete by matching rule case */ nft_rule_to_arpt_entry(r, &this); DEBUGP("comparing with... "); +#ifdef DEBUG_DEL + nft_rule_print_save(&this, r, NFT_RULE_APPEND, 0); +#endif + + if (!ops->is_same(fw, &this)) + goto next; + + t_fw = nft_arp_get_target(fw); + t_this = nft_arp_get_target(&this); + + targname_fw = t_fw->u.user.name; + targname_this = t_this->u.user.name; + + target_fw = xtables_find_target(targname_fw, XTF_TRY_LOAD); + target_this = xtables_find_target(targname_this, XTF_TRY_LOAD); + + if (target_fw != NULL && target_this != NULL) { + if (!compare_targets(target_fw, target_this)) { + DEBUGP("Different target\n"); + goto next; + } + } else { + if (strcmp(targname_fw, targname_this) != 0) { + DEBUGP("Different verdict\n"); + goto next; + } + } found = true; break; diff --git a/iptables/nft.h b/iptables/nft.h index 25275cee..09d3e0c5 100644 --- a/iptables/nft.h +++ b/iptables/nft.h @@ -162,4 +162,6 @@ int nft_arp_rule_insert(struct nft_handle *h, const char *chain, const char *table, struct arpt_entry *fw, int rulenum, bool verbose); +void nft_rule_to_arpt_entry(struct nft_rule *r, struct arpt_entry *fw); + #endif diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c index 68687c0e..4b3b0461 100644 --- a/iptables/xtables-arp.c +++ b/iptables/xtables-arp.c @@ -1402,7 +1402,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table) handle);*/ break; case CMD_INSERT: - ret = append_entry(h, chain, *table, e, rulenum, + ret = append_entry(h, chain, *table, e, rulenum - 1, nsaddrs, saddrs, ndaddrs, daddrs, options&OPT_VERBOSE, false); break; -- cgit v1.2.3