]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
xtables: nft-arp: implements is_same op for ARP family
authorGiuseppe Longo <giuseppelng@gmail.com>
Mon, 16 Sep 2013 08:58:16 +0000 (10:58 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 30 Dec 2013 22:50:46 +0000 (23:50 +0100)
The following patch implements the is_same operation
for ARP family needed for searching arp rule.

Signed-off-by: Giuseppe Longo <giuseppelng@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
iptables/nft-arp.c
iptables/nft-ipv4.c
iptables/nft-ipv6.c
iptables/nft-shared.h
iptables/nft.c
iptables/nft.h
iptables/xtables-arp.c

index 6ec8a455de430f4a5a54462e43eb633d66a30aa0..494d2c2f04711722b3f401572285f99c954242db 100644 (file)
 
 #include <xtables.h>
 #include <net/if_arp.h>
-#include <if_ether.h>
+#include <netinet/if_ether.h>
 
 #include <linux/netfilter_arp/arp_tables.h>
 #include <linux/netfilter/nf_tables.h>
 
 #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,
index 40340984edc98e48fb9d3135ca9e7e42cb24a7b4..71fbc830b66c31c6b751560b3c6a8a5caa3af96b 100644 (file)
@@ -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
index 2efe95e3a890090b5c79062e7244180d4701cf13..3d35290fc4dd54bb84fb1b43ff14f391d2c422d5 100644 (file)
@@ -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,
index 375c714f32f09b9354b1999af7329236689cf51e..80f2bc6fa839326cb5a0030dd17b1c98ece55a7c 100644 (file)
@@ -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,
index 28c5473de3a4033c633b0f41f888a68f725b2597..8ac43c5554ff82d52049c4d355b0240ff02adb93 100644 (file)
@@ -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;
index 25275cee1531fd3cc596c42b74084ad743b84b1d..09d3e0c57538cf77429e69cc3d62c5fb3378a793 100644 (file)
@@ -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
index 68687c0e78925497cb614f0e968e3c47af9d46ef..4b3b0461ffd3d0cac5248b241af9e2603358dd8f 100644 (file)
@@ -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;