Skip to content

Commit 1dc9a09

Browse files
mikemiles-devmikemiles-dev
and
mikemiles-dev
authored
feat(Fix Readme example packets.) (#83)
feat(Fix Readme example packets.) feat(Optimized IPFix, V9 NetflowCommon lookup.) feat(DataNumber down converters and netflowcommon cleanup) --------- Co-authored-by: mikemiles-dev <[email protected]>
1 parent 0373ad3 commit 1dc9a09

File tree

6 files changed

+245
-137
lines changed

6 files changed

+245
-137
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "netflow_parser"
33
description = "Parser for Netflow Cisco V5, V7, V9, IPFIX"
4-
version = "0.4.3"
4+
version = "0.4.4"
55
edition = "2021"
66
77
license = "MIT OR Apache-2.0"

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ See: <https://en.wikipedia.org/wiki/NetFlow>
1515
```rust
1616
use netflow_parser::{NetflowParser, NetflowPacket};
1717

18-
let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
18+
let v5_packet = [0, 5, 0, 1, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
1919
match NetflowParser::default().parse_bytes(&v5_packet).first() {
2020
Some(NetflowPacket::V5(v5)) => assert_eq!(v5.header.version, 5),
2121
Some(NetflowPacket::Error(e)) => println!("{:?}", e),
@@ -29,7 +29,7 @@ Structures fully support serialization. Below is an example using the serde_jso
2929
use serde_json::json;
3030
use netflow_parser::NetflowParser;
3131

32-
let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
32+
let v5_packet = [0, 5, 0, 1, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
3333
println!("{}", json!(NetflowParser::default().parse_bytes(&v5_packet)).to_string());
3434
```
3535

@@ -42,7 +42,7 @@ println!("{}", json!(NetflowParser::default().parse_bytes(&v5_packet)).to_string
4242
```rust
4343
use netflow_parser::{NetflowParser, NetflowPacket};
4444

45-
let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
45+
let v5_packet = [0, 5, 0, 1, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
4646
let parsed = NetflowParser::default().parse_bytes(&v5_packet);
4747

4848
let v5_parsed: Vec<NetflowPacket> = parsed.into_iter().filter(|p| p.is_v5()).collect();

RELEASES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 0.4.4
2+
* Fix Readme example packets.
3+
* Optimized IPFix, V9 NetflowCommon lookup.
4+
* DataNumbers can now be downcast into actual data types: (u8, u16, i32, u32, u64, u128).
5+
16
# 0.4.3
27
* Fixed bug in NetflowCommon where ProtocolType was never set.
38
* Minor Readme Changes.

src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//! ```rust
1616
//! use netflow_parser::{NetflowParser, NetflowPacket};
1717
//!
18-
//! let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
18+
//! let v5_packet = [0, 5, 0, 1, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
1919
//! match NetflowParser::default().parse_bytes(&v5_packet).first() {
2020
//! Some(NetflowPacket::V5(v5)) => assert_eq!(v5.header.version, 5),
2121
//! Some(NetflowPacket::Error(e)) => println!("{:?}", e),
@@ -29,7 +29,7 @@
2929
//! use serde_json::json;
3030
//! use netflow_parser::NetflowParser;
3131
//!
32-
//! let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
32+
//! let v5_packet = [0, 5, 0, 1, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
3333
//! println!("{}", json!(NetflowParser::default().parse_bytes(&v5_packet)).to_string());
3434
//! ```
3535
//!
@@ -42,7 +42,7 @@
4242
//! ```rust
4343
//! use netflow_parser::{NetflowParser, NetflowPacket};
4444
//!
45-
//! let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
45+
//! let v5_packet = [0, 5, 0, 1, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
4646
//! let parsed = NetflowParser::default().parse_bytes(&v5_packet);
4747
//!
4848
//! let v5_parsed: Vec<NetflowPacket> = parsed.into_iter().filter(|p| p.is_v5()).collect();

src/netflow_common.rs

Lines changed: 60 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
use std::collections::BTreeMap;
12
use std::net::IpAddr;
23

34
use crate::protocol::ProtocolTypes;
45
use crate::static_versions::{v5::V5, v7::V7};
5-
use crate::variable_versions::data_number::{DataNumber, FieldValue};
6+
use crate::variable_versions::data_number::FieldValue;
67
use crate::variable_versions::ipfix_lookup::IPFixField;
78
use crate::variable_versions::v9_lookup::V9Field;
89
use crate::variable_versions::{ipfix::IPFix, v9::V9};
@@ -112,71 +113,35 @@ impl From<&V9> for NetflowCommon {
112113
for flowset in &value.flowsets {
113114
if let Some(data) = &flowset.body.data {
114115
for data_field in &data.data_fields {
115-
let values: Vec<(V9Field, FieldValue)> =
116+
let value_map: BTreeMap<V9Field, FieldValue> =
116117
data_field.values().cloned().collect();
117118
flowsets.push(NetflowCommonFlowSet {
118-
src_addr: values
119-
.iter()
120-
.find(|(k, _)| {
121-
*k == V9Field::Ipv4SrcAddr || *k == V9Field::Ipv6SrcAddr
122-
})
123-
.and_then(|(_, v)| match v {
124-
FieldValue::Ip4Addr(ip) => Some((*ip).into()),
125-
_ => None,
126-
}),
127-
dst_addr: values
128-
.iter()
129-
.find(|(k, _)| {
130-
*k == V9Field::Ipv4DstAddr || *k == V9Field::Ipv6DstAddr
131-
})
132-
.and_then(|(_, v)| match v {
133-
FieldValue::Ip4Addr(ip) => Some((*ip).into()),
134-
_ => None,
135-
}),
136-
src_port: values
137-
.iter()
138-
.find(|(k, _)| *k == V9Field::L4SrcPort)
139-
.and_then(|(_, v)| match v {
140-
FieldValue::DataNumber(DataNumber::U16(port)) => Some(*port),
141-
_ => None,
142-
}),
143-
dst_port: values
144-
.iter()
145-
.find(|(k, _)| *k == V9Field::L4DstPort)
146-
.and_then(|(_, v)| match v {
147-
FieldValue::DataNumber(DataNumber::U16(port)) => Some(*port),
148-
_ => None,
149-
}),
150-
protocol_number: values
151-
.iter()
152-
.find(|(k, _)| *k == V9Field::Protocol)
153-
.and_then(|(_, v)| match v {
154-
FieldValue::DataNumber(DataNumber::U8(proto)) => Some(*proto),
155-
_ => None,
156-
}),
157-
first_seen: values
158-
.iter()
159-
.find(|(k, _)| *k == V9Field::FirstSwitched)
160-
.and_then(|(_, v)| match v {
161-
FieldValue::DataNumber(DataNumber::U32(seen)) => Some(*seen),
162-
_ => None,
163-
}),
164-
last_seen: values
165-
.iter()
166-
.find(|(k, _)| *k == V9Field::LastSwitched)
167-
.and_then(|(_, v)| match v {
168-
FieldValue::DataNumber(DataNumber::U32(seen)) => Some(*seen),
169-
_ => None,
170-
}),
171-
protocol_type: values
172-
.iter()
173-
.find(|(k, _)| *k == V9Field::Protocol)
174-
.and_then(|(_, v)| match v {
175-
FieldValue::DataNumber(DataNumber::U8(proto)) => {
176-
Some(ProtocolTypes::from(*proto))
177-
}
178-
_ => None,
179-
}),
119+
src_addr: value_map
120+
.get(&V9Field::Ipv4SrcAddr)
121+
.and_then(|v| v.try_into().ok()),
122+
dst_addr: value_map
123+
.get(&V9Field::Ipv4DstAddr)
124+
.and_then(|v| v.try_into().ok()),
125+
src_port: value_map
126+
.get(&V9Field::L4SrcPort)
127+
.and_then(|v| v.try_into().ok()),
128+
dst_port: value_map
129+
.get(&V9Field::L4DstPort)
130+
.and_then(|v| v.try_into().ok()),
131+
protocol_number: value_map
132+
.get(&V9Field::Protocol)
133+
.and_then(|v| v.try_into().ok()),
134+
protocol_type: value_map.get(&V9Field::Protocol).and_then(|v| {
135+
v.try_into()
136+
.ok()
137+
.map(|proto: u8| ProtocolTypes::from(proto))
138+
}),
139+
first_seen: value_map
140+
.get(&V9Field::FirstSwitched)
141+
.and_then(|v| v.try_into().ok()),
142+
last_seen: value_map
143+
.get(&V9Field::LastSwitched)
144+
.and_then(|v| v.try_into().ok()),
180145
});
181146
}
182147
}
@@ -199,73 +164,39 @@ impl From<&IPFix> for NetflowCommon {
199164
for flowset in &value.flowsets {
200165
if let Some(data) = &flowset.body.data {
201166
for data_field in &data.data_fields {
202-
let values: Vec<(IPFixField, FieldValue)> =
167+
let value_map: BTreeMap<IPFixField, FieldValue> =
203168
data_field.values().cloned().collect();
204169
flowsets.push(NetflowCommonFlowSet {
205-
src_addr: values
206-
.iter()
207-
.find(|(k, _)| {
208-
*k == IPFixField::SourceIpv4address
209-
|| *k == IPFixField::SourceIpv6address
210-
})
211-
.and_then(|(_, v)| match v {
212-
FieldValue::Ip4Addr(ip) => Some((*ip).into()),
213-
_ => None,
214-
}),
215-
dst_addr: values
216-
.iter()
217-
.find(|(k, _)| {
218-
*k == IPFixField::DestinationIpv4address
219-
|| *k == IPFixField::DestinationIpv6address
220-
})
221-
.and_then(|(_, v)| match v {
222-
FieldValue::Ip4Addr(ip) => Some((*ip).into()),
223-
_ => None,
224-
}),
225-
src_port: values
226-
.iter()
227-
.find(|(k, _)| *k == IPFixField::SourceTransportPort)
228-
.and_then(|(_, v)| match v {
229-
FieldValue::DataNumber(DataNumber::U16(port)) => Some(*port),
230-
_ => None,
231-
}),
232-
dst_port: values
233-
.iter()
234-
.find(|(k, _)| *k == IPFixField::DestinationTransportPort)
235-
.and_then(|(_, v)| match v {
236-
FieldValue::DataNumber(DataNumber::U16(port)) => Some(*port),
237-
_ => None,
238-
}),
239-
protocol_number: values
240-
.iter()
241-
.find(|(k, _)| *k == IPFixField::ProtocolIdentifier)
242-
.and_then(|(_, v)| match v {
243-
FieldValue::DataNumber(DataNumber::U8(proto)) => Some(*proto),
244-
_ => None,
245-
}),
246-
first_seen: values
247-
.iter()
248-
.find(|(k, _)| *k == IPFixField::FlowStartSysUpTime)
249-
.and_then(|(_, v)| match v {
250-
FieldValue::DataNumber(DataNumber::U32(seen)) => Some(*seen),
251-
_ => None,
252-
}),
253-
last_seen: values
254-
.iter()
255-
.find(|(k, _)| *k == IPFixField::FlowEndSysUpTime)
256-
.and_then(|(_, v)| match v {
257-
FieldValue::DataNumber(DataNumber::U32(seen)) => Some(*seen),
258-
_ => None,
259-
}),
260-
protocol_type: values
261-
.iter()
262-
.find(|(k, _)| *k == IPFixField::ProtocolIdentifier)
263-
.and_then(|(_, v)| match v {
264-
FieldValue::DataNumber(DataNumber::U8(proto)) => {
265-
Some(ProtocolTypes::from(*proto))
266-
}
267-
_ => None,
268-
}),
170+
src_addr: value_map
171+
.get(&IPFixField::SourceIpv4address)
172+
.or_else(|| value_map.get(&IPFixField::SourceIpv6address))
173+
.and_then(|v| v.try_into().ok()),
174+
dst_addr: value_map
175+
.get(&IPFixField::DestinationIpv4address)
176+
.or_else(|| value_map.get(&IPFixField::DestinationIpv6address))
177+
.and_then(|v| v.try_into().ok()),
178+
src_port: value_map
179+
.get(&IPFixField::SourceTransportPort)
180+
.and_then(|v| v.try_into().ok()),
181+
dst_port: value_map
182+
.get(&IPFixField::DestinationTransportPort)
183+
.and_then(|v| v.try_into().ok()),
184+
protocol_number: value_map
185+
.get(&IPFixField::ProtocolIdentifier)
186+
.and_then(|v| v.try_into().ok()),
187+
protocol_type: value_map.get(&IPFixField::ProtocolIdentifier).and_then(
188+
|v| {
189+
v.try_into()
190+
.ok()
191+
.map(|proto: u8| ProtocolTypes::from(proto))
192+
},
193+
),
194+
first_seen: value_map
195+
.get(&IPFixField::FlowStartSysUpTime)
196+
.and_then(|v| v.try_into().ok()),
197+
last_seen: value_map
198+
.get(&IPFixField::FlowEndSysUpTime)
199+
.and_then(|v| v.try_into().ok()),
269200
});
270201
}
271202
}

0 commit comments

Comments
 (0)