]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
netlink: rework range_expr_to_prefix()
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 6 Sep 2021 20:04:51 +0000 (22:04 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 8 Sep 2021 23:13:47 +0000 (01:13 +0200)
Consolidate prefix calculation in range_expr_is_prefix().

Add tests/py for 9208fb30dc49 ("src: Check range bounds before converting to
prefix").

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/netlink.c
tests/py/ip/snat.t
tests/py/ip/snat.t.json
tests/py/ip/snat.t.payload

index 0fd0b6647643f147463e55063e8645909b9dd1bd..9a0d96f0b546751726034aca5a142df27d059531 100644 (file)
@@ -1048,48 +1048,54 @@ void alloc_setelem_cache(const struct expr *set, struct nftnl_set *nls)
        }
 }
 
-static bool mpz_bitmask_is_prefix(mpz_t bitmask, uint32_t len)
+static bool range_expr_is_prefix(const struct expr *range, uint32_t *prefix_len)
 {
+       const struct expr *right = range->right;
+       const struct expr *left = range->left;
+       uint32_t len = left->len;
        unsigned long n1, n2;
+       uint32_t plen;
+       mpz_t bitmask;
 
-        n1 = mpz_scan0(bitmask, 0);
-        if (n1 == ULONG_MAX)
-                return false;
+       mpz_init2(bitmask, left->len);
+       mpz_xor(bitmask, left->value, right->value);
 
-        n2 = mpz_scan1(bitmask, n1 + 1);
-        if (n2 < len)
-                return false;
+       n1 = mpz_scan0(bitmask, 0);
+       if (n1 == ULONG_MAX)
+               goto not_a_prefix;
 
-        return true;
-}
+       n2 = mpz_scan1(bitmask, n1 + 1);
+       if (n2 < len)
+               goto not_a_prefix;
 
-static uint32_t mpz_bitmask_to_prefix(mpz_t bitmask, uint32_t len)
-{
-       return len - mpz_scan0(bitmask, 0);
+       plen = len - n1;
+
+       if (mpz_scan1(left->value, 0) < len - plen)
+               goto not_a_prefix;
+
+       mpz_clear(bitmask);
+       *prefix_len = plen;
+
+       return true;
+
+not_a_prefix:
+       mpz_clear(bitmask);
+
+       return false;
 }
 
 struct expr *range_expr_to_prefix(struct expr *range)
 {
-       struct expr *left = range->left, *right = range->right, *prefix;
-       uint32_t len = left->len, prefix_len;
-       mpz_t bitmask;
-
-       mpz_init2(bitmask, len);
-       mpz_xor(bitmask, left->value, right->value);
+       struct expr *prefix;
+       uint32_t prefix_len;
 
-       if (mpz_bitmask_is_prefix(bitmask, len)) {
-               prefix_len = mpz_bitmask_to_prefix(bitmask, len);
-               if (mpz_scan1(left->value, 0) >= len - prefix_len) {
-                       prefix = prefix_expr_alloc(&range->location,
-                                                  expr_get(left),
-                                                  prefix_len);
-                       mpz_clear(bitmask);
-                       expr_free(range);
-
-                       return prefix;
-               }
+       if (range_expr_is_prefix(range, &prefix_len)) {
+               prefix = prefix_expr_alloc(&range->location,
+                                          expr_get(range->left),
+                                          prefix_len);
+               expr_free(range);
+               return prefix;
        }
-       mpz_clear(bitmask);
 
        return range;
 }
index 38acf52ffe094e1540ef1185da8580ae9f6ccd3e..a8ff8d1a00c1b017d4c9db6df02c8b4f38138ba3 100644 (file)
@@ -6,6 +6,8 @@ iifname "eth0" tcp dport 80-90 snat to 192.168.3.2;ok
 iifname "eth0" tcp dport != 80-90 snat to 192.168.3.2;ok
 iifname "eth0" tcp dport {80, 90, 23} snat to 192.168.3.2;ok
 iifname "eth0" tcp dport != {80, 90, 23} snat to 192.168.3.2;ok
+iifname "eth0" tcp dport 80-90 snat to 192.168.3.0-192.168.3.255;ok;iifname "eth0" tcp dport 80-90 snat to 192.168.3.0/24
+iifname "eth0" tcp dport 80-90 snat to 192.168.3.15-192.168.3.240;ok
 
 iifname "eth0" tcp dport != 23-34 snat to 192.168.3.2;ok
 
index 0e1485faedfc7c1f816b749cbb50052baccd280b..0813086c8405d87a73311b2624d01f89ddd85b18 100644 (file)
     }
 ]
 
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.0-192.168.3.255
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "iifname"
+                }
+            },
+            "op": "==",
+            "right": "eth0"
+        }
+    },
+    {
+        "match": {
+            "left": {
+                "payload": {
+                    "field": "dport",
+                    "protocol": "tcp"
+                }
+            },
+            "op": "==",
+            "right": {
+                "range": [
+                    80,
+                    90
+                ]
+            }
+        }
+    },
+    {
+        "snat": {
+            "addr": {
+                "prefix": {
+                    "addr": "192.168.3.0",
+                    "len": 24
+                }
+            }
+        }
+    }
+]
+
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.15-192.168.3.240
+[
+    {
+        "match": {
+            "left": {
+                "meta": {
+                    "key": "iifname"
+                }
+            },
+            "op": "==",
+            "right": "eth0"
+        }
+    },
+    {
+        "match": {
+            "left": {
+                "payload": {
+                    "field": "dport",
+                    "protocol": "tcp"
+                }
+            },
+            "op": "==",
+            "right": {
+                "range": [
+                    80,
+                    90
+                ]
+            }
+        }
+    },
+    {
+        "snat": {
+            "addr": {
+                "range": [
+                    "192.168.3.15",
+                    "192.168.3.240"
+                ]
+            }
+        }
+    }
+]
+
 # snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }
 [
     {
index 58b1c1a484eba48152317d8c53c1b73dc692eb90..64f478964a40ea7446523f1f3c9a75f3e55d507b 100644 (file)
@@ -60,6 +60,32 @@ ip test-ip4 postrouting
   [ immediate reg 1 0x0203a8c0 ]
   [ nat snat ip addr_min reg 1 ]
 
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.0-192.168.3.255
+ip
+  [ meta load iifname => reg 1 ]
+  [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+  [ meta load l4proto => reg 1 ]
+  [ cmp eq reg 1 0x00000006 ]
+  [ payload load 2b @ transport header + 2 => reg 1 ]
+  [ cmp gte reg 1 0x00005000 ]
+  [ cmp lte reg 1 0x00005a00 ]
+  [ immediate reg 1 0x0003a8c0 ]
+  [ immediate reg 2 0xff03a8c0 ]
+  [ nat snat ip addr_min reg 1 addr_max reg 2 ]
+
+# iifname "eth0" tcp dport 80-90 snat to 192.168.3.15-192.168.3.240
+ip
+  [ meta load iifname => reg 1 ]
+  [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ]
+  [ meta load l4proto => reg 1 ]
+  [ cmp eq reg 1 0x00000006 ]
+  [ payload load 2b @ transport header + 2 => reg 1 ]
+  [ cmp gte reg 1 0x00005000 ]
+  [ cmp lte reg 1 0x00005a00 ]
+  [ immediate reg 1 0x0f03a8c0 ]
+  [ immediate reg 2 0xf003a8c0 ]
+  [ nat snat ip addr_min reg 1 addr_max reg 2 ]
+
 # snat ip to ip saddr map { 10.141.11.4 : 192.168.2.3 . 80 }
 __map%d test-ip4 b size 1
 __map%d test-ip4 0