net_parser_rs/flow/layer3/
ipv4.rs

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