diff --git a/Cargo.toml b/Cargo.toml index a5687bc7..64967f64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "netflow_parser" description = "Parser for Netflow Cisco V5, V7, V9, IPFIX" -version = "0.6.3" +version = "0.6.4" edition = "2024" authors = ["michael.mileusnich@gmail.com"] license = "MIT OR Apache-2.0" diff --git a/RELEASES.md b/RELEASES.md index 6e407a69..51ee747b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,7 @@ +# 0.6.4 +* Removed uneeded DataNumber Parsing for Durations. +* Explicity rename methods DurationMicros and DurationNanos into DurationMicrosNTP and DurationNanosNTP + # 0.6.3 * Ipfix dateTimeNanoseconds and dateTimeMicroseconds use the NTP 64 bit time format #15 * Added NetEvent and ObservationTimeMilliseconds for V9. diff --git a/src/variable_versions/data_number.rs b/src/variable_versions/data_number.rs index ed4bca97..ed6ddec7 100644 --- a/src/variable_versions/data_number.rs +++ b/src/variable_versions/data_number.rs @@ -1,17 +1,17 @@ use crate::protocol::ProtocolTypes; - use byteorder::{BigEndian, WriteBytesExt}; -use nom::Err as NomErr; -use nom::IResult; -use nom::bytes::complete::take; -use nom::error::{Error as NomError, ErrorKind}; -use nom::number::complete::{be_i24, be_u24, be_u32, be_u128}; -use nom_derive::*; +use nom::{ + Err as NomErr, IResult, + bytes::complete::take, + error::{Error as NomError, ErrorKind}, + number::complete::{be_i24, be_u24, be_u32, be_u128}, +}; +use nom_derive::Parse; use serde::Serialize; - -use std::convert::Into; -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -use std::time::Duration; +use std::{ + net::{IpAddr, Ipv4Addr, Ipv6Addr}, + time::Duration, +}; macro_rules! impl_try_from { ($($t:ty => $v:ident),*; $($s:ty => $sv:ident),*) => { @@ -173,26 +173,6 @@ impl DataNumber { } } -/// Convert into usize, mainly for serialization purposes -impl From for usize { - fn from(val: DataNumber) -> Self { - match val { - DataNumber::U8(i) => usize::from(i), - DataNumber::I8(i) => i as usize, - DataNumber::U16(i) => i as usize, - DataNumber::I16(i) => i as usize, - DataNumber::I24(i) => i as usize, - DataNumber::U24(i) => i as usize, - DataNumber::U32(i) => i as usize, - DataNumber::I32(i) => i as usize, - DataNumber::U64(i) => i as usize, - DataNumber::I64(i) => i as usize, - DataNumber::U128(i) => i as usize, - DataNumber::I128(i) => i as usize, - } - } -} - #[derive(Debug, PartialEq, PartialOrd, Clone, Serialize)] pub struct ApplicationId { pub classification_engine_id: u8, @@ -240,6 +220,12 @@ impl FieldValue { } } + fn make_ntp_time_with_unit(seconds: u32, fraction: u32, unit: u64) -> Duration { + Duration::from_secs(u64::from(seconds)).saturating_add(Duration::from_micros( + ((u64::from(fraction)).saturating_mul(unit)) >> 32, + )) + } + pub fn from_field_type( remaining: &[u8], field_type: FieldDataType, @@ -297,40 +283,51 @@ impl FieldValue { (i, FieldValue::MacAddr(mac_addr)) } FieldDataType::DurationSeconds => { - let (i, data_number) = DataNumber::parse(remaining, field_length, false)?; - ( - i, - FieldValue::Duration(Duration::from_secs( - >::into(data_number) as u64, - )), - ) + let (i, value) = match field_length { + 4 => { + let (i, seconds) = u32::parse_be(remaining)?; + let dur = Duration::from_secs(seconds.into()); + (i, FieldValue::Duration(dur)) + } + 8 => { + let (i, seconds) = u64::parse_be(remaining)?; + let dur = Duration::from_secs(seconds); + (i, FieldValue::Duration(dur)) + } + _ => { + return Err(NomErr::Error(NomError::new(remaining, ErrorKind::Fail))); + } + }; + (i, value) } FieldDataType::DurationMillis => { - let (i, data_number) = DataNumber::parse(remaining, field_length, false)?; - ( - i, - FieldValue::Duration(Duration::from_millis( - >::into(data_number) as u64, - )), - ) + let (i, value) = match field_length { + 4 => { + let (i, seconds) = u32::parse_be(remaining)?; + let dur = Duration::from_millis(u64::from(seconds)); + (i, FieldValue::Duration(dur)) + } + 8 => { + let (i, seconds) = u64::parse_be(remaining)?; + let dur = Duration::from_millis(seconds); + (i, FieldValue::Duration(dur)) + } + _ => { + return Err(NomErr::Error(NomError::new(remaining, ErrorKind::Fail))); + } + }; + (i, value) } - FieldDataType::DurationMicros => { + FieldDataType::DurationMicrosNTP => { let (i, seconds) = u32::parse_be(remaining)?; let (i, fraction) = u32::parse_be(i)?; - let dur = - Duration::from_secs(seconds as u64).saturating_add(Duration::from_micros( - ((u64::from(fraction)).saturating_mul(1_000_000)) >> 32, - )); + let dur = Self::make_ntp_time_with_unit(seconds, fraction, 1_000_000); (i, FieldValue::Duration(dur)) } - FieldDataType::DurationNanos => { + FieldDataType::DurationNanosNTP => { let (i, seconds) = u32::parse_be(remaining)?; let (i, fraction) = u32::parse_be(i)?; - let dur = Duration::from_secs(u64::from(seconds)).saturating_add( - Duration::from_nanos( - (u64::from(fraction).saturating_mul(1_000_000_000)) >> 32, - ), - ); + let dur = Self::make_ntp_time_with_unit(seconds, fraction, 1_000_000_000); (i, FieldValue::Duration(dur)) } FieldDataType::ProtocolType => { @@ -361,8 +358,8 @@ pub enum FieldDataType { Float64, DurationSeconds, DurationMillis, - DurationMicros, - DurationNanos, + DurationMicrosNTP, + DurationNanosNTP, Ip4Addr, Ip6Addr, MacAddr, diff --git a/src/variable_versions/ipfix_lookup.rs b/src/variable_versions/ipfix_lookup.rs index adf7bad1..77e4dc67 100644 --- a/src/variable_versions/ipfix_lookup.rs +++ b/src/variable_versions/ipfix_lookup.rs @@ -1101,10 +1101,10 @@ FlowStartSeconds = 150 => FieldDataType::DurationSeconds, FlowEndSeconds = 151 => FieldDataType::DurationSeconds, FlowStartMilliseconds = 152 => FieldDataType::DurationMillis, FlowEndMilliseconds = 153 => FieldDataType::DurationMillis, -FlowStartMicroseconds = 154 => FieldDataType::DurationMicros, -FlowEndMicroseconds = 155 => FieldDataType::DurationMicros, -FlowStartNanoseconds = 156 => FieldDataType::DurationNanos, -FlowEndNanoseconds = 157 => FieldDataType::DurationNanos, +FlowStartMicroseconds = 154 => FieldDataType::DurationMicrosNTP, +FlowEndMicroseconds = 155 => FieldDataType::DurationMicrosNTP, +FlowStartNanoseconds = 156 => FieldDataType::DurationNanosNTP, +FlowEndNanoseconds = 157 => FieldDataType::DurationNanosNTP, FlowStartDeltaMicroseconds = 158 => FieldDataType::UnsignedDataNumber, FlowEndDeltaMicroseconds = 159 => FieldDataType::UnsignedDataNumber, SystemInitTimeMilliseconds = 160 => FieldDataType::DurationMillis, @@ -1215,12 +1215,12 @@ MinExportSeconds = 264 => FieldDataType::DurationSeconds, MinFlowStartSeconds = 265 => FieldDataType::DurationSeconds, OpaqueOctets = 266 => FieldDataType::String, SessionScope = 267 => FieldDataType::UnsignedDataNumber, -MaxFlowEndMicroseconds = 268 => FieldDataType::DurationMicros, +MaxFlowEndMicroseconds = 268 => FieldDataType::DurationMicrosNTP, MaxFlowEndMilliseconds = 269 => FieldDataType::DurationMillis, -MaxFlowEndNanoseconds = 270 => FieldDataType::DurationNanos, -MinFlowStartMicroseconds = 271 => FieldDataType::DurationMicros, +MaxFlowEndNanoseconds = 270 => FieldDataType::DurationNanosNTP, +MinFlowStartMicroseconds = 271 => FieldDataType::DurationMicrosNTP, MinFlowStartMilliseconds = 272 => FieldDataType::DurationMillis, -MinFlowStartNanoseconds = 273 => FieldDataType::DurationNanos, +MinFlowStartNanoseconds = 273 => FieldDataType::DurationNanosNTP, CollectorCertificate = 274 => FieldDataType::String, ExporterCertificate = 275 => FieldDataType::String, DataRecordsReliability = 276 => FieldDataType::UnsignedDataNumber, @@ -1271,8 +1271,8 @@ AbsoluteError = 320 => FieldDataType::Float64, RelativeError = 321 => FieldDataType::Float64, ObservationTimeSeconds = 322 => FieldDataType::DurationSeconds, ObservationTimeMilliseconds = 323 => FieldDataType::DurationMillis, -ObservationTimeMicroseconds = 324 => FieldDataType::DurationMicros, -ObservationTimeNanoseconds = 325 => FieldDataType::DurationNanos, +ObservationTimeMicroseconds = 324 => FieldDataType::DurationMicrosNTP, +ObservationTimeNanoseconds = 325 => FieldDataType::DurationNanosNTP, DigestHashValue = 326 => FieldDataType::UnsignedDataNumber, HashIppayloadOffset = 327 => FieldDataType::UnsignedDataNumber, HashIppayloadSize = 328 => FieldDataType::UnsignedDataNumber, diff --git a/src/variable_versions/snapshots/netflow_parser__variable_versions__ipfix_lookup__ipfix_lookup_tests__it_tests_field_data_type_lookup.snap b/src/variable_versions/snapshots/netflow_parser__variable_versions__ipfix_lookup__ipfix_lookup_tests__it_tests_field_data_type_lookup.snap index 39797bd0..9ccc082b 100644 --- a/src/variable_versions/snapshots/netflow_parser__variable_versions__ipfix_lookup__ipfix_lookup_tests__it_tests_field_data_type_lookup.snap +++ b/src/variable_versions/snapshots/netflow_parser__variable_versions__ipfix_lookup__ipfix_lookup_tests__it_tests_field_data_type_lookup.snap @@ -156,10 +156,10 @@ expression: lookup - DurationSeconds - DurationMillis - DurationMillis -- DurationMicros -- DurationMicros -- DurationNanos -- DurationNanos +- DurationMicrosNTP +- DurationMicrosNTP +- DurationNanosNTP +- DurationNanosNTP - UnsignedDataNumber - UnsignedDataNumber - DurationMillis @@ -270,12 +270,12 @@ expression: lookup - DurationSeconds - String - UnsignedDataNumber -- DurationMicros +- DurationMicrosNTP - DurationMillis -- DurationNanos -- DurationMicros +- DurationNanosNTP +- DurationMicrosNTP - DurationMillis -- DurationNanos +- DurationNanosNTP - String - String - UnsignedDataNumber @@ -326,8 +326,8 @@ expression: lookup - Float64 - DurationSeconds - DurationMillis -- DurationMicros -- DurationNanos +- DurationMicrosNTP +- DurationNanosNTP - UnsignedDataNumber - UnsignedDataNumber - UnsignedDataNumber diff --git a/src/variable_versions/v9.rs b/src/variable_versions/v9.rs index d0c12955..adf259c2 100644 --- a/src/variable_versions/v9.rs +++ b/src/variable_versions/v9.rs @@ -250,10 +250,10 @@ pub struct OptionsTemplate { /// This field gives the length (in bytes) of any Options field definitions that are contained in this options template pub options_length: u16, /// Options Scope Fields - #[nom(Count = "(options_scope_length / 4) as usize")] + #[nom(Count = "usize::from((options_scope_length.saturating_div(4)))")] pub scope_fields: Vec, /// Options Fields - #[nom(Count = "(options_length / 4) as usize")] + #[nom(Count = "usize::from((options_length.saturating_div(4)))")] pub option_fields: Vec, }