detect/iprep: update keyword parser for extendibility

pull/11309/head
Victor Julien 2 years ago committed by Victor Julien
parent f0dbfe863d
commit 539ab3a404

@ -23,6 +23,7 @@ use nom7::error::{ErrorKind, ParseError};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum RuleParseError<I> { pub enum RuleParseError<I> {
InvalidByteMath(String), InvalidByteMath(String),
InvalidIPRep(String),
Nom(I, ErrorKind), Nom(I, ErrorKind),
} }

@ -16,10 +16,11 @@
*/ */
use super::uint::*; use super::uint::*;
use nom7::bytes::complete::{is_a, take_while}; use crate::detect::error::RuleParseError;
use nom7::character::complete::{alpha0, char, digit1}; use nom7::bytes::complete::tag;
use nom7::combinator::{all_consuming, map_opt, map_res, opt}; use nom7::character::complete::multispace0;
use nom7::error::{make_error, ErrorKind}; use nom7::sequence::preceded;
use nom7::Err; use nom7::Err;
use nom7::IResult; use nom7::IResult;
@ -75,36 +76,46 @@ extern "C" {
pub fn SRepCatGetByShortname(name: *const c_char) -> u8; pub fn SRepCatGetByShortname(name: *const c_char) -> u8;
} }
pub fn detect_parse_iprep(i: &str) -> IResult<&str, DetectIPRepData> { pub fn detect_parse_iprep(i: &str) -> IResult<&str, DetectIPRepData, RuleParseError<&str>> {
let (i, _) = opt(is_a(" "))(i)?; // Inner utility function for easy error creation.
let (i, cmd) = map_res(alpha0, DetectIPRepDataCmd::from_str)(i)?; fn make_error(reason: String) -> nom7::Err<RuleParseError<&'static str>> {
let (i, _) = opt(is_a(" "))(i)?; Err::Error(RuleParseError::InvalidIPRep(reason))
let (i, _) = char(',')(i)?; }
let (i, _) = opt(is_a(" "))(i)?; let (_, values) = nom7::multi::separated_list1(
tag(","),
preceded(multispace0, nom7::bytes::complete::is_not(",")),
)(i)?;
if values.len() == 4 {
let cmd = match DetectIPRepDataCmd::from_str(values[0].trim()) {
Ok(val) => val,
Err(_) => return Err(make_error("invalid command".to_string())),
};
let name = values[1].trim();
let mode = match detect_parse_uint_mode(values[2].trim()) {
Ok(val) => val.1,
Err(_) => return Err(make_error("invalid mode".to_string())),
};
let (i, name) = take_while(is_alphanumeric_or_slash)(i)?; let namez = CString::new(name).unwrap();
// copy as to have final zero let cat = unsafe { SRepCatGetByShortname(namez.as_ptr()) };
let namez = CString::new(name).unwrap(); if cat == 0 {
let cat = unsafe { SRepCatGetByShortname(namez.as_ptr()) }; return Err(make_error("unknown category".to_string()));
if cat == 0 { }
return Err(Err::Error(make_error(i, ErrorKind::MapOpt))); let arg1 = match values[3].trim().parse::<u8>() {
Ok(val) => val,
Err(_) => return Err(make_error("invalid value".to_string())),
};
let du8 = DetectUintData::<u8> {
arg1,
arg2: 0,
mode,
};
return Ok((i, DetectIPRepData { du8, cat, cmd }));
} else {
return Err(make_error("too many arguments".to_string()));
} }
let (i, _) = opt(is_a(" "))(i)?;
let (i, _) = char(',')(i)?;
let (i, _) = opt(is_a(" "))(i)?;
let (i, mode) = detect_parse_uint_mode(i)?;
let (i, _) = opt(is_a(" "))(i)?;
let (i, _) = char(',')(i)?;
let (i, _) = opt(is_a(" "))(i)?;
let (i, arg1) = map_opt(digit1, |s: &str| s.parse::<u8>().ok())(i)?;
let (i, _) = all_consuming(take_while(|c| c == ' '))(i)?;
let du8 = DetectUintData::<u8> {
arg1,
arg2: 0,
mode,
};
return Ok((i, DetectIPRepData { du8, cat, cmd }));
} }
#[no_mangle] #[no_mangle]

Loading…
Cancel
Save