]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
evaluate: skip byteorder conversion for selector smaller than 2 bytes
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 7 Feb 2024 22:53:32 +0000 (23:53 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 22 Jan 2025 23:41:54 +0000 (00:41 +0100)
commit 9fe58952c45a1643dc7df1a0b1f5d88e8ae1a978 upstream.

Add unary expression to trigger byteorder conversion for host byteorder
selectors only if selectors length is larger or equal than 2 bytes.

 # cat test.nft
 table ip x {
        set test {
                type ipv4_addr . ether_addr . inet_proto
                flags interval
        }

        chain y {
                ip saddr . ether saddr . meta l4proto @test counter
        }
 }

 # nft -f test.nft
 ip x y
  [ meta load iiftype => reg 1 ]
  [ cmp eq reg 1 0x00000001 ]
  [ payload load 4b @ network header + 12 => reg 1 ]
  [ payload load 6b @ link header + 6 => reg 9 ]
  [ meta load l4proto => reg 11 ]
  [ byteorder reg 11 = hton(reg 11, 2, 1) ] <--- should not be here
  [ lookup reg 1 set test ]
  [ counter pkts 0 bytes 0 ]

Fixes: 1017d323cafa ("src: support for selectors with different byteorder with interval concatenations")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/evaluate.c
tests/py/inet/meta.t
tests/py/inet/meta.t.json
tests/py/inet/meta.t.json.output
tests/py/inet/meta.t.payload

index 97ae2609b99ad2b2642e89b3aa12fb5598133483..91c7ce07cd1a2b6694104284cd8d947d1de7d3f4 100644 (file)
@@ -193,12 +193,14 @@ static int byteorder_conversion(struct eval_ctx *ctx, struct expr **expr,
 
                        assert(basetype == TYPE_INTEGER);
 
-                       op = byteorder_conversion_op(i, byteorder);
-                       unary = unary_expr_alloc(&i->location, op, i);
-                       if (expr_evaluate(ctx, &unary) < 0)
-                               return -1;
+                       if (div_round_up(i->len, BITS_PER_BYTE) >= 2) {
+                               op = byteorder_conversion_op(i, byteorder);
+                               unary = unary_expr_alloc(&i->location, op, i);
+                               if (expr_evaluate(ctx, &unary) < 0)
+                                       return -1;
 
-                       list_replace(&i->list, &unary->list);
+                               list_replace(&i->list, &unary->list);
+                       }
                }
 
                return 0;
index 374738a701d642adf1732411bb1c6caa65bcb101..7d2515c97f47902d30ce1afc6ce11a38d871b7a8 100644 (file)
@@ -25,3 +25,9 @@ meta mark set ct mark >> 8;ok
 meta mark . tcp dport { 0x0000000a-0x00000014 . 80-90, 0x00100000-0x00100123 . 100-120 };ok
 ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 1.2.3.6-1.2.3.8 . 0x00000200-0x00000300 };ok
 ip saddr . meta mark { 1.2.3.4 . 0x00000100 , 5.6.7.8 . 0x00000200 };ok
+ip saddr . ether saddr . meta l4proto { 1.2.3.4 . aa:bb:cc:dd:ee:ff . 6 };ok
+
+meta mark set ip dscp;ok
+meta mark set ip dscp | 0x40;ok
+meta mark set ip6 dscp;ok
+meta mark set ip6 dscp | 0x40;ok
index 92a1f9bff37352887a85bbb360bee15b167aef1f..a9869e9bb22d74d9ac202f1683e600b341b5ad10 100644 (file)
     }
 ]
 
+# meta mark set ip dscp
+[
+    {
+        "mangle": {
+            "key": {
+                "meta": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "payload": {
+                    "field": "dscp",
+                    "protocol": "ip"
+                }
+            }
+        }
+    }
+]
+
+# meta mark set ip dscp | 0x40
+[
+    {
+        "mangle": {
+            "key": {
+                "meta": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip"
+                        }
+                    },
+                    64
+                ]
+            }
+        }
+    }
+]
+
+# meta mark set ip6 dscp
+[
+    {
+        "mangle": {
+            "key": {
+                "meta": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "payload": {
+                    "field": "dscp",
+                    "protocol": "ip6"
+                }
+            }
+        }
+    }
+]
+
+# meta mark set ip6 dscp | 0x40
+[
+    {
+        "mangle": {
+            "key": {
+                "meta": {
+                    "key": "mark"
+                }
+            },
+            "value": {
+                "|": [
+                    {
+                        "payload": {
+                            "field": "dscp",
+                            "protocol": "ip6"
+                        }
+                    },
+                    64
+                ]
+            }
+        }
+    }
+]
+
+# ip saddr . ether saddr . meta l4proto { 1.2.3.4 . aa:bb:cc:dd:ee:ff . 6 }
+[
+    {
+        "match": {
+            "left": {
+                "concat": [
+                    {
+                        "payload": {
+                            "field": "saddr",
+                            "protocol": "ip"
+                        }
+                    },
+                    {
+                        "payload": {
+                            "field": "saddr",
+                            "protocol": "ether"
+                        }
+                    },
+                    {
+                        "meta": {
+                            "key": "l4proto"
+                        }
+                    }
+                ]
+            },
+            "op": "==",
+            "right": {
+                "set": [
+                    {
+                        "concat": [
+                            "1.2.3.4",
+                            "aa:bb:cc:dd:ee:ff",
+                            "tcp"
+                        ]
+                    }
+                ]
+            }
+        }
+    }
+]
index 3e7dd2145e67f45ab4680a86498a6360773e1f9d..8697d5a2b9e22311c3a4fcf1884f546b3b59628a 100644 (file)
     }
 ]
 
+# ip saddr . ether saddr . meta l4proto { 1.2.3.4 . aa:bb:cc:dd:ee:ff . 6 }
+[
+    {
+        "match": {
+            "left": {
+                "concat": [
+                    {
+                        "payload": {
+                            "field": "saddr",
+                            "protocol": "ip"
+                        }
+                    },
+                    {
+                        "payload": {
+                            "field": "saddr",
+                            "protocol": "ether"
+                        }
+                    },
+                    {
+                        "meta": {
+                            "key": "l4proto"
+                        }
+                    }
+                ]
+            },
+            "op": "==",
+            "right": {
+                "set": [
+                    {
+                        "concat": [
+                            "1.2.3.4",
+                            "aa:bb:cc:dd:ee:ff",
+                            6
+                        ]
+                    }
+                ]
+            }
+        }
+    }
+]
+
index ea54090727faa0f8d4821143466bf5c9abe8d579..65b55babb51b58ed5fb2963d8dfe6eac091d10e8 100644 (file)
@@ -133,3 +133,56 @@ inet test-inet input
   [ meta load mark => reg 9 ]
   [ lookup reg 1 set __set%d ]
 
+# meta mark set ip dscp
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x00000002 ]
+  [ payload load 1b @ network header + 1 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+  [ meta set mark with reg 1 ]
+
+# meta mark set ip dscp | 0x40
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x00000002 ]
+  [ payload load 1b @ network header + 1 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
+  [ bitwise reg 1 = ( reg 1 & 0xffffffbf ) ^ 0x00000040 ]
+  [ meta set mark with reg 1 ]
+
+# meta mark set ip6 dscp
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x0000000a ]
+  [ payload load 2b @ network header + 0 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+  [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+  [ meta set mark with reg 1 ]
+
+# meta mark set ip6 dscp | 0x40
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x0000000a ]
+  [ payload load 2b @ network header + 0 => reg 1 ]
+  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
+  [ byteorder reg 1 = ntoh(reg 1, 2, 2) ]
+  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
+  [ bitwise reg 1 = ( reg 1 & 0xffffffbf ) ^ 0x00000040 ]
+  [ meta set mark with reg 1 ]
+
+# ip saddr . ether saddr . meta l4proto { 1.2.3.4 . aa:bb:cc:dd:ee:ff . 6 }
+__set%d test-inet 3 size 1
+__set%d test-inet 0
+       element 04030201 ddccbbaa 0000ffee 00000006  : 0 [end]
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x00000002 ]
+  [ meta load iiftype => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+  [ payload load 4b @ network header + 12 => reg 1 ]
+  [ payload load 6b @ link header + 6 => reg 9 ]
+  [ meta load l4proto => reg 11 ]
+  [ lookup reg 1 set __set%d ]