]> git.ipfire.org Git - thirdparty/suricata-verify.git/commitdiff
tests: add rule check for xbits keyword 2797/head
authorJames Kaddu <kaddujames501@gmail.com>
Wed, 5 Nov 2025 12:40:16 +0000 (15:40 +0300)
committerVictor Julien <vjulien@oisf.net>
Fri, 5 Dec 2025 08:41:00 +0000 (08:41 +0000)
Related to
Task #6351

tests/rules/xbits/README.md [new file with mode: 0644]
tests/rules/xbits/test.rules [new file with mode: 0644]
tests/rules/xbits/test.yaml [new file with mode: 0644]

diff --git a/tests/rules/xbits/README.md b/tests/rules/xbits/README.md
new file mode 100644 (file)
index 0000000..7639d14
--- /dev/null
@@ -0,0 +1,34 @@
+# Xbits Keyword Engine Analysis Test
+
+This test verifies the engine analysis output for the `xbits` keyword.
+
+## Purpose
+
+Tests that the `xbits` keyword is properly reported in the `rules.json`
+output when using `--engine-analysis` mode.
+
+## Coverage
+
+This test covers:
+- `xbits:set` with different tracking modes (ip_src, ip_dst, ip_pair)
+- `xbits:isset` 
+- `xbits:isnotset`
+- `xbits:unset`
+- `xbits:toggle`
+- `xbits` with expire values (default, 60s, 300s)
+- Multiple xbits in a single rule
+
+The test verifies all four properties exposed by the engine analysis:
+- **cmd**: The xbits command (set, isset, isnotset, unset, toggle)
+- **name**: The xbit name being tracked
+- **track**: The tracking mode (ip_src, ip_dst, ip_pair)
+- **expire**: The expiration time in seconds (when specified)
+
+## Reference
+
+Similar to the flowbits engine analysis test, but for the xbits keyword
+which tracks state across hosts/networks rather than within a single flow.
+
+## Ticket
+
+https://redmine.openinfosecfoundation.org/issues/6351
diff --git a/tests/rules/xbits/test.rules b/tests/rules/xbits/test.rules
new file mode 100644 (file)
index 0000000..6f24b05
--- /dev/null
@@ -0,0 +1,11 @@
+alert ip any any -> any any (msg:"Xbit set"; xbits:set,xb1,track ip_src; sid:1;)
+alert ip any any -> any any (msg:"Xbit set"; xbits:set,xb2,track ip_dst; sid:2;)
+alert ip any any -> any any (msg:"Xbit isset"; xbits:isset,xb1,track ip_src; sid:3;)
+alert ip any any -> any any (msg:"Xbit isset"; xbits:isset,xb2,track ip_dst; sid:4;)
+alert ip any any -> any any (msg:"Xbit isnotset"; xbits:isnotset,xb3,track ip_src; sid:5;)
+alert ip any any -> any any (msg:"Xbit unset"; xbits:unset,xb1,track ip_src; sid:6;)
+alert ip any any -> any any (msg:"Xbit toggle"; xbits:toggle,xb2,track ip_dst; sid:7;)
+alert ip any any -> any any (msg:"Xbit isset ip_pair"; xbits:isset,xb4,track ip_pair; sid:8;)
+alert ip any any -> any any (msg:"Xbit set both"; xbits:set,xb5,track ip_src; xbits:set,xb6,track ip_dst; sid:9;)
+alert ip any any -> any any (msg:"Xbit set with expire"; xbits:set,xb7,track ip_src,expire 60; sid:10;)
+alert ip any any -> any any (msg:"Xbit set with expire 300"; xbits:set,xb8,track ip_dst,expire 300; sid:11;)
diff --git a/tests/rules/xbits/test.yaml b/tests/rules/xbits/test.yaml
new file mode 100644 (file)
index 0000000..702d8ba
--- /dev/null
@@ -0,0 +1,114 @@
+requires:
+  min-version: 9.0
+  pcap: false
+
+args:
+  - --engine-analysis
+
+checks:
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 1
+      lists.postmatch.matches[0].name: "xbits"
+      lists.postmatch.matches[0].xbits.cmd: "set"
+      lists.postmatch.matches[0].xbits.name: "xb1"
+      lists.postmatch.matches[0].xbits.track: "ip_src"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 2
+      lists.postmatch.matches[0].name: "xbits"
+      lists.postmatch.matches[0].xbits.cmd: "set"
+      lists.postmatch.matches[0].xbits.name: "xb2"
+      lists.postmatch.matches[0].xbits.track: "ip_dst"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 3
+      lists.packet.matches[0].name: "xbits"
+      lists.packet.matches[0].xbits.cmd: "isset"
+      lists.packet.matches[0].xbits.name: "xb1"
+      lists.packet.matches[0].xbits.track: "ip_src"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 4
+      lists.packet.matches[0].name: "xbits"
+      lists.packet.matches[0].xbits.cmd: "isset"
+      lists.packet.matches[0].xbits.name: "xb2"
+      lists.packet.matches[0].xbits.track: "ip_dst"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 5
+      lists.packet.matches[0].name: "xbits"
+      lists.packet.matches[0].xbits.cmd: "isnotset"
+      lists.packet.matches[0].xbits.name: "xb3"
+      lists.packet.matches[0].xbits.track: "ip_src"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 6
+      lists.postmatch.matches[0].name: "xbits"
+      lists.postmatch.matches[0].xbits.cmd: "unset"
+      lists.postmatch.matches[0].xbits.name: "xb1"
+      lists.postmatch.matches[0].xbits.track: "ip_src"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 7
+      lists.postmatch.matches[0].name: "xbits"
+      lists.postmatch.matches[0].xbits.cmd: "toggle"
+      lists.postmatch.matches[0].xbits.name: "xb2"
+      lists.postmatch.matches[0].xbits.track: "ip_dst"
+      lists.postmatch.matches[0].xbits.expire: 30
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 8
+      lists.packet.matches[0].name: "xbits"
+      lists.packet.matches[0].xbits.cmd: "isset"
+      lists.packet.matches[0].xbits.name: "xb4"
+      lists.packet.matches[0].xbits.track: "ip_pair"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 9
+      lists.postmatch.matches[0].name: "xbits"
+      lists.postmatch.matches[0].xbits.cmd: "set"
+      lists.postmatch.matches[0].xbits.name: "xb5"
+      lists.postmatch.matches[0].xbits.track: "ip_src"
+      lists.postmatch.matches[1].name: "xbits"
+      lists.postmatch.matches[1].xbits.cmd: "set"
+      lists.postmatch.matches[1].xbits.name: "xb6"
+      lists.postmatch.matches[1].xbits.track: "ip_dst"
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 10
+      lists.postmatch.matches[0].name: "xbits"
+      lists.postmatch.matches[0].xbits.cmd: "set"
+      lists.postmatch.matches[0].xbits.name: "xb7"
+      lists.postmatch.matches[0].xbits.track: "ip_src"
+      lists.postmatch.matches[0].xbits.expire: 60
+- filter:
+    filename: rules.json
+    count: 1
+    match:
+      id: 11
+      lists.postmatch.matches[0].name: "xbits"
+      lists.postmatch.matches[0].xbits.cmd: "set"
+      lists.postmatch.matches[0].xbits.name: "xb8"
+      lists.postmatch.matches[0].xbits.track: "ip_dst"
+      lists.postmatch.matches[0].xbits.expire: 300