Skip to main content

nex_packet/
frame.rs

1use bytes::Bytes;
2use nex_core::mac::MacAddr;
3
4use crate::{
5    arp::{ArpHeader, ArpPacket},
6    ethernet::{EtherType, EthernetHeader, EthernetPacket},
7    icmp::{IcmpHeader, IcmpPacket},
8    icmpv6::{Icmpv6Header, Icmpv6Packet},
9    ip::IpNextProtocol,
10    ipv4::{Ipv4Header, Ipv4Packet},
11    ipv6::{Ipv6Header, Ipv6Packet},
12    packet::Packet,
13    tcp::{TcpHeader, TcpPacket},
14    udp::{UdpHeader, UdpPacket},
15};
16
17#[cfg(feature = "serde")]
18use serde::{Deserialize, Serialize};
19
20#[derive(Clone, Debug, PartialEq, Eq)]
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22pub struct DatalinkLayer {
23    pub ethernet: Option<EthernetHeader>,
24    pub arp: Option<ArpHeader>,
25}
26
27#[derive(Clone, Debug, PartialEq, Eq)]
28#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
29pub struct IpLayer {
30    pub ipv4: Option<Ipv4Header>,
31    pub ipv6: Option<Ipv6Header>,
32    pub icmp: Option<IcmpHeader>,
33    pub icmpv6: Option<Icmpv6Header>,
34}
35
36#[derive(Clone, Debug, PartialEq, Eq)]
37#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
38pub struct TransportLayer {
39    pub tcp: Option<TcpHeader>,
40    pub udp: Option<UdpHeader>,
41}
42
43#[derive(Clone, Debug, PartialEq, Eq)]
44#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
45pub struct ParseOption {
46    pub from_ip_packet: bool,
47    pub offset: usize,
48}
49
50impl Default for ParseOption {
51    fn default() -> Self {
52        Self {
53            from_ip_packet: false,
54            offset: 0,
55        }
56    }
57}
58
59#[derive(Clone, Debug, PartialEq, Eq)]
60#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
61pub struct Frame {
62    pub datalink: Option<DatalinkLayer>,
63    pub ip: Option<IpLayer>,
64    pub transport: Option<TransportLayer>,
65    pub payload: Bytes,
66    pub packet_len: usize,
67}
68
69impl Frame {
70    pub fn from_buf(packet: &[u8], option: ParseOption) -> Option<Self> {
71        let mut frame = Frame {
72            datalink: None,
73            ip: None,
74            transport: None,
75            payload: Bytes::new(),
76            packet_len: packet.len(),
77        };
78
79        let ethernet_packet = if option.from_ip_packet {
80            create_dummy_ethernet_packet(packet, option.offset)?
81        } else {
82            EthernetPacket::from_buf(packet)?
83        };
84
85        let ether_type = ethernet_packet.get_ethertype();
86        let (ether_header, ether_payload) = ethernet_packet.into_parts();
87        frame.datalink = Some(DatalinkLayer {
88            ethernet: Some(ether_header),
89            arp: None,
90        });
91
92        match ether_type {
93            EtherType::Ipv4 => parse_ipv4_packet(ether_payload, &mut frame),
94            EtherType::Ipv6 => parse_ipv6_packet(ether_payload, &mut frame),
95            EtherType::Arp => parse_arp_packet(ether_payload, &mut frame),
96            _ => {}
97        }
98
99        Some(frame)
100    }
101}
102
103pub fn create_dummy_ethernet_packet(packet: &[u8], offset: usize) -> Option<EthernetPacket> {
104    if offset >= packet.len() {
105        return None;
106    }
107
108    let payload = &packet[offset..];
109
110    let ethertype = if Ipv4Packet::from_buf(payload).is_some() {
111        EtherType::Ipv4
112    } else if Ipv6Packet::from_buf(payload).is_some() {
113        EtherType::Ipv6
114    } else {
115        return None;
116    };
117
118    let header = EthernetHeader {
119        destination: MacAddr::zero(),
120        source: MacAddr::zero(),
121        ethertype,
122    };
123
124    Some(EthernetPacket {
125        header,
126        payload: Bytes::copy_from_slice(payload),
127    })
128}
129
130fn parse_arp_packet(packet: Bytes, frame: &mut Frame) {
131    match ArpPacket::from_buf(&packet) {
132        Some(arp_packet) => {
133            if let Some(datalink) = &mut frame.datalink {
134                datalink.arp = Some(arp_packet.header);
135            }
136        }
137        None => {
138            if let Some(datalink) = &mut frame.datalink {
139                datalink.arp = None;
140            }
141            frame.payload = packet;
142        }
143    }
144}
145
146fn parse_ipv4_packet(packet: Bytes, frame: &mut Frame) {
147    match Ipv4Packet::from_bytes(packet) {
148        Some(ipv4_packet) => {
149            let (header, payload) = ipv4_packet.into_parts();
150            let proto = header.next_level_protocol;
151            frame.ip = Some(IpLayer {
152                ipv4: Some(header),
153                ipv6: None,
154                icmp: None,
155                icmpv6: None,
156            });
157            match proto {
158                IpNextProtocol::Tcp => {
159                    parse_tcp_packet(payload, frame);
160                }
161                IpNextProtocol::Udp => {
162                    parse_udp_packet(payload, frame);
163                }
164                IpNextProtocol::Icmp => {
165                    parse_icmp_packet(payload, frame);
166                }
167                _ => {
168                    frame.payload = payload;
169                }
170            }
171        }
172        None => {
173            frame.ip = Some(IpLayer {
174                ipv4: None,
175                ipv6: None,
176                icmp: None,
177                icmpv6: None,
178            });
179        }
180    }
181}
182
183fn parse_ipv6_packet(packet: Bytes, frame: &mut Frame) {
184    match Ipv6Packet::from_bytes(packet) {
185        Some(ipv6_packet) => {
186            let (header, payload) = ipv6_packet.into_parts();
187            let proto = header.next_header;
188            frame.ip = Some(IpLayer {
189                ipv4: None,
190                ipv6: Some(header),
191                icmp: None,
192                icmpv6: None,
193            });
194            match proto {
195                IpNextProtocol::Tcp => {
196                    parse_tcp_packet(payload, frame);
197                }
198                IpNextProtocol::Udp => {
199                    parse_udp_packet(payload, frame);
200                }
201                IpNextProtocol::Icmpv6 => {
202                    parse_icmpv6_packet(payload, frame);
203                }
204                _ => {
205                    frame.payload = payload;
206                }
207            }
208        }
209        None => {
210            frame.ip = Some(IpLayer {
211                ipv4: None,
212                ipv6: None,
213                icmp: None,
214                icmpv6: None,
215            });
216        }
217    }
218}
219
220fn parse_tcp_packet(packet: Bytes, frame: &mut Frame) {
221    match TcpPacket::from_bytes(packet.clone()) {
222        Some(tcp_packet) => {
223            let (header, payload) = tcp_packet.into_parts();
224            frame.transport = Some(TransportLayer {
225                tcp: Some(header),
226                udp: None,
227            });
228            frame.payload = payload;
229        }
230        None => {
231            frame.transport = Some(TransportLayer {
232                tcp: None,
233                udp: None,
234            });
235            frame.payload = packet;
236        }
237    }
238}
239
240fn parse_udp_packet(packet: Bytes, frame: &mut Frame) {
241    match UdpPacket::from_bytes(packet.clone()) {
242        Some(udp_packet) => {
243            let (header, payload) = udp_packet.into_parts();
244            frame.transport = Some(TransportLayer {
245                tcp: None,
246                udp: Some(header),
247            });
248            frame.payload = payload;
249        }
250        None => {
251            frame.transport = Some(TransportLayer {
252                tcp: None,
253                udp: None,
254            });
255            frame.payload = packet;
256        }
257    }
258}
259
260fn parse_icmp_packet(packet: Bytes, frame: &mut Frame) {
261    match IcmpPacket::from_bytes(packet.clone()) {
262        Some(icmp_packet) => {
263            let (header, payload) = icmp_packet.into_parts();
264            if let Some(ip) = &mut frame.ip {
265                ip.icmp = Some(header);
266            }
267            frame.payload = payload;
268        }
269        None => {
270            if let Some(ip) = &mut frame.ip {
271                ip.icmp = None;
272            }
273            frame.payload = packet;
274        }
275    }
276}
277
278fn parse_icmpv6_packet(packet: Bytes, frame: &mut Frame) {
279    match Icmpv6Packet::from_bytes(packet.clone()) {
280        Some(icmpv6_packet) => {
281            let (header, payload) = icmpv6_packet.into_parts();
282            if let Some(ip) = &mut frame.ip {
283                ip.icmpv6 = Some(header);
284            }
285            frame.payload = payload;
286        }
287        None => {
288            if let Some(ip) = &mut frame.ip {
289                ip.icmpv6 = None;
290            }
291            frame.payload = packet;
292        }
293    }
294}