* 02110-1301, USA.
*/
-use super::dns::{DNSTransaction, ALPROTO_DNS};
+use super::dns::{DNSRcode, DNSTransaction, ALPROTO_DNS};
use crate::detect::uint::{
- detect_match_uint, DetectUintData, SCDetectU16Free, SCDetectU16Parse, SCDetectU8Free,
- SCDetectU8Parse,
+ detect_match_uint, detect_parse_uint_enum, SCDetectU16Free, SCDetectU16Parse,
+ SCDetectU8Free, SCDetectU8Parse, DetectUintData,
};
use crate::detect::{
DetectBufferSetActiveList, DetectHelperBufferRegister, DetectHelperGetMultiData,
SigMatchAppendSMToList, SIGMATCH_INFO_STICKY_BUFFER, SIGMATCH_NOOPT,
};
use crate::direction::Direction;
+use std::ffi::CStr;
use std::os::raw::{c_int, c_void};
/// Perform the DNS opcode match.
_sig: *const c_void, ctx: *const c_void,
) -> c_int {
let tx = cast_pointer!(tx, DNSTransaction);
- let ctx = cast_pointer!(ctx, DetectUintData<u8>);
+ let ctx = cast_pointer!(ctx, DetectUintData<u16>);
let header_flags = if flags & Direction::ToServer as u8 != 0 {
if let Some(request) = &tx.request {
request.header.flags
return 0;
};
- let rcode = (header_flags & 0xf) as u8;
+ let rcode = header_flags & 0xf;
if detect_match_uint(ctx, rcode) {
return 1;
SCDetectU8Free(ctx);
}
+unsafe extern "C" fn dns_rcode_parse(ustr: *const std::os::raw::c_char) -> *mut DetectUintData<u8> {
+ let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
+ if let Ok(s) = ft_name.to_str() {
+ if let Some(ctx) = detect_parse_uint_enum::<u16, DNSRcode>(s) {
+ let boxed = Box::new(ctx);
+ return Box::into_raw(boxed) as *mut _;
+ }
+ }
+ return std::ptr::null_mut();
+}
+
unsafe extern "C" fn dns_rcode_setup(
de: *mut c_void, s: *mut c_void, raw: *const libc::c_char,
) -> c_int {
if DetectSignatureSetAppProto(s, ALPROTO_DNS) != 0 {
return -1;
}
- let ctx = SCDetectU8Parse(raw) as *mut c_void;
+ let ctx = dns_rcode_parse(raw) as *mut c_void;
if ctx.is_null() {
return -1;
}
unsafe extern "C" fn dns_rcode_free(_de: *mut c_void, ctx: *mut c_void) {
// Just unbox...
- let ctx = cast_pointer!(ctx, DetectUintData<u8>);
- SCDetectU8Free(ctx);
+ let ctx = cast_pointer!(ctx, DetectUintData<u16>);
+ SCDetectU16Free(ctx);
}
unsafe extern "C" fn dns_rrtype_setup(
#[test]
fn parse_rcode_good() {
assert_eq!(
- detect_parse_uint::<u8>("1").unwrap().1,
+ detect_parse_uint_enum::<u16, DNSRcode>("1").unwrap(),
DetectUintData {
mode: DetectUintMode::DetectUintModeEqual,
arg1: 1,
}
);
assert_eq!(
- detect_parse_uint::<u8>("123").unwrap().1,
+ detect_parse_uint_enum::<u16, DNSRcode>("123").unwrap(),
DetectUintData {
mode: DetectUintMode::DetectUintModeEqual,
arg1: 123,
}
);
assert_eq!(
- detect_parse_uint::<u8>("!123").unwrap().1,
+ detect_parse_uint_enum::<u16, DNSRcode>("!123").unwrap(),
DetectUintData {
mode: DetectUintMode::DetectUintModeNe,
arg1: 123,
}
);
assert_eq!(
- detect_parse_uint::<u8>("7-15").unwrap().1,
+ detect_parse_uint_enum::<u16, DNSRcode>("7-15").unwrap(),
DetectUintData {
mode: DetectUintMode::DetectUintModeRange,
arg1: 7,
arg2: 15,
}
);
- assert!(detect_parse_uint::<u16>("").is_err());
- assert!(detect_parse_uint::<u16>("!").is_err());
- assert!(detect_parse_uint::<u16>("! ").is_err());
- assert!(detect_parse_uint::<u16>("!asdf").is_err());
+ assert_eq!(
+ detect_parse_uint_enum::<u16, DNSRcode>("nxdomain").unwrap(),
+ DetectUintData {
+ mode: DetectUintMode::DetectUintModeEqual,
+ arg1: DNSRcode::NXDOMAIN as u16,
+ arg2: 0,
+ }
+ );
+ assert!(detect_parse_uint_enum::<u16, DNSRcode>("").is_none());
+ assert!(detect_parse_uint_enum::<u16, DNSRcode>("!").is_none());
+ assert!(detect_parse_uint_enum::<u16, DNSRcode>("! ").is_none());
+ assert!(detect_parse_uint_enum::<u16, DNSRcode>("!asdf").is_none());
}
#[test]
pub const DNS_RECORD_TYPE_URI: u16 = 256;
/// DNS error codes.
-pub const DNS_RCODE_NOERROR: u16 = 0;
-pub const DNS_RCODE_FORMERR: u16 = 1;
-pub const DNS_RCODE_SERVFAIL: u16 = 2;
-pub const DNS_RCODE_NXDOMAIN: u16 = 3;
-pub const DNS_RCODE_NOTIMP: u16 = 4;
-pub const DNS_RCODE_REFUSED: u16 = 5;
-pub const DNS_RCODE_YXDOMAIN: u16 = 6;
-pub const DNS_RCODE_YXRRSET: u16 = 7;
-pub const DNS_RCODE_NXRRSET: u16 = 8;
-pub const DNS_RCODE_NOTAUTH: u16 = 9;
-pub const DNS_RCODE_NOTZONE: u16 = 10;
-// Support for OPT RR from RFC6891 will be needed to
-// parse RCODE values over 15
-pub const DNS_RCODE_BADVERS: u16 = 16;
-//also pub const DNS_RCODE_BADSIG: u16 = 16;
-pub const DNS_RCODE_BADKEY: u16 = 17;
-pub const DNS_RCODE_BADTIME: u16 = 18;
-pub const DNS_RCODE_BADMODE: u16 = 19;
-pub const DNS_RCODE_BADNAME: u16 = 20;
-pub const DNS_RCODE_BADALG: u16 = 21;
-pub const DNS_RCODE_BADTRUNC: u16 = 22;
+#[derive(Clone, Debug, EnumStringU16)]
+pub enum DNSRcode {
+ NOERROR = 0,
+ FORMERR = 1,
+ SERVFAIL = 2,
+ NXDOMAIN = 3,
+ NOTIMP = 4,
+ REFUSED = 5,
+ YXDOMAIN = 6,
+ YXRRSET = 7,
+ NXRRSET = 8,
+ NOTAUTH = 9,
+ NOTZONE = 10,
+ // Support for OPT RR from RFC6891 will be needed to
+ // parse RCODE values over 15
+ BADVERS = 16,
+ //also pub const DNS_RCODE_BADSIG: u16 = 16;
+ BADKEY = 17,
+ BADTIME = 18,
+ BADMODE = 19,
+ BADNAME = 20,
+ BADALG = 21,
+ BADTRUNC = 22,
+}
pub(super) static mut ALPROTO_DNS: AppProto = ALPROTO_UNKNOWN;
use std::collections::HashMap;
use std::string::String;
+use crate::detect::EnumString;
use crate::dns::dns::*;
use crate::jsonbuilder::{JsonBuilder, JsonError};
}
pub fn dns_rcode_string(flags: u16) -> String {
- match flags & 0x000f {
- DNS_RCODE_NOERROR => "NOERROR",
- DNS_RCODE_FORMERR => "FORMERR",
- DNS_RCODE_SERVFAIL => "SERVFAIL",
- DNS_RCODE_NXDOMAIN => "NXDOMAIN",
- DNS_RCODE_NOTIMP => "NOTIMP",
- DNS_RCODE_REFUSED => "REFUSED",
- DNS_RCODE_YXDOMAIN => "YXDOMAIN",
- DNS_RCODE_YXRRSET => "YXRRSET",
- DNS_RCODE_NXRRSET => "NXRRSET",
- DNS_RCODE_NOTAUTH => "NOTAUTH",
- DNS_RCODE_NOTZONE => "NOTZONE",
- DNS_RCODE_BADVERS => "BADVERS/BADSIG",
- DNS_RCODE_BADKEY => "BADKEY",
- DNS_RCODE_BADTIME => "BADTIME",
- DNS_RCODE_BADMODE => "BADMODE",
- DNS_RCODE_BADNAME => "BADNAME",
- DNS_RCODE_BADALG => "BADALG",
- DNS_RCODE_BADTRUNC => "BADTRUNC",
- _ => {
- return (flags & 0x000f).to_string();
- }
+ if flags & 0x000f == DNSRcode::BADVERS as u16 {
+ return "BADVERS/BADSIG".to_string();
}
- .to_string()
+ if let Some(rc) = DNSRcode::from_u(flags & 0x000f) {
+ return rc.to_str().to_uppercase();
+ }
+ return (flags & 0x000f).to_string();
}
/// Format bytes as an IP address string.