net_parser_rs/flow/layer3/
ipv4.rs1use crate::flow::Flow;
2use crate::flow::errors::Error;
3use crate::flow::info::layer2::{Info as L2Info};
4use crate::flow::info::layer3::{Id, Info};
5use crate::flow::layer3::FlowExtraction;
6use crate::flow::layer3::errors::{Error as L3Error};
7use crate::flow::layer4::{FlowExtraction as Layer4Extraction};
8use crate::layer3::{InternetProtocolId, IPv4};
9use crate::layer4::{Tcp, Udp};
10
11use log::*;
12
13pub mod errors {
14 use crate::errors::Error as NetParserError;
15 use crate::layer3::InternetProtocolId;
16 use thiserror::{Error as ThisError};
17
18 #[derive(Debug, ThisError)]
19 pub enum Error {
20 #[error("Failed parse of {:?}: {}", l4, err)]
21 NetParser {
22 l4: InternetProtocolId,
23 err: NetParserError
24 },
25 #[error("Incomplete parse of {:?}: {}", l4, size)]
26 Incomplete {
27 l4: InternetProtocolId,
28 size: usize
29 },
30 #[error("Unknown type while parsing IPv4: {:?}", id)]
31 InternetProtocolId {
32 id: InternetProtocolId
33 },
34 }
35
36 unsafe impl Sync for Error {}
37 unsafe impl Send for Error {}
38}
39
40impl<'a> FlowExtraction for IPv4<'a> {
41 fn extract_flow(&self, l2: L2Info) -> Result<Flow, Error> {
42 let l3 = Info {
43 id: Id::IPv4,
44 src_ip: self.src_ip,
45 dst_ip: self.dst_ip
46 };
47 debug!("Creating stream info from {:?}", self.protocol);
48 let proto = self.protocol.clone();
49 match proto {
50 InternetProtocolId::Tcp => {
51 Tcp::parse(self.payload).map_err(|e| {
52 error!("Error parsing tcp {:?}", e);
53 let e: L3Error = errors::Error::NetParser {
54 l4: proto.clone(),
55 err: e
56 }.into();
57 e.into()
58 })
59 .and_then(|r| {
60 let (rem, l4) = r;
61 if rem.is_empty() {
62 l4.extract_flow(l2, l3)
63 } else {
64 let e: L3Error = errors::Error::Incomplete {
65 l4: proto.clone(),
66 size: rem.len()
67 }.into();
68 Err(e.into())
69 }
70 })
71 }
72 InternetProtocolId::Udp => {
73 Udp::parse(self.payload).map_err(|e| {
74 #[cfg(feature = "logging")]
75 error!("Error parsing udp {:?}", e);
76 let e: L3Error = errors::Error::NetParser {
77 l4: proto.clone(),
78 err: e
79 }.into();
80 e.into()
81 })
82 .and_then(|r| {
83 let (rem, l4) = r;
84 if rem.is_empty() {
85 l4.extract_flow(l2, l3)
86 } else {
87 let e: L3Error = errors::Error::Incomplete {
88 l4: proto.clone(),
89 size: rem.len()
90 }.into();
91 Err(e.into())
92 }
93 })
94 }
95 _ => {
96 let e: L3Error = errors::Error::InternetProtocolId {
97 id: proto.clone()
98 }.into();
99 Err(e.into())
100 }
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 use crate::common::MacAddress;
110 use crate::flow::info::layer2::{Id as L2Id, Info as L2Info};
111 use crate::flow::info::layer3::{Id as L3Id};
112 use crate::layer3::ipv4::IPv4;
113 use crate::layer3::ipv4::tests::RAW_DATA;
114
115 #[test]
116 fn convert_ipv4() {
117 let _ = env_logger::try_init();
118
119 let (_, l3) = IPv4::parse(RAW_DATA).expect("Unable to parse");
120
121 let l2 = L2Info {
122 id: L2Id::Ethernet,
123 src_mac: MacAddress::default(),
124 dst_mac: MacAddress::default(),
125 vlan: 0
126 };
127
128 let info = l3.extract_flow(l2).expect("Could not convert to layer 3 info");
129
130 assert_eq!(info.layer3, L3Id::IPv4);
131 assert_eq!(
132 info.source.ip,
133 "1.2.3.4"
134 .parse::<std::net::IpAddr>()
135 .expect("Could not parse ip address")
136 );
137 assert_eq!(
138 info.destination.ip,
139 "10.11.12.13"
140 .parse::<std::net::IpAddr>()
141 .expect("Could not parse ip address")
142 );
143 assert_eq!(info.source.port, 50871);
144 assert_eq!(info.destination.port, 80);
145 }
146}