net_parser_rs/flow/layer3/
ipv6.rs1use crate::flow::Flow;
2use crate::flow::errors::Error;
3use crate::flow::info::layer2::{Info as L2Info};
4use crate::flow::info::layer3::{Info, Id};
5use crate::flow::layer3::FlowExtraction;
6use crate::flow::layer3::errors::{Error as L3Error};
7use crate::flow::layer4::{FlowExtraction as Layer4Extraction};
8use crate::layer3::{InternetProtocolId, IPv6};
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 IPv6<'a> {
41 fn extract_flow(&self, l2: L2Info) -> Result<Flow, Error> {
42 let l3 = Info {
43 id: Id::IPv6,
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 error!("Error parsing udp {:?}", e);
75 let e: L3Error = errors::Error::NetParser {
76 l4: proto.clone(),
77 err: e.into()
78 }.into();
79 e.into()
80 })
81 .and_then(|r| {
82 let (rem, l4) = r;
83 if rem.is_empty() {
84 l4.extract_flow(l2, l3)
85 } else {
86 let e: L3Error = errors::Error::Incomplete {
87 l4: proto.clone(),
88 size: rem.len()
89 }.into();
90 Err(e.into())
91 }
92 })
93 }
94 _ => {
95 let e: L3Error = errors::Error::InternetProtocolId {
96 id: proto.clone()
97 }.into();
98 Err(e.into())
99 }
100 }
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 use crate::common::MacAddress;
109 use crate::flow::info::layer2::{Id as L2Id, Info as L2Info};
110 use crate::flow::info::layer3::{Id as L3Id};
111 use crate::layer3::ipv6::IPv6;
112 use crate::layer3::ipv6::tests::RAW_DATA;
113
114 #[test]
115 fn convert_ipv6() {
116 let _ = env_logger::try_init();
117
118 let (_, l3) = IPv6::parse(RAW_DATA).expect("Unable to parse");
119
120 let l2 = L2Info {
121 id: L2Id::Ethernet,
122 src_mac: MacAddress::default(),
123 dst_mac: MacAddress::default(),
124 vlan: 0
125 };
126
127 let info = l3.extract_flow(l2).expect("Could not convert to layer 3 info");
128
129 assert_eq!(info.layer3, L3Id::IPv6);
130 assert_eq!(
131 info.source.ip,
132 "102:304:506:708:90A:B0C:D0E:F0F"
133 .parse::<std::net::IpAddr>()
134 .expect("Could not parse ip address")
135 );
136 assert_eq!(
137 info.destination.ip,
138 "F00:102:304:506:708:90A:B0C:D0E"
139 .parse::<std::net::IpAddr>()
140 .expect("Could not parse ip address")
141 );
142 assert_eq!(info.source.port, 50871);
143 assert_eq!(info.destination.port, 80);
144 }
145}