]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: dns.opcode as first-class integer
authorPhilippe Antoine <pantoine@oisf.net>
Thu, 30 Nov 2023 13:32:08 +0000 (14:32 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 6 Feb 2024 09:15:48 +0000 (10:15 +0100)
Ticket: 5446

That means it can accept ranges

doc/userguide/rules/dns-keywords.rst
rust/src/detect/uint.rs
rust/src/dns/detect.rs
src/detect-dns-opcode.c

index a514ae25195be28750c562d951701492859ab7f5..005164dfd159f68daae20e0c70817da0473117ec 100644 (file)
@@ -28,12 +28,15 @@ dns.opcode
 
 This keyword matches on the **opcode** found in the DNS header flags.
 
+dns.opcode uses an :ref:`unsigned 8-bit integer <rules-integer-keywords>`.
+
 Syntax
 ~~~~~~
 
 ::
 
    dns.opcode:[!]<number>
+   dns.opcode:[!]<number1>-<number2>
 
 Examples
 ~~~~~~~~
@@ -46,6 +49,14 @@ Match on DNS requests where the **opcode** is NOT 0::
 
   dns.opcode:!0;
 
+Match on DNS requests where the **opcode** is between 7 and 15, exclusively:
+
+  dns.opcode:7-15;
+
+Match on DNS requests where the **opcode** is not between 7 and 15:
+
+  dns.opcode:!7-15;
+
 dns.query
 ---------
 
index 7ce86d57f3e2bd58950d5ce95c3773021f59c387..5b28830cea6aba2b4d5b3ebe14eaf81b9125b345 100644 (file)
@@ -42,7 +42,7 @@ pub enum DetectUintMode {
     DetectUintModeNegBitmask,
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
 #[repr(C)]
 pub struct DetectUintData<T> {
     pub arg1: T,
index 5d9d945be0cee20fbc85d9e08aa6fad44818a2e4..452d4e8380e11dc32f41ec143ab209a303241e3b 100644 (file)
  */
 
 use super::dns::DNSTransaction;
-use crate::core::*;
-use std::ffi::CStr;
-use std::os::raw::{c_char, c_void};
-
-#[derive(Debug, PartialEq, Eq)]
-pub struct DetectDnsOpcode {
-    negate: bool,
-    opcode: u8,
-}
-
-/// Parse a DNS opcode argument returning the code and if it is to be
-/// negated or not.
-///
-/// For now only an indication that an error occurred is returned, not
-/// the details of the error.
-fn parse_opcode(opcode: &str) -> Result<DetectDnsOpcode, ()> {
-    let mut negated = false;
-    for (i, c) in opcode.chars().enumerate() {
-        match c {
-            ' ' | '\t' => {
-                continue;
-            }
-            '!' => {
-                negated = true;
-            }
-            _ => {
-                let code: u8 = opcode[i..].parse().map_err(|_| ())?;
-                return Ok(DetectDnsOpcode {
-                    negate: negated,
-                    opcode: code,
-                });
-            }
-        }
-    }
-    Err(())
-}
+use crate::core::Direction;
+use crate::detect::uint::{detect_match_uint, DetectUintData};
 
 /// Perform the DNS opcode match.
 ///
 /// 1 will be returned on match, otherwise 0 will be returned.
 #[no_mangle]
 pub extern "C" fn rs_dns_opcode_match(
-    tx: &mut DNSTransaction, detect: &mut DetectDnsOpcode, flags: u8,
+    tx: &mut DNSTransaction, detect: &mut DetectUintData<u8>, flags: u8,
 ) -> u8 {
     let header_flags = if flags & Direction::ToServer as u8 != 0 {
         if let Some(request) = &tx.request {
@@ -76,116 +42,87 @@ pub extern "C" fn rs_dns_opcode_match(
         // Not to server or to client??
         return 0;
     };
+    let opcode = ((header_flags >> 11) & 0xf) as u8;
 
-    match_opcode(detect, header_flags).into()
-}
-
-fn match_opcode(detect: &DetectDnsOpcode, flags: u16) -> bool {
-    let opcode = ((flags >> 11) & 0xf) as u8;
-    if detect.negate {
-        detect.opcode != opcode
-    } else {
-        detect.opcode == opcode
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rs_detect_dns_opcode_parse(carg: *const c_char) -> *mut c_void {
-    if carg.is_null() {
-        return std::ptr::null_mut();
-    }
-    let arg = match CStr::from_ptr(carg).to_str() {
-        Ok(arg) => arg,
-        _ => {
-            return std::ptr::null_mut();
-        }
-    };
-
-    match parse_opcode(arg) {
-        Ok(detect) => Box::into_raw(Box::new(detect)) as *mut _,
-        Err(_) => std::ptr::null_mut(),
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn rs_dns_detect_opcode_free(ptr: *mut c_void) {
-    if !ptr.is_null() {
-        std::mem::drop(Box::from_raw(ptr as *mut DetectDnsOpcode));
+    if detect_match_uint(detect, opcode) {
+        return 1;
     }
+    return 0;
 }
 
 #[cfg(test)]
 mod test {
     use super::*;
+    use crate::detect::uint::{detect_parse_uint, DetectUintMode};
 
     #[test]
     fn parse_opcode_good() {
         assert_eq!(
-            parse_opcode("1"),
-            Ok(DetectDnsOpcode {
-                negate: false,
-                opcode: 1
-            })
-        );
-        assert_eq!(
-            parse_opcode("123"),
-            Ok(DetectDnsOpcode {
-                negate: false,
-                opcode: 123
-            })
+            detect_parse_uint::<u8>("1").unwrap().1,
+            DetectUintData {
+                mode: DetectUintMode::DetectUintModeEqual,
+                arg1: 1,
+                arg2: 0,
+            }
         );
         assert_eq!(
-            parse_opcode("!123"),
-            Ok(DetectDnsOpcode {
-                negate: true,
-                opcode: 123
-            })
+            detect_parse_uint::<u8>("123").unwrap().1,
+            DetectUintData {
+                mode: DetectUintMode::DetectUintModeEqual,
+                arg1: 123,
+                arg2: 0,
+            }
         );
         assert_eq!(
-            parse_opcode("!123"),
-            Ok(DetectDnsOpcode {
-                negate: true,
-                opcode: 123
-            })
+            detect_parse_uint::<u8>("!123").unwrap().1,
+            DetectUintData {
+                mode: DetectUintMode::DetectUintModeNe,
+                arg1: 123,
+                arg2: 0,
+            }
         );
-        assert_eq!(parse_opcode(""), Err(()));
-        assert_eq!(parse_opcode("!"), Err(()));
-        assert_eq!(parse_opcode("!   "), Err(()));
-        assert_eq!(parse_opcode("!asdf"), Err(()));
+        assert!(detect_parse_uint::<u8>("").is_err());
+        assert!(detect_parse_uint::<u8>("!").is_err());
+        assert!(detect_parse_uint::<u8>("!   ").is_err());
+        assert!(detect_parse_uint::<u8>("!asdf").is_err());
     }
 
     #[test]
     fn test_match_opcode() {
-        assert!(match_opcode(
-            &DetectDnsOpcode {
-                negate: false,
-                opcode: 0,
+        assert!(detect_match_uint(
+            &DetectUintData {
+                mode: DetectUintMode::DetectUintModeEqual,
+                arg1: 0,
+                arg2: 0,
             },
             0b0000_0000_0000_0000,
         ));
 
-        assert!(!match_opcode(
-            &DetectDnsOpcode {
-                negate: true,
-                opcode: 0,
+        assert!(!detect_match_uint(
+            &DetectUintData {
+                mode: DetectUintMode::DetectUintModeNe,
+                arg1: 0,
+                arg2: 0,
             },
             0b0000_0000_0000_0000,
         ));
 
-        assert!(match_opcode(
-            &DetectDnsOpcode {
-                negate: false,
-                opcode: 4,
+        assert!(detect_match_uint(
+            &DetectUintData {
+                mode: DetectUintMode::DetectUintModeEqual,
+                arg1: 4,
+                arg2: 0,
             },
-            0b0010_0000_0000_0000,
+            ((0b0010_0000_0000_0000 >> 11) & 0xf) as u8,
         ));
 
-        assert!(!match_opcode(
-            &DetectDnsOpcode {
-                negate: true,
-                opcode: 4,
+        assert!(!detect_match_uint(
+            &DetectUintData {
+                mode: DetectUintMode::DetectUintModeNe,
+                arg1: 4,
+                arg2: 0,
             },
-            0b0010_0000_0000_0000,
+            ((0b0010_0000_0000_0000 >> 11) & 0xf) as u8,
         ));
     }
 }
index 4baee19b8cd3cee72b088af1c23b67c83c7620d1..f5dcab700f27593d4883ac28bd3bf49f546bb3af 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "detect-parse.h"
 #include "detect-engine.h"
+#include "detect-engine-uint.h"
 #include "detect-dns-opcode.h"
 #include "rust.h"
 
@@ -35,7 +36,7 @@ static int DetectDnsOpcodeSetup(DetectEngineCtx *de_ctx, Signature *s,
         return -1;
     }
 
-    void *detect = rs_detect_dns_opcode_parse(str);
+    void *detect = DetectU8Parse(str);
     if (detect == NULL) {
         SCLogError("failed to parse dns.opcode: %s", str);
         return -1;
@@ -57,7 +58,7 @@ static void DetectDnsOpcodeFree(DetectEngineCtx *de_ctx, void *ptr)
 {
     SCEnter();
     if (ptr != NULL) {
-        rs_dns_detect_opcode_free(ptr);
+        rs_detect_u8_free(ptr);
     }
     SCReturn;
 }