From aa0cb4a681bea668a6af8f1d54e8646070dc601d Mon Sep 17 00:00:00 2001 From: Michael Mileusnich Date: Thu, 18 Dec 2025 11:11:38 -0600 Subject: [PATCH 1/3] fix: Reworked padding for exporting --- README.md | 7 +++- RELEASES.md | 6 ++++ src/lib.rs | 7 +++- src/variable_versions/ipfix.rs | 35 +++++++++++++++++-- src/variable_versions/v9.rs | 63 ++++++++++++++++++++++++++-------- 5 files changed, 100 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 32ac2ee9..80d3dcad 100644 --- a/README.md +++ b/README.md @@ -374,7 +374,12 @@ Each field mapping has a `primary` field (always checked first) and an optional Parsed V5, V7, V9, and IPFIX packets can be re-exported back into bytes. -**Note:** For V9/IPFIX, we only export the original padding we dissected and do not calculate/align the flowset padding ourselves. If you modify an existing V9/IPFIX flow or create your own, you must manually adjust the padding. +**V9/IPFIX Padding Behavior:** +- For **parsed packets**: Original padding is preserved exactly for byte-perfect round-trips +- For **manually created packets**: Padding is automatically calculated to align FlowSets to 4-byte boundaries - simply leave the `padding` field empty (`vec![]`) + +See `examples/manual_ipfix_creation.rs` for a complete example of creating IPFIX packets from scratch. + ```rust // 0000 00 05 00 01 03 00 04 00 05 00 06 07 08 09 00 01 ................ // 0010 02 03 04 05 06 07 08 09 00 01 02 03 04 05 06 07 ................ diff --git a/RELEASES.md b/RELEASES.md index f2e2b1a4..f54bfa3d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -8,6 +8,12 @@ * Enhanced validation for malformed packets * Improved IPFIX error handling - parse errors now properly propagate * Added thread safety documentation and performance tuning guide +* **Fixed V9/IPFIX padding handling:** + * Fixed missing padding export for V9 Data FlowSets + * Added padding fields to IPFIX Data and OptionsData structures + * Auto-calculate padding for manually created packets (when padding field is empty) + * Preserve original padding for parsed packets (byte-perfect round-trips) + * Added `examples/manual_ipfix_creation.rs` demonstrating manual packet creation # 0.6.6 * Added configurable field mappings for V9 and IPFIX in NetflowCommon. diff --git a/src/lib.rs b/src/lib.rs index 15a192e0..3e4f207a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -345,7 +345,12 @@ //! //! Parsed V5, V7, V9, and IPFIX packets can be re-exported back into bytes. //! -//! **Note:** For V9/IPFIX, we only export the original padding we dissected and do not calculate/align the flowset padding ourselves. If you modify an existing V9/IPFIX flow or create your own, you must manually adjust the padding. +//! **V9/IPFIX Padding Behavior:** +//! - For **parsed packets**: Original padding is preserved exactly for byte-perfect round-trips +//! - For **manually created packets**: Padding is automatically calculated to align FlowSets to 4-byte boundaries - simply leave the `padding` field empty (`vec![]`) +//! +//! See `examples/manual_ipfix_creation.rs` for a complete example of creating IPFIX packets from scratch. +//! //! ```rust //! use netflow_parser::{NetflowParser, NetflowPacket}; //! diff --git a/src/variable_versions/ipfix.rs b/src/variable_versions/ipfix.rs index af912594..900f8017 100644 --- a/src/variable_versions/ipfix.rs +++ b/src/variable_versions/ipfix.rs @@ -34,6 +34,13 @@ type TemplateId = u16; pub type IPFixFieldPair = (IPFixField, FieldValue); pub type IpFixFlowRecord = Vec; +/// Calculate padding needed to align to 4-byte boundary. +/// Returns a Vec of zero bytes with the appropriate length. +fn calculate_padding(content_size: usize) -> Vec { + let padding_len = (4 - (content_size % 4)) % 4; + vec![0u8; padding_len] +} + #[derive(Debug, PartialEq, Clone, Serialize)] pub struct IPFixParser { pub templates: HashMap, @@ -358,6 +365,8 @@ pub struct Data { Parse = "{ |i| FieldParser::parse::