1use std::fmt::{Display, Formatter};
71
72use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
73
74use crate::packet::protocol::EtherProto;
75use crate::packet::{HeaderParser, PacketHeader};
76
77#[repr(u32)]
82#[derive(Debug, Clone, Copy, PartialEq, Eq)]
83pub enum AddressFamily {
84 Inet = 2,
86 Inet6Linux = 10,
88 Inet6Darwin = 30,
90 Inet6FreeBsd = 28,
92 Inet6OpenBsd = 24,
94 Unknown(u32),
96}
97
98impl From<u32> for AddressFamily {
99 fn from(value: u32) -> Self {
100 match value {
101 2 => AddressFamily::Inet,
102 10 => AddressFamily::Inet6Linux,
103 24 => AddressFamily::Inet6OpenBsd,
104 28 => AddressFamily::Inet6FreeBsd,
105 30 => AddressFamily::Inet6Darwin,
106 other => AddressFamily::Unknown(other),
107 }
108 }
109}
110
111impl AddressFamily {
112 pub fn is_ipv6(&self) -> bool {
114 matches!(
115 self,
116 AddressFamily::Inet6Linux
117 | AddressFamily::Inet6Darwin
118 | AddressFamily::Inet6FreeBsd
119 | AddressFamily::Inet6OpenBsd
120 )
121 }
122
123 pub fn to_ether_proto(&self) -> EtherProto {
125 match self {
126 AddressFamily::Inet => EtherProto::IPV4,
127 AddressFamily::Inet6Linux
128 | AddressFamily::Inet6Darwin
129 | AddressFamily::Inet6FreeBsd
130 | AddressFamily::Inet6OpenBsd => EtherProto::IPV6,
131 AddressFamily::Unknown(_) => EtherProto::from(0u16),
132 }
133 }
134}
135
136impl Display for AddressFamily {
137 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
138 match self {
139 AddressFamily::Inet => write!(f, "AF_INET"),
140 AddressFamily::Inet6Linux => write!(f, "AF_INET6 (Linux)"),
141 AddressFamily::Inet6Darwin => write!(f, "AF_INET6 (Darwin)"),
142 AddressFamily::Inet6FreeBsd => write!(f, "AF_INET6 (FreeBSD)"),
143 AddressFamily::Inet6OpenBsd => write!(f, "AF_INET6 (OpenBSD)"),
144 AddressFamily::Unknown(v) => write!(f, "Unknown({})", v),
145 }
146 }
147}
148
149#[repr(C)]
161#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)]
162pub struct NullHeader {
163 family: [u8; 4],
165}
166
167impl NullHeader {
168 pub const SIZE: usize = 4;
170
171 #[inline]
173 pub fn family_raw_le(&self) -> u32 {
174 u32::from_le_bytes(self.family)
175 }
176
177 #[inline]
179 pub fn family_raw_be(&self) -> u32 {
180 u32::from_be_bytes(self.family)
181 }
182
183 #[inline]
189 pub fn address_family(&self) -> AddressFamily {
190 let le_value = self.family_raw_le();
191 let be_value = self.family_raw_be();
192
193 match le_value {
195 2 | 10 | 24 | 28 | 30 => AddressFamily::from(le_value),
196 _ => {
197 match be_value {
199 2 | 10 | 24 | 28 | 30 => AddressFamily::from(be_value),
200 _ => AddressFamily::from(le_value),
202 }
203 }
204 }
205 }
206
207 #[inline]
209 pub fn protocol(&self) -> EtherProto {
210 self.address_family().to_ether_proto()
211 }
212}
213
214impl PacketHeader for NullHeader {
215 const NAME: &'static str = "Null/Loopback";
216 type InnerType = EtherProto;
217
218 #[inline]
219 fn inner_type(&self) -> Self::InnerType {
220 self.protocol()
221 }
222}
223
224impl HeaderParser for NullHeader {
225 type Output<'a> = &'a NullHeader;
226
227 fn into_view<'a>(header: &'a Self, _options: &'a [u8]) -> Self::Output<'a> {
228 header
229 }
230}
231
232impl Display for NullHeader {
233 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
234 write!(
235 f,
236 "Null family={} (0x{:08x})",
237 self.address_family(),
238 self.family_raw_le()
239 )
240 }
241}
242
243#[cfg(test)]
244mod tests {
245 use super::*;
246
247 #[test]
248 fn test_null_header_size() {
249 assert_eq!(std::mem::size_of::<NullHeader>(), 4);
250 assert_eq!(NullHeader::SIZE, 4);
251 }
252
253 #[test]
254 fn test_null_header_ipv4_le() {
255 let packet = vec![0x02, 0x00, 0x00, 0x00, 0x45, 0x00]; let (header, payload) = NullHeader::from_bytes(&packet).unwrap();
259
260 assert_eq!(header.family_raw_le(), 2);
261 assert_eq!(header.address_family(), AddressFamily::Inet);
262 assert_eq!(header.protocol(), EtherProto::IPV4);
263 assert_eq!(payload.len(), 2);
264 }
265
266 #[test]
267 fn test_null_header_ipv6_darwin() {
268 let packet = vec![0x1e, 0x00, 0x00, 0x00, 0x60, 0x00]; let (header, payload) = NullHeader::from_bytes(&packet).unwrap();
272
273 assert_eq!(header.family_raw_le(), 30);
274 assert_eq!(header.address_family(), AddressFamily::Inet6Darwin);
275 assert!(header.address_family().is_ipv6());
276 assert_eq!(header.protocol(), EtherProto::IPV6);
277 assert_eq!(payload.len(), 2);
278 }
279
280 #[test]
281 fn test_null_header_ipv6_linux() {
282 let packet = vec![0x0a, 0x00, 0x00, 0x00];
284
285 let (header, _payload) = NullHeader::from_bytes(&packet).unwrap();
286
287 assert_eq!(header.family_raw_le(), 10);
288 assert_eq!(header.address_family(), AddressFamily::Inet6Linux);
289 assert!(header.address_family().is_ipv6());
290 assert_eq!(header.protocol(), EtherProto::IPV6);
291 }
292
293 #[test]
294 fn test_null_header_ipv6_freebsd() {
295 let packet = vec![0x1c, 0x00, 0x00, 0x00];
297
298 let (header, _payload) = NullHeader::from_bytes(&packet).unwrap();
299
300 assert_eq!(header.family_raw_le(), 28);
301 assert_eq!(header.address_family(), AddressFamily::Inet6FreeBsd);
302 assert!(header.address_family().is_ipv6());
303 }
304
305 #[test]
306 fn test_null_header_ipv6_openbsd() {
307 let packet = vec![0x18, 0x00, 0x00, 0x00];
309
310 let (header, _payload) = NullHeader::from_bytes(&packet).unwrap();
311
312 assert_eq!(header.family_raw_le(), 24);
313 assert_eq!(header.address_family(), AddressFamily::Inet6OpenBsd);
314 assert!(header.address_family().is_ipv6());
315 }
316
317 #[test]
318 fn test_null_header_ipv4_be() {
319 let packet = vec![0x00, 0x00, 0x00, 0x02];
321
322 let (header, _payload) = NullHeader::from_bytes(&packet).unwrap();
323
324 assert_eq!(header.address_family(), AddressFamily::Inet);
326 assert_eq!(header.protocol(), EtherProto::IPV4);
327 }
328
329 #[test]
330 fn test_null_header_unknown() {
331 let packet = vec![0xff, 0x00, 0x00, 0x00];
333
334 let (header, _payload) = NullHeader::from_bytes(&packet).unwrap();
335
336 assert!(matches!(
337 header.address_family(),
338 AddressFamily::Unknown(255)
339 ));
340 assert_eq!(header.protocol(), EtherProto::from(0u16));
341 }
342
343 #[test]
344 fn test_null_header_too_short() {
345 let packet = vec![0x02, 0x00, 0x00]; let result = NullHeader::from_bytes(&packet);
348 assert!(result.is_err());
349 }
350
351 #[test]
352 fn test_null_header_display() {
353 let packet = vec![0x02, 0x00, 0x00, 0x00];
354 let (header, _) = NullHeader::from_bytes(&packet).unwrap();
355
356 let display = format!("{}", header);
357 assert!(display.contains("Null"));
358 assert!(display.contains("family="));
359 assert!(display.contains("AF_INET"));
360 }
361
362 #[test]
363 fn test_address_family_display() {
364 assert_eq!(format!("{}", AddressFamily::Inet), "AF_INET");
365 assert_eq!(format!("{}", AddressFamily::Inet6Linux), "AF_INET6 (Linux)");
366 assert_eq!(
367 format!("{}", AddressFamily::Inet6Darwin),
368 "AF_INET6 (Darwin)"
369 );
370 assert_eq!(format!("{}", AddressFamily::Unknown(99)), "Unknown(99)");
371 }
372
373 #[test]
374 fn test_packet_header_trait() {
375 let packet = vec![0x02, 0x00, 0x00, 0x00];
376 let (header, _) = NullHeader::from_bytes(&packet).unwrap();
377
378 assert_eq!(NullHeader::NAME, "Null/Loopback");
379 assert_eq!(header.inner_type(), EtherProto::IPV4);
380 }
381}