net_parser_rs/flow/layer3/
ipv6.rs

1use 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}