1#[cfg(feature = "codec")]
45pub mod codec;
46pub mod ie;
47pub mod ipfix;
48pub mod netflow;
49#[cfg(feature = "serde")]
50pub mod wire;
51
52use crate::ie::*;
53use serde::{Deserialize, Serialize};
54use std::ops::Deref;
55
56#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, strum_macros::Display)]
58pub enum FlowInfoError {
59 #[strum(serialize = "NetFlow v9 is not supported for this operation")]
61 NetFlowV9NotSupported,
62}
63
64impl std::error::Error for FlowInfoError {}
65
66#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
67pub enum FlowInfo {
68 NetFlowV9(netflow::NetFlowV9Packet),
69 IPFIX(ipfix::IpfixPacket),
70}
71
72impl FlowInfo {
73 pub const fn export_time(&self) -> chrono::DateTime<chrono::Utc> {
74 match self {
75 Self::IPFIX(packet) => packet.export_time(),
76 Self::NetFlowV9(packet) => packet.unix_time(),
77 }
78 }
79
80 pub const fn sequence_number(&self) -> u32 {
81 match self {
82 Self::IPFIX(packet) => packet.sequence_number(),
83 Self::NetFlowV9(packet) => packet.sequence_number(),
84 }
85 }
86
87 pub const fn observation_domain_id(&self) -> u32 {
88 match self {
89 Self::IPFIX(packet) => packet.observation_domain_id(),
90 Self::NetFlowV9(packet) => packet.source_id(),
91 }
92 }
93
94 pub fn with_fields_added(self, add_fields: &[Field]) -> Result<Self, FlowInfoError> {
96 match self {
97 Self::IPFIX(packet) => Ok(Self::IPFIX(packet.with_fields_added(add_fields))),
98 Self::NetFlowV9(_) => Err(FlowInfoError::NetFlowV9NotSupported),
99 }
100 }
101
102 pub fn with_scope_fields_added(
104 self,
105 add_scope_fields: &[Field],
106 ) -> Result<Self, FlowInfoError> {
107 match self {
108 Self::IPFIX(packet) => Ok(Self::IPFIX(
109 packet.with_scope_fields_added(add_scope_fields),
110 )),
111 Self::NetFlowV9(_) => Err(FlowInfoError::NetFlowV9NotSupported),
112 }
113 }
114}
115
116#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, strum_macros::Display)]
118pub enum FieldSpecifierError {
119 #[strum(to_string = "Invalid length specified {0} for IE: {1:?}")]
121 InvalidLength(u16, IE),
122}
123
124impl std::error::Error for FieldSpecifierError {}
125
126#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
138#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
139pub struct FieldSpecifier {
140 element_id: IE,
141 length: u16,
142}
143
144impl FieldSpecifier {
145 pub fn new(element_id: IE, length: u16) -> Result<Self, FieldSpecifierError> {
146 if let Some(range) = element_id.length_range()
147 && !range.contains(&length)
148 {
149 return Err(FieldSpecifierError::InvalidLength(length, element_id));
150 };
151 Ok(Self { element_id, length })
152 }
153
154 pub const fn element_id(&self) -> IE {
155 self.element_id
156 }
157
158 pub const fn length(&self) -> u16 {
159 self.length
160 }
161}
162
163#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, strum_macros::Display)]
164pub enum DataSetIdError {
165 #[strum(serialize = "Invalid data set id specified: {0}")]
166 InvalidId(u16),
167}
168
169impl std::error::Error for DataSetIdError {}
170
171#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
172#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
173pub struct DataSetId(u16);
174
175pub(crate) const DATA_SET_MIN_ID: u16 = 256;
177
178impl DataSetId {
179 pub const fn new(id: u16) -> Result<Self, DataSetIdError> {
180 if id < DATA_SET_MIN_ID {
181 Err(DataSetIdError::InvalidId(id))
182 } else {
183 Ok(Self(id))
184 }
185 }
186
187 #[inline]
188 pub const fn id(&self) -> u16 {
189 self.0
190 }
191}
192
193impl Deref for DataSetId {
194 type Target = u16;
195
196 fn deref(&self) -> &Self::Target {
197 &self.0
198 }
199}
200
201#[cfg(feature = "fuzz")]
202fn arbitrary_datetime(
203 u: &mut arbitrary::Unstructured<'_>,
204) -> arbitrary::Result<chrono::DateTime<chrono::Utc>> {
205 use chrono::TimeZone;
206 loop {
207 let seconds = u.int_in_range(0..=i64::MAX)?;
208 if let chrono::LocalResult::Single(tt) = chrono::Utc.timestamp_opt(seconds, 0) {
209 return Ok(tt);
210 }
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217 use crate::ie::protocolIdentifier;
218 use crate::ipfix::IpfixPacket;
219 use crate::netflow::NetFlowV9Packet;
220 use chrono::{TimeZone, Utc};
221 use netgauze_iana::tcp::TCPHeaderFlags;
222
223 #[test]
224 fn test_flow_info_api() {
225 let export_time = Utc.with_ymd_and_hms(2024, 6, 20, 14, 0, 0).unwrap();
226 let sequence_number = 2;
227 let observation_domain = 100;
228 let ipfix_data = IpfixPacket::new(
229 export_time,
230 sequence_number,
231 observation_domain,
232 Box::new([ipfix::Set::Data {
233 id: DataSetId::new(400).unwrap(),
234 records: Box::new([]),
235 }]),
236 );
237 let netflow_data = NetFlowV9Packet::new(
238 45646,
239 export_time,
240 sequence_number,
241 observation_domain,
242 Box::new([netflow::Set::Data {
243 id: DataSetId::new(400).unwrap(),
244 records: Box::new([]),
245 }]),
246 );
247
248 let flow_ipfix = FlowInfo::IPFIX(ipfix_data.clone());
249 let flow_netflow = FlowInfo::NetFlowV9(netflow_data.clone());
250
251 assert_eq!(ipfix_data.export_time(), export_time);
252 assert_eq!(ipfix_data.sequence_number(), sequence_number);
253 assert_eq!(ipfix_data.observation_domain_id(), observation_domain);
254 assert_eq!(netflow_data.unix_time(), export_time);
255 assert_eq!(netflow_data.sequence_number(), sequence_number);
256 assert_eq!(netflow_data.source_id(), observation_domain);
257 assert_eq!(flow_ipfix.export_time(), export_time);
258 assert_eq!(flow_ipfix.sequence_number(), sequence_number);
259 assert_eq!(flow_ipfix.observation_domain_id(), observation_domain);
260 assert_eq!(flow_netflow.export_time(), export_time);
261 assert_eq!(flow_netflow.sequence_number(), sequence_number);
262 assert_eq!(flow_netflow.observation_domain_id(), observation_domain);
263 }
264
265 #[test]
266 fn test_supports_arithmetic() {
267 assert!(!IE::mplsLabelStackSection.supports_arithmetic_ops());
269 assert!(!IE::paddingOctets.supports_arithmetic_ops());
270 assert!(IE::destinationIPv4PrefixLength.supports_arithmetic_ops());
272 assert!(IE::flowActiveTimeout.supports_arithmetic_ops());
273 assert!(IE::distinctCountOfSourceIPv4Address.supports_arithmetic_ops());
274 assert!(IE::postMCastPacketDeltaCount.supports_arithmetic_ops());
275 assert!(!IE::ipv6ExtensionHeadersFull.supports_arithmetic_ops());
276 assert!(IE::mibObjectValueInteger.supports_arithmetic_ops());
277 assert!(IE::absoluteError.supports_arithmetic_ops());
278 assert!(!IE::ipClassOfService.supports_arithmetic_ops());
281 assert!(!IE::egressInterface.supports_arithmetic_ops());
282 assert!(!IE::forwardingStatus.supports_arithmetic_ops());
283 assert!(!IE::dataRecordsReliability.supports_arithmetic_ops());
285 assert!(!IE::observationTimeSeconds.supports_arithmetic_ops());
287 assert!(!IE::observationTimeMilliseconds.supports_arithmetic_ops());
288 assert!(!IE::observationTimeNanoseconds.supports_arithmetic_ops());
289 assert!(!IE::observationTimeMicroseconds.supports_arithmetic_ops());
290 assert!(!IE::sourceIPv4Address.supports_arithmetic_ops());
292 assert!(!IE::sourceIPv6Address.supports_arithmetic_ops());
293 assert!(!IE::bgpSourceCommunityList.supports_arithmetic_ops());
295 assert!(!IE::ipv6ExtensionHeaderTypeCountList.supports_arithmetic_ops());
296 assert!(!IE::subTemplateMultiList.supports_arithmetic_ops());
297 }
298
299 #[test]
300 fn test_supports_bitwise_ops() {
301 assert!(IE::mplsLabelStackSection.supports_bitwise_ops());
303 assert!(IE::paddingOctets.supports_bitwise_ops());
304 assert!(IE::destinationIPv4PrefixLength.supports_bitwise_ops());
306 assert!(IE::flowActiveTimeout.supports_bitwise_ops());
307 assert!(IE::distinctCountOfSourceIPv4Address.supports_bitwise_ops());
308 assert!(IE::postMCastPacketDeltaCount.supports_bitwise_ops());
309 assert!(IE::ipv6ExtensionHeadersFull.supports_bitwise_ops());
310 assert!(IE::mibObjectValueInteger.supports_bitwise_ops());
311 assert!(IE::ipClassOfService.supports_bitwise_ops());
314 assert!(IE::egressInterface.supports_bitwise_ops());
315 assert!(IE::forwardingStatus.supports_bitwise_ops());
316 assert!(IE::dataRecordsReliability.supports_bitwise_ops());
318 assert!(!IE::observationTimeSeconds.supports_bitwise_ops());
320 assert!(!IE::observationTimeMilliseconds.supports_bitwise_ops());
321 assert!(!IE::observationTimeNanoseconds.supports_bitwise_ops());
322 assert!(!IE::observationTimeMicroseconds.supports_bitwise_ops());
323 assert!(IE::sourceIPv4Address.supports_bitwise_ops());
325 assert!(IE::sourceIPv6Address.supports_bitwise_ops());
326 }
327
328 #[test]
329 fn test_supports_comparison_ops() {
330 assert!(!IE::mplsLabelStackSection.supports_comparison_ops());
332 assert!(!IE::paddingOctets.supports_comparison_ops());
333 assert!(IE::destinationIPv4PrefixLength.supports_comparison_ops());
335 assert!(IE::flowActiveTimeout.supports_comparison_ops());
336 assert!(IE::distinctCountOfSourceIPv4Address.supports_comparison_ops());
337 assert!(IE::postMCastPacketDeltaCount.supports_comparison_ops());
338 assert!(!IE::ipv6ExtensionHeadersFull.supports_comparison_ops());
339 assert!(IE::mibObjectValueInteger.supports_comparison_ops());
340 assert!(IE::ipClassOfService.supports_comparison_ops());
343 assert!(IE::egressInterface.supports_comparison_ops());
344 assert!(IE::forwardingStatus.supports_comparison_ops());
345 assert!(!IE::dataRecordsReliability.supports_comparison_ops());
347 assert!(IE::observationTimeSeconds.supports_comparison_ops());
349 assert!(IE::observationTimeMilliseconds.supports_comparison_ops());
350 assert!(IE::observationTimeNanoseconds.supports_comparison_ops());
351 assert!(IE::observationTimeMicroseconds.supports_comparison_ops());
352 assert!(IE::sourceIPv4Address.supports_comparison_ops());
354 assert!(IE::sourceIPv6Address.supports_comparison_ops());
355 }
356
357 #[test]
358 fn test_field_add() {
359 let mut octet1 = Field::octetDeltaCount(100);
360 let octet2 = Field::octetDeltaCount(200);
361 let packet1 = Field::packetDeltaCount(300);
362
363 let result_err1 = octet1.add_field(&packet1);
364 let result_err2 = octet1.add_assign_field(&packet1);
365 let result = octet1.add_field(&octet2).expect("add field");
366 octet1
367 .add_assign_field(&octet2)
368 .expect("add field mut failed");
369 let expected = Field::octetDeltaCount(300);
370 let expected_err = Some(FieldOperationError::InapplicableAdd(
371 IE::octetDeltaCount,
372 IE::packetDeltaCount,
373 ));
374
375 assert_eq!(result, expected);
376 assert_eq!(octet1, expected);
377 assert_eq!(result_err1.err(), expected_err);
378 assert_eq!(result_err2.err(), expected_err);
379 }
380
381 #[test]
382 fn test_field_min() {
383 let mut field1 = Field::octetDeltaCount(100);
384 let field2 = Field::octetDeltaCount(200);
385 let packet1 = Field::packetDeltaCount(300);
386
387 let result_err1 = field1.min_field(&packet1);
388 let result_err2 = field1.min_assign_field(&packet1);
389 let result = field1.min_field(&field2).expect("min field");
390 field1
391 .min_assign_field(&field2)
392 .expect("min field mut failed");
393 let expected = Field::octetDeltaCount(100);
394 let expected_err = Some(FieldOperationError::InapplicableMin(
395 IE::octetDeltaCount,
396 IE::packetDeltaCount,
397 ));
398
399 assert_eq!(result, expected);
400 assert_eq!(field1, expected);
401 assert_eq!(result_err1.err(), expected_err);
402 assert_eq!(result_err2.err(), expected_err);
403 }
404
405 #[test]
406 fn test_field_max() {
407 let mut field1 = Field::octetDeltaCount(100);
408 let field2 = Field::octetDeltaCount(200);
409 let packet1 = Field::packetDeltaCount(300);
410
411 let result_err1 = field1.max_field(&packet1);
412 let result_err2 = field1.max_assign_field(&packet1);
413 let result = field1.max_field(&field2).expect("max field");
414 field1
415 .max_assign_field(&field2)
416 .expect("max field mut failed");
417 let expected = Field::octetDeltaCount(200);
418 let expected_err = Some(FieldOperationError::InapplicableMax(
419 IE::octetDeltaCount,
420 IE::packetDeltaCount,
421 ));
422
423 assert_eq!(result, expected);
424 assert_eq!(field1, expected);
425 assert_eq!(result_err1.err(), expected_err);
426 assert_eq!(result_err2.err(), expected_err);
427 }
428
429 #[test]
430 fn test_field_bitwise_or() {
431 let mut field1 = Field::octetDeltaCount(100);
432 let field2 = Field::octetDeltaCount(200);
433 let packet1 = Field::packetDeltaCount(300);
434
435 let result_err1 = field1.bitwise_or_field(&packet1);
436 let result_err2 = field1.bitwise_or_assign_field(&packet1);
437 let result = field1.bitwise_or_field(&field2).expect("bitwise or field");
438 field1
439 .bitwise_or_assign_field(&field2)
440 .expect("bitwise or field mut failed");
441 let expected = Field::octetDeltaCount(236);
442 let expected_err = Some(FieldOperationError::InapplicableBitwise(
443 IE::octetDeltaCount,
444 IE::packetDeltaCount,
445 ));
446
447 assert_eq!(result, expected);
448 assert_eq!(field1, expected);
449 assert_eq!(result_err1.err(), expected_err);
450 assert_eq!(result_err2.err(), expected_err);
451 }
452
453 #[test]
454 fn test_field_bitwise_or_tcp_control_bits() {
455 let mut field1 = Field::tcpControlBits(TCPHeaderFlags::from(0x01u8));
456 let field2 = Field::tcpControlBits(TCPHeaderFlags::from(0x02u8));
457 let packet1 = Field::packetDeltaCount(300);
458
459 let result_err1 = field1.bitwise_or_field(&packet1);
460 let result_err2 = field1.bitwise_or_assign_field(&packet1);
461 let result = field1.bitwise_or_field(&field2).expect("bitwise or field");
462 field1
463 .bitwise_or_assign_field(&field2)
464 .expect("bitwise or field mut failed");
465 let expected = Field::tcpControlBits(TCPHeaderFlags::from(0x03u8));
466 let expected_err = Some(FieldOperationError::InapplicableBitwise(
467 IE::tcpControlBits,
468 IE::packetDeltaCount,
469 ));
470
471 assert_eq!(result, expected);
472 assert_eq!(field1, expected);
473 assert_eq!(result_err1.err(), expected_err);
474 assert_eq!(result_err2.err(), expected_err);
475 }
476
477 #[test]
478 fn test_field_bitwise_or_protocol_identifier() {
479 let mut field1 = Field::protocolIdentifier(protocolIdentifier::ICMP);
480 let field2 = Field::protocolIdentifier(protocolIdentifier::IGMP);
481 let packet1 = Field::packetDeltaCount(300);
482
483 let result_err1 = field1.bitwise_or_field(&packet1);
484 let result_err2 = field1.bitwise_or_assign_field(&packet1);
485 let result = field1.bitwise_or_field(&field2).expect("bitwise or field");
486 field1
487 .bitwise_or_assign_field(&field2)
488 .expect("bitwise or field mut failed");
489 let expected = Field::protocolIdentifier(protocolIdentifier::from(0x03u8));
490 let expected_err = Some(FieldOperationError::InapplicableBitwise(
491 IE::protocolIdentifier,
492 IE::packetDeltaCount,
493 ));
494
495 assert_eq!(result, expected);
496 assert_eq!(field1, expected);
497 assert_eq!(result_err1.err(), expected_err);
498 assert_eq!(result_err2.err(), expected_err);
499 }
500
501 #[test]
502 fn test_vmware_ops() {
503 let mut vendor_field1 = vmware::Field::averageLatency(100);
504 let vendor_field2 = vmware::Field::averageLatency(200);
505 let vendor_other_field = vmware::Field::algControlFlowId(123);
506
507 let result_err1 = vendor_field1.add_field(&vendor_other_field);
508 let result_err2 = vendor_field1.add_assign_field(&vendor_other_field);
509 let result = vendor_field1.add_field(&vendor_field2).expect("add field");
510 vendor_field1
511 .add_assign_field(&vendor_field2)
512 .expect("add field");
513 let expected = vmware::Field::averageLatency(300);
514 let expected_err = Some(vmware::FieldOperationError::InapplicableAdd(
515 vmware::IE::averageLatency,
516 vmware::IE::algControlFlowId,
517 ));
518
519 assert_eq!(result, expected);
520 assert_eq!(vendor_field1, expected);
521 assert_eq!(result_err1.err(), expected_err);
522 assert_eq!(result_err2.err(), expected_err);
523 }
524
525 #[test]
526 fn test_vendor_field_add() {
527 let mut field1 = Field::VMWare(vmware::Field::averageLatency(100));
528 let field2 = Field::VMWare(vmware::Field::averageLatency(200));
529 let other_field = Field::VMWare(vmware::Field::algControlFlowId(123));
530
531 let result_err1 = field1.add_field(&other_field);
532 let result_err2 = field1.add_assign_field(&other_field);
533 let result = field1.add_field(&field2).expect("add field");
534 field1.add_assign_field(&field2).expect("add field");
535 let expected = Field::VMWare(vmware::Field::averageLatency(300));
536 let expected_err = Some(FieldOperationError::InapplicableAdd(
537 IE::VMWare(vmware::IE::averageLatency),
538 IE::VMWare(vmware::IE::algControlFlowId),
539 ));
540
541 assert_eq!(result, expected);
542 assert_eq!(field1, expected);
543 assert_eq!(result_err1.err(), expected_err);
544 assert_eq!(result_err2.err(), expected_err);
545 }
546
547 #[test]
548 fn test_vendor_field_min() {
549 let mut field1 = Field::VMWare(vmware::Field::averageLatency(100));
550 let field2 = Field::VMWare(vmware::Field::averageLatency(200));
551 let other_field = Field::VMWare(vmware::Field::algControlFlowId(123));
552
553 let result_err1 = field1.min_field(&other_field);
554 let result_err2 = field1.min_assign_field(&other_field);
555 let result = field1.min_field(&field2).expect("min field");
556 field1.min_assign_field(&field2).expect("min field");
557 let expected = Field::VMWare(vmware::Field::averageLatency(100));
558 let expected_err = Some(FieldOperationError::InapplicableMin(
559 IE::VMWare(vmware::IE::averageLatency),
560 IE::VMWare(vmware::IE::algControlFlowId),
561 ));
562
563 assert_eq!(result, expected);
564 assert_eq!(field1, expected);
565 assert_eq!(result_err1.err(), expected_err);
566 assert_eq!(result_err2.err(), expected_err);
567 }
568
569 #[test]
570 fn test_vendor_field_max() {
571 let mut field1 = Field::VMWare(vmware::Field::averageLatency(100));
572 let field2 = Field::VMWare(vmware::Field::averageLatency(200));
573 let other_field = Field::VMWare(vmware::Field::algControlFlowId(123));
574
575 let result_err1 = field1.max_field(&other_field);
576 let result_err2 = field1.max_assign_field(&other_field);
577 let result = field1.max_field(&field2).expect("max field");
578 field1.max_assign_field(&field2).expect("max field");
579 let expected = Field::VMWare(vmware::Field::averageLatency(200));
580 let expected_err = Some(FieldOperationError::InapplicableMax(
581 IE::VMWare(vmware::IE::averageLatency),
582 IE::VMWare(vmware::IE::algControlFlowId),
583 ));
584
585 assert_eq!(result, expected);
586 assert_eq!(field1, expected);
587 assert_eq!(result_err1.err(), expected_err);
588 assert_eq!(result_err2.err(), expected_err);
589 }
590
591 #[test]
592 fn test_vendor_field_bitwise_or() {
593 let mut field1 = Field::VMWare(vmware::Field::algControlFlowId(100));
594 let field2 = Field::VMWare(vmware::Field::algControlFlowId(200));
595 let other_field = Field::VMWare(vmware::Field::averageLatency(123));
596
597 let result_err1 = field1.bitwise_or_field(&other_field);
598 let result_err2 = field1.bitwise_or_field(&other_field);
599 let result = field1.bitwise_or_field(&field2).expect("bitwise or field");
600 field1
601 .bitwise_or_assign_field(&field2)
602 .expect("bitwise or field");
603 let expected = Field::VMWare(vmware::Field::algControlFlowId(236));
604 let expected_err = Some(FieldOperationError::InapplicableBitwise(
605 IE::VMWare(vmware::IE::algControlFlowId),
606 IE::VMWare(vmware::IE::averageLatency),
607 ));
608
609 assert_eq!(result, expected);
610 assert_eq!(field1, expected);
611 assert_eq!(result_err1.err(), expected_err);
612 assert_eq!(result_err2.err(), expected_err);
613 }
614}