]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft: check for source and destination address in first place
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 1 Jun 2023 19:28:28 +0000 (21:28 +0200)
committerPhil Sutter <phil@nwl.cc>
Fri, 2 Jun 2023 11:05:13 +0000 (13:05 +0200)
When generating bytecode, check for source and destination address in
first place, then, check for the input and output device. In general,
the first expression in the rule is the most evaluated during the
evaluation process. These selectors are likely to show more variability
in rulesets.

 # iptables-nft -vv -I INPUT -s 1.2.3.4 -p tcp
  tcp opt -- in * out *  1.2.3.4  -> 0.0.0.0/0
table filter ip flags 0 use 0 handle 0
ip filter INPUT use 0 type filter hook input prio 0 policy accept packets 0 bytes 0
ip filter INPUT
  [ payload load 4b @ network header + 12 => reg 1 ]
  [ cmp eq reg 1 0x04030201 ]
  [ meta load l4proto => reg 1 ]
  [ cmp eq reg 1 0x00000006 ]
  [ counter pkts 0 bytes 0 ]

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Phil Sutter <phil@nwl.cc>
iptables/nft-bridge.c
iptables/nft-ipv4.c
iptables/nft-ipv6.c

index f3dfa488c6202cf4d70c940b4b55acf4f0ba3421..6e50950774e6e7d3a8ef857a330d6468da4e5d18 100644 (file)
@@ -163,6 +163,20 @@ static int nft_bridge_add(struct nft_handle *h,
        struct ebt_entry *fw = &cs->eb;
        uint32_t op;
 
+       if (fw->bitmask & EBT_ISOURCE) {
+               op = nft_invflags2cmp(fw->invflags, EBT_ISOURCE);
+               add_addr(h, r, NFT_PAYLOAD_LL_HEADER,
+                        offsetof(struct ethhdr, h_source),
+                        fw->sourcemac, fw->sourcemsk, ETH_ALEN, op);
+       }
+
+       if (fw->bitmask & EBT_IDEST) {
+               op = nft_invflags2cmp(fw->invflags, EBT_IDEST);
+               add_addr(h, r, NFT_PAYLOAD_LL_HEADER,
+                        offsetof(struct ethhdr, h_dest),
+                        fw->destmac, fw->destmsk, ETH_ALEN, op);
+       }
+
        if (fw->in[0] != '\0') {
                op = nft_invflags2cmp(fw->invflags, EBT_IIN);
                add_iniface(h, r, fw->in, op);
@@ -183,20 +197,6 @@ static int nft_bridge_add(struct nft_handle *h,
                add_logical_outiface(h, r, fw->logical_out, op);
        }
 
-       if (fw->bitmask & EBT_ISOURCE) {
-               op = nft_invflags2cmp(fw->invflags, EBT_ISOURCE);
-               add_addr(h, r, NFT_PAYLOAD_LL_HEADER,
-                        offsetof(struct ethhdr, h_source),
-                        fw->sourcemac, fw->sourcemsk, ETH_ALEN, op);
-       }
-
-       if (fw->bitmask & EBT_IDEST) {
-               op = nft_invflags2cmp(fw->invflags, EBT_IDEST);
-               add_addr(h, r, NFT_PAYLOAD_LL_HEADER,
-                        offsetof(struct ethhdr, h_dest),
-                        fw->destmac, fw->destmsk, ETH_ALEN, op);
-       }
-
        if ((fw->bitmask & EBT_NOPROTO) == 0) {
                uint16_t ethproto = fw->ethproto;
                uint8_t reg;
index 6df4e46bc37730180122c1529fd45868f7bffa6b..d67d8198bfaf0155fa9107bc7ece16c7ed8474e9 100644 (file)
@@ -33,6 +33,22 @@ static int nft_ipv4_add(struct nft_handle *h, struct nftnl_rule *r,
        uint32_t op;
        int ret;
 
+       if (cs->fw.ip.src.s_addr || cs->fw.ip.smsk.s_addr || cs->fw.ip.invflags & IPT_INV_SRCIP) {
+               op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_SRCIP);
+               add_addr(h, r, NFT_PAYLOAD_NETWORK_HEADER,
+                        offsetof(struct iphdr, saddr),
+                        &cs->fw.ip.src.s_addr, &cs->fw.ip.smsk.s_addr,
+                        sizeof(struct in_addr), op);
+       }
+
+       if (cs->fw.ip.dst.s_addr || cs->fw.ip.dmsk.s_addr || cs->fw.ip.invflags & IPT_INV_DSTIP) {
+               op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_DSTIP);
+               add_addr(h, r, NFT_PAYLOAD_NETWORK_HEADER,
+                        offsetof(struct iphdr, daddr),
+                        &cs->fw.ip.dst.s_addr, &cs->fw.ip.dmsk.s_addr,
+                        sizeof(struct in_addr), op);
+       }
+
        if (cs->fw.ip.iniface[0] != '\0') {
                op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_VIA_IN);
                add_iniface(h, r, cs->fw.ip.iniface, op);
@@ -48,20 +64,6 @@ static int nft_ipv4_add(struct nft_handle *h, struct nftnl_rule *r,
                add_l4proto(h, r, cs->fw.ip.proto, op);
        }
 
-       if (cs->fw.ip.src.s_addr || cs->fw.ip.smsk.s_addr || cs->fw.ip.invflags & IPT_INV_SRCIP) {
-               op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_SRCIP);
-               add_addr(h, r, NFT_PAYLOAD_NETWORK_HEADER,
-                        offsetof(struct iphdr, saddr),
-                        &cs->fw.ip.src.s_addr, &cs->fw.ip.smsk.s_addr,
-                        sizeof(struct in_addr), op);
-       }
-       if (cs->fw.ip.dst.s_addr || cs->fw.ip.dmsk.s_addr || cs->fw.ip.invflags & IPT_INV_DSTIP) {
-               op = nft_invflags2cmp(cs->fw.ip.invflags, IPT_INV_DSTIP);
-               add_addr(h, r, NFT_PAYLOAD_NETWORK_HEADER,
-                        offsetof(struct iphdr, daddr),
-                        &cs->fw.ip.dst.s_addr, &cs->fw.ip.dmsk.s_addr,
-                        sizeof(struct in_addr), op);
-       }
        if (cs->fw.ip.flags & IPT_F_FRAG) {
                uint8_t reg;
 
index 693a1c87b997dc2996104b1016b8e1b9ea9d95f8..658a4f2018959e84a2b0c3a08032db4edf0dfa76 100644 (file)
@@ -32,21 +32,6 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r,
        uint32_t op;
        int ret;
 
-       if (cs->fw6.ipv6.iniface[0] != '\0') {
-               op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_VIA_IN);
-               add_iniface(h, r, cs->fw6.ipv6.iniface, op);
-       }
-
-       if (cs->fw6.ipv6.outiface[0] != '\0') {
-               op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_VIA_OUT);
-               add_outiface(h, r, cs->fw6.ipv6.outiface, op);
-       }
-
-       if (cs->fw6.ipv6.proto != 0) {
-               op = nft_invflags2cmp(cs->fw6.ipv6.invflags, XT_INV_PROTO);
-               add_l4proto(h, r, cs->fw6.ipv6.proto, op);
-       }
-
        if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src) ||
            !IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.smsk) ||
            (cs->fw6.ipv6.invflags & IPT_INV_SRCIP)) {
@@ -56,6 +41,7 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r,
                         &cs->fw6.ipv6.src, &cs->fw6.ipv6.smsk,
                         sizeof(struct in6_addr), op);
        }
+
        if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst) ||
            !IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dmsk) ||
            (cs->fw6.ipv6.invflags & IPT_INV_DSTIP)) {
@@ -65,6 +51,22 @@ static int nft_ipv6_add(struct nft_handle *h, struct nftnl_rule *r,
                         &cs->fw6.ipv6.dst, &cs->fw6.ipv6.dmsk,
                         sizeof(struct in6_addr), op);
        }
+
+       if (cs->fw6.ipv6.iniface[0] != '\0') {
+               op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_VIA_IN);
+               add_iniface(h, r, cs->fw6.ipv6.iniface, op);
+       }
+
+       if (cs->fw6.ipv6.outiface[0] != '\0') {
+               op = nft_invflags2cmp(cs->fw6.ipv6.invflags, IPT_INV_VIA_OUT);
+               add_outiface(h, r, cs->fw6.ipv6.outiface, op);
+       }
+
+       if (cs->fw6.ipv6.proto != 0) {
+               op = nft_invflags2cmp(cs->fw6.ipv6.invflags, XT_INV_PROTO);
+               add_l4proto(h, r, cs->fw6.ipv6.proto, op);
+       }
+
        add_compat(r, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags & XT_INV_PROTO);
 
        for (matchp = cs->matches; matchp; matchp = matchp->next) {