*/
use super::uint::*;
-use nom7::bytes::complete::{is_a, take_while};
-use nom7::character::complete::{alpha0, char, digit1};
-use nom7::combinator::{all_consuming, map_opt, map_res, opt};
-use nom7::error::{make_error, ErrorKind};
+use crate::detect::error::RuleParseError;
+use nom7::bytes::complete::tag;
+use nom7::character::complete::multispace0;
+use nom7::sequence::preceded;
+
use nom7::Err;
use nom7::IResult;
pub fn SRepCatGetByShortname(name: *const c_char) -> u8;
}
-pub fn detect_parse_iprep(i: &str) -> IResult<&str, DetectIPRepData> {
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, cmd) = map_res(alpha0, DetectIPRepDataCmd::from_str)(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
- let (i, _) = char(',')(i)?;
- let (i, _) = opt(is_a(" "))(i)?;
+pub fn detect_parse_iprep(i: &str) -> IResult<&str, DetectIPRepData, RuleParseError<&str>> {
+ // Inner utility function for easy error creation.
+ fn make_error(reason: String) -> nom7::Err<RuleParseError<&'static str>> {
+ Err::Error(RuleParseError::InvalidIPRep(reason))
+ }
+ 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)?;
- // copy as to have final zero
- let namez = CString::new(name).unwrap();
- let cat = unsafe { SRepCatGetByShortname(namez.as_ptr()) };
- if cat == 0 {
- return Err(Err::Error(make_error(i, ErrorKind::MapOpt)));
+ let namez = CString::new(name).unwrap();
+ let cat = unsafe { SRepCatGetByShortname(namez.as_ptr()) };
+ if cat == 0 {
+ return Err(make_error("unknown category".to_string()));
+ }
+ 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]