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}