1use core::fmt;
62use std::fmt::{Display, Formatter};
63use std::net::Ipv4Addr;
64use std::ops::Deref;
65use zerocopy::byteorder::{BigEndian, U16};
66use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
67
68use crate::packet::ether::EthAddr;
69use crate::packet::{HeaderParser, PacketHeader};
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, FromBytes, IntoBytes, Immutable, KnownLayout)]
73#[repr(transparent)]
74pub struct ArpHardwareType(pub U16<BigEndian>);
75
76impl ArpHardwareType {
77 pub const ETHERNET: ArpHardwareType = ArpHardwareType(U16::new(1)); pub const EXPERIMENTAL_ETHERNET: ArpHardwareType = ArpHardwareType(U16::new(2)); pub const AX25: ArpHardwareType = ArpHardwareType(U16::new(3)); pub const PROTEON_TOKEN_RING: ArpHardwareType = ArpHardwareType(U16::new(4)); pub const CHAOS: ArpHardwareType = ArpHardwareType(U16::new(5)); pub const IEEE802: ArpHardwareType = ArpHardwareType(U16::new(6)); pub const ARCNET: ArpHardwareType = ArpHardwareType(U16::new(7)); pub const HYPERCHANNEL: ArpHardwareType = ArpHardwareType(U16::new(8)); pub const LANSTAR: ArpHardwareType = ArpHardwareType(U16::new(9)); pub const AUTONET: ArpHardwareType = ArpHardwareType(U16::new(10)); pub const LOCALTALK: ArpHardwareType = ArpHardwareType(U16::new(11)); pub const LOCALNET: ArpHardwareType = ArpHardwareType(U16::new(12)); pub const ULTRA_LINK: ArpHardwareType = ArpHardwareType(U16::new(13)); pub const SMDS: ArpHardwareType = ArpHardwareType(U16::new(14)); pub const FRAME_RELAY: ArpHardwareType = ArpHardwareType(U16::new(15)); pub const ATM: ArpHardwareType = ArpHardwareType(U16::new(16)); pub const HDLC: ArpHardwareType = ArpHardwareType(U16::new(17)); pub const FIBRE_CHANNEL: ArpHardwareType = ArpHardwareType(U16::new(18)); pub const ATM_2: ArpHardwareType = ArpHardwareType(U16::new(19)); pub const SERIAL_LINE: ArpHardwareType = ArpHardwareType(U16::new(20)); #[inline]
99 pub fn value(&self) -> u16 {
100 self.0.get()
101 }
102}
103
104impl Display for ArpHardwareType {
105 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
106 let name = match *self {
107 ArpHardwareType::ETHERNET => "ethernet",
108 ArpHardwareType::EXPERIMENTAL_ETHERNET => "exp-ethernet",
109 ArpHardwareType::AX25 => "ax25",
110 ArpHardwareType::PROTEON_TOKEN_RING => "token-ring",
111 ArpHardwareType::CHAOS => "chaos",
112 ArpHardwareType::IEEE802 => "ieee802",
113 ArpHardwareType::ARCNET => "arcnet",
114 ArpHardwareType::HYPERCHANNEL => "hyperchannel",
115 ArpHardwareType::LANSTAR => "lanstar",
116 ArpHardwareType::AUTONET => "autonet",
117 ArpHardwareType::LOCALTALK => "localtalk",
118 ArpHardwareType::LOCALNET => "localnet",
119 ArpHardwareType::ULTRA_LINK => "ultra-link",
120 ArpHardwareType::SMDS => "smds",
121 ArpHardwareType::FRAME_RELAY => "frame-relay",
122 ArpHardwareType::ATM => "atm",
123 ArpHardwareType::HDLC => "hdlc",
124 ArpHardwareType::FIBRE_CHANNEL => "fibre-channel",
125 ArpHardwareType::ATM_2 => "atm2",
126 ArpHardwareType::SERIAL_LINE => "serial-line",
127 _ => return write!(f, "unknown({})", self.value()),
128 };
129 write!(f, "{}", name)
130 }
131}
132
133#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, FromBytes, IntoBytes, Immutable, KnownLayout)]
135#[repr(transparent)]
136pub struct ArpProtocolType(pub U16<BigEndian>);
137
138impl ArpProtocolType {
139 pub const IPV4: ArpProtocolType = ArpProtocolType(U16::new(0x0800)); #[inline]
142 pub fn value(&self) -> u16 {
143 self.0.get()
144 }
145}
146
147impl Display for ArpProtocolType {
148 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
149 match *self {
150 ArpProtocolType::IPV4 => write!(f, "ipv4"),
151 _ => write!(f, "0x{:04x}", self.value()),
152 }
153 }
154}
155
156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, FromBytes, IntoBytes, Immutable, KnownLayout)]
158#[repr(transparent)]
159pub struct ArpOperation(pub U16<BigEndian>);
160
161impl ArpOperation {
162 pub const REQUEST: ArpOperation = ArpOperation(U16::new(1)); pub const REPLY: ArpOperation = ArpOperation(U16::new(2)); pub const RARP_REQUEST: ArpOperation = ArpOperation(U16::new(3)); pub const RARP_REPLY: ArpOperation = ArpOperation(U16::new(4)); pub const DRARP_REQUEST: ArpOperation = ArpOperation(U16::new(5)); pub const DRARP_REPLY: ArpOperation = ArpOperation(U16::new(6)); pub const DRARP_ERROR: ArpOperation = ArpOperation(U16::new(7)); pub const INARP_REQUEST: ArpOperation = ArpOperation(U16::new(8)); pub const INARP_REPLY: ArpOperation = ArpOperation(U16::new(9)); pub const ARP_NAK: ArpOperation = ArpOperation(U16::new(10)); #[inline]
174 pub fn value(&self) -> u16 {
175 self.0.get()
176 }
177}
178
179impl Display for ArpOperation {
180 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
181 let name = match *self {
182 ArpOperation::REQUEST => "request",
183 ArpOperation::REPLY => "reply",
184 ArpOperation::RARP_REQUEST => "rarp-request",
185 ArpOperation::RARP_REPLY => "rarp-reply",
186 ArpOperation::DRARP_REQUEST => "drarp-request",
187 ArpOperation::DRARP_REPLY => "drarp-reply",
188 ArpOperation::DRARP_ERROR => "drarp-error",
189 ArpOperation::INARP_REQUEST => "inarp-request",
190 ArpOperation::INARP_REPLY => "inarp-reply",
191 ArpOperation::ARP_NAK => "arp-nak",
192 _ => return write!(f, "unknown({})", self.value()),
193 };
194 write!(f, "{}", name)
195 }
196}
197
198#[repr(C, packed)]
204#[derive(FromBytes, IntoBytes, Unaligned, Immutable, KnownLayout, Debug, Clone, Copy)]
205pub struct ArpHeader {
206 htype: ArpHardwareType, ptype: ArpProtocolType, hlen: u8, plen: u8, oper: ArpOperation, }
212
213impl ArpHeader {
214 #[inline]
216 pub fn hardware_type(&self) -> ArpHardwareType {
217 self.htype
218 }
219
220 #[inline]
222 pub fn protocol_type(&self) -> ArpProtocolType {
223 self.ptype
224 }
225
226 #[inline]
228 pub fn hardware_len(&self) -> u8 {
229 self.hlen
230 }
231
232 #[inline]
234 pub fn protocol_len(&self) -> u8 {
235 self.plen
236 }
237
238 #[inline]
240 pub fn operation(&self) -> ArpOperation {
241 self.oper
242 }
243
244 #[inline]
246 fn addresses_len(&self) -> usize {
247 2 * (self.hlen as usize + self.plen as usize)
249 }
250
251 #[inline]
253 fn is_valid(&self) -> bool {
254 self.hlen > 0 && self.plen > 0
257 }
258
259 #[inline]
261 pub fn is_eth_ipv4(&self) -> bool {
262 self.htype == ArpHardwareType::ETHERNET
263 && self.ptype == ArpProtocolType::IPV4
264 && self.hlen == 6
265 && self.plen == 4
266 }
267}
268
269impl PacketHeader for ArpHeader {
270 const NAME: &'static str = "ArpHeader";
271 type InnerType = ();
272
273 #[inline]
274 fn inner_type(&self) -> Self::InnerType {}
275
276 #[inline]
277 fn total_len(&self, _buf: &[u8]) -> usize {
278 Self::FIXED_LEN + self.addresses_len()
279 }
280
281 #[inline]
282 fn is_valid(&self) -> bool {
283 self.is_valid()
284 }
285}
286
287impl HeaderParser for ArpHeader {
288 type Output<'a> = ArpHeaderFull<'a>;
289
290 #[inline]
291 fn into_view<'a>(header: &'a Self, addresses: &'a [u8]) -> Self::Output<'a> {
292 ArpHeaderFull { header, addresses }
293 }
294}
295
296#[derive(Debug, Clone)]
301pub struct ArpHeaderFull<'a> {
302 pub header: &'a ArpHeader,
303 pub addresses: &'a [u8],
304}
305
306impl<'a> ArpHeaderFull<'a> {
307 #[inline]
309 pub fn hardware_type(&self) -> ArpHardwareType {
310 self.header.hardware_type()
311 }
312
313 #[inline]
315 pub fn protocol_type(&self) -> ArpProtocolType {
316 self.header.protocol_type()
317 }
318
319 #[inline]
321 pub fn hardware_len(&self) -> u8 {
322 self.header.hardware_len()
323 }
324
325 #[inline]
327 pub fn protocol_len(&self) -> u8 {
328 self.header.protocol_len()
329 }
330
331 #[inline]
333 pub fn operation(&self) -> ArpOperation {
334 self.header.operation()
335 }
336
337 #[inline]
339 pub fn is_eth_ipv4(&self) -> bool {
340 self.header.is_eth_ipv4()
341 }
342
343 #[inline]
345 pub fn sender_hw_addr_raw(&self) -> &[u8] {
346 let hlen = self.hardware_len() as usize;
347 &self.addresses[0..hlen]
348 }
349
350 #[inline]
352 pub fn sender_proto_addr_raw(&self) -> &[u8] {
353 let hlen = self.hardware_len() as usize;
354 let plen = self.protocol_len() as usize;
355 &self.addresses[hlen..hlen + plen]
356 }
357
358 #[inline]
360 pub fn target_hw_addr_raw(&self) -> &[u8] {
361 let hlen = self.hardware_len() as usize;
362 let plen = self.protocol_len() as usize;
363 &self.addresses[hlen + plen..hlen + plen + hlen]
364 }
365
366 #[inline]
368 pub fn target_proto_addr_raw(&self) -> &[u8] {
369 let hlen = self.hardware_len() as usize;
370 let plen = self.protocol_len() as usize;
371 &self.addresses[hlen + plen + hlen..]
372 }
373
374 #[inline]
376 pub fn sender_hw_addr(&self) -> Option<&EthAddr> {
377 if self.is_eth_ipv4() {
378 zerocopy::Ref::<_, EthAddr>::from_prefix(self.sender_hw_addr_raw())
379 .ok()
380 .map(|(r, _)| zerocopy::Ref::into_ref(r))
381 } else {
382 None
383 }
384 }
385
386 #[inline]
388 pub fn sender_proto_addr(&self) -> Option<[u8; 4]> {
389 if self.is_eth_ipv4() {
390 self.sender_proto_addr_raw().try_into().ok()
391 } else {
392 None
393 }
394 }
395
396 #[inline]
398 pub fn sender_ipv4(&self) -> Option<Ipv4Addr> {
399 self.sender_proto_addr().map(Ipv4Addr::from)
400 }
401
402 #[inline]
404 pub fn target_hw_addr(&self) -> Option<&EthAddr> {
405 if self.is_eth_ipv4() {
406 zerocopy::Ref::<_, EthAddr>::from_prefix(self.target_hw_addr_raw())
407 .ok()
408 .map(|(r, _)| zerocopy::Ref::into_ref(r))
409 } else {
410 None
411 }
412 }
413
414 #[inline]
416 pub fn target_proto_addr(&self) -> Option<[u8; 4]> {
417 if self.is_eth_ipv4() {
418 self.target_proto_addr_raw().try_into().ok()
419 } else {
420 None
421 }
422 }
423
424 #[inline]
426 pub fn target_ipv4(&self) -> Option<Ipv4Addr> {
427 self.target_proto_addr().map(Ipv4Addr::from)
428 }
429}
430
431impl Deref for ArpHeaderFull<'_> {
432 type Target = ArpHeader;
433
434 #[inline]
435 fn deref(&self) -> &Self::Target {
436 self.header
437 }
438}
439
440impl Display for ArpHeaderFull<'_> {
441 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
442 if self.is_eth_ipv4() {
443 if let (Some(sha), Some(spa), Some(tha), Some(tpa)) = (
445 self.sender_hw_addr(),
446 self.sender_ipv4(),
447 self.target_hw_addr(),
448 self.target_ipv4(),
449 ) {
450 write!(
451 f,
452 "ARP {} {} -> {} ({}): {} -> {}",
453 self.operation(),
454 sha,
455 tha,
456 if self.operation() == ArpOperation::REQUEST {
457 "who-has"
458 } else {
459 "is-at"
460 },
461 spa,
462 tpa
463 )
464 } else {
465 write!(f, "ARP {} (invalid)", self.operation())
466 }
467 } else {
468 write!(
470 f,
471 "ARP {} htype={} ptype={} hlen={} plen={}",
472 self.operation(),
473 self.hardware_type(),
474 self.protocol_type(),
475 self.hardware_len(),
476 self.protocol_len()
477 )
478 }
479 }
480}
481
482#[cfg(test)]
483mod tests {
484 use super::*;
485 use std::str::FromStr;
486
487 #[test]
488 fn test_arp_request_eth_ipv4() {
489 let packet = vec![
491 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 192, 168, 1, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192, 168, 1, 1, ];
501
502 let (arp, remaining) = ArpHeader::from_bytes(&packet).expect("Failed to parse ARP");
503
504 assert_eq!(remaining.len(), 0);
505 assert_eq!(arp.hardware_type(), ArpHardwareType::ETHERNET);
506 assert_eq!(arp.protocol_type(), ArpProtocolType::IPV4);
507 assert_eq!(arp.hardware_len(), 6);
508 assert_eq!(arp.protocol_len(), 4);
509 assert_eq!(arp.operation(), ArpOperation::REQUEST);
510 assert!(arp.is_eth_ipv4());
511
512 assert_eq!(
514 arp.sender_hw_addr().unwrap().to_string(),
515 "aa:bb:cc:dd:ee:ff"
516 );
517 assert_eq!(arp.sender_proto_addr().unwrap(), [192, 168, 1, 2]);
518 assert_eq!(arp.sender_ipv4().unwrap(), Ipv4Addr::new(192, 168, 1, 2));
519
520 assert_eq!(
521 arp.target_hw_addr().unwrap().to_string(),
522 "00:00:00:00:00:00"
523 );
524 assert_eq!(arp.target_proto_addr().unwrap(), [192, 168, 1, 1]);
525 assert_eq!(arp.target_ipv4().unwrap(), Ipv4Addr::new(192, 168, 1, 1));
526 }
527
528 #[test]
529 fn test_arp_reply_eth_ipv4() {
530 let packet = vec![
532 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 192, 168, 1, 1, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 192, 168, 1, 2, ];
542
543 let (arp, remaining) = ArpHeader::from_bytes(&packet).expect("Failed to parse ARP reply");
544
545 assert_eq!(remaining.len(), 0);
546 assert_eq!(arp.operation(), ArpOperation::REPLY);
547 assert!(arp.is_eth_ipv4());
548
549 assert_eq!(
550 arp.sender_hw_addr().unwrap().to_string(),
551 "11:22:33:44:55:66"
552 );
553 assert_eq!(arp.sender_proto_addr().unwrap(), [192, 168, 1, 1]);
554 }
555
556 #[test]
557 fn test_arp_packet_too_short() {
558 let short_packet = vec![0x00, 0x01, 0x08, 0x00]; let result = ArpHeader::from_bytes(&short_packet);
561 assert!(result.is_err());
562 }
563
564 #[test]
565 fn test_arp_invalid_lengths() {
566 let packet = vec![
568 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, ];
574
575 let result = ArpHeader::from_bytes(&packet);
576 assert!(result.is_err());
577 }
578
579 #[test]
580 fn test_arp_display() {
581 let packet = vec![
582 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
583 192, 168, 1, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192, 168, 1, 1,
584 ];
585
586 let (arp, _) = ArpHeader::from_bytes(&packet).unwrap();
587 let display_str = format!("{}", arp);
588
589 assert!(display_str.contains("request"));
590 assert!(display_str.contains("aa:bb:cc:dd:ee:ff"));
591 }
592
593 #[test]
594 fn test_arp_operation_display() {
595 assert_eq!(format!("{}", ArpOperation::REQUEST), "request");
596 assert_eq!(format!("{}", ArpOperation::REPLY), "reply");
597 assert_eq!(format!("{}", ArpOperation::RARP_REQUEST), "rarp-request");
598 assert_eq!(format!("{}", ArpOperation::RARP_REPLY), "rarp-reply");
599 assert_eq!(format!("{}", ArpOperation::ARP_NAK), "arp-nak");
600 }
601
602 #[test]
603 fn test_arp_hardware_type_display() {
604 assert_eq!(format!("{}", ArpHardwareType::ETHERNET), "ethernet");
605 assert_eq!(format!("{}", ArpHardwareType::IEEE802), "ieee802");
606 assert_eq!(format!("{}", ArpHardwareType::FRAME_RELAY), "frame-relay");
607 assert_eq!(
608 format!("{}", ArpHardwareType(U16::new(9999))),
609 "unknown(9999)"
610 );
611 }
612
613 #[test]
614 fn test_arp_protocol_type_display() {
615 assert_eq!(format!("{}", ArpProtocolType::IPV4), "ipv4");
616 assert_eq!(format!("{}", ArpProtocolType(U16::new(0x1234))), "0x1234");
617 }
618
619 #[test]
620 fn test_arp_with_payload() {
621 let mut packet = vec![
622 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
623 192, 168, 1, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192, 168, 1, 1,
624 ];
625
626 packet.extend_from_slice(b"extra data");
628
629 let (arp, remaining) = ArpHeader::from_bytes(&packet).unwrap();
630
631 assert_eq!(arp.operation(), ArpOperation::REQUEST);
632 assert_eq!(remaining, b"extra data");
633 }
634
635 #[test]
636 fn test_arp_rarp_request() {
637 let packet = vec![
638 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x03, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, ];
648
649 let (arp, _) = ArpHeader::from_bytes(&packet).unwrap();
650 assert_eq!(arp.operation(), ArpOperation::RARP_REQUEST);
651 }
652
653 #[test]
654 fn test_arp_gratuitous() {
655 let packet = vec![
657 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
658 192, 168, 1, 100, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 192, 168, 1, 100, ];
662
663 let (arp, _) = ArpHeader::from_bytes(&packet).unwrap();
664
665 assert_eq!(arp.sender_ipv4().unwrap(), Ipv4Addr::new(192, 168, 1, 100));
667 assert_eq!(arp.sender_ipv4().unwrap(), arp.target_ipv4().unwrap());
668 assert_eq!(arp.operation(), ArpOperation::REQUEST);
669 }
670
671 #[test]
672 fn test_arp_probe() {
673 let packet = vec![
675 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0,
676 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192, 168, 1, 100, ];
680
681 let (arp, _) = ArpHeader::from_bytes(&packet).unwrap();
682
683 assert_eq!(arp.sender_ipv4().unwrap(), Ipv4Addr::new(0, 0, 0, 0));
684 assert_eq!(arp.target_ipv4().unwrap(), Ipv4Addr::new(192, 168, 1, 100));
685 }
686
687 #[test]
688 fn test_arp_real_world_request() {
689 let packet = vec![
692 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x08, 0x00, 0x27, 0x12, 0x34, 0x56, 10, 0, 0, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 10, 0, 0, 1, ];
701
702 let (arp, remaining) = ArpHeader::from_bytes(&packet).unwrap();
703
704 assert_eq!(remaining.len(), 0);
705 assert_eq!(arp.sender_ipv4().unwrap(), Ipv4Addr::new(10, 0, 0, 2));
706 assert_eq!(arp.target_ipv4().unwrap(), Ipv4Addr::new(10, 0, 0, 1));
707 assert_eq!(
708 arp.sender_hw_addr().unwrap(),
709 &EthAddr::from_str("08:00:27:12:34:56").unwrap()
710 );
711 }
712
713 #[test]
714 fn test_arp_real_world_reply() {
715 let packet = vec![
718 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x52, 0x54, 0x00, 0x12, 0x34, 0x56, 10, 0, 0, 1, 0x08, 0x00, 0x27, 0x12, 0x34, 0x56, 10, 0, 0, 2, ];
727
728 let (arp, _) = ArpHeader::from_bytes(&packet).unwrap();
729
730 assert_eq!(arp.operation(), ArpOperation::REPLY);
731 assert_eq!(
732 arp.sender_hw_addr().unwrap(),
733 &EthAddr::from_str("52:54:00:12:34:56").unwrap()
734 );
735 assert_eq!(arp.sender_ipv4().unwrap(), Ipv4Addr::new(10, 0, 0, 1));
736 }
737
738 #[test]
739 fn test_arp_from_bytes_multiple_packets() {
740 let test_cases = vec![
742 (
743 vec![
744 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
745 0xff, 192, 168, 1, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192, 168, 1, 1,
746 ],
747 ArpOperation::REQUEST,
748 ),
749 (
750 vec![
751 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x11, 0x22, 0x33, 0x44, 0x55,
752 0x66, 192, 168, 1, 1, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 192, 168, 1, 2,
753 ],
754 ArpOperation::REPLY,
755 ),
756 ];
757
758 for (packet, expected_op) in test_cases {
759 let (arp, _) = ArpHeader::from_bytes(&packet).unwrap();
760 assert_eq!(arp.operation(), expected_op);
761 assert!(arp.is_eth_ipv4());
762 }
763 }
764
765 #[test]
766 fn test_arp_size_constants() {
767 assert_eq!(
768 std::mem::size_of::<ArpHeader>(),
769 8,
770 "ARP fixed header should be 8 bytes"
771 );
772 assert_eq!(ArpHeader::FIXED_LEN, 8);
773 }
774
775 #[test]
776 fn test_arp_packet_boundary_conditions() {
777 let packet = vec![
779 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
780 192, 168, 1, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192, 168, 1, 1,
781 ];
782
783 assert_eq!(packet.len(), 28);
784 let (arp, remaining) = ArpHeader::from_bytes(&packet).unwrap();
785 assert_eq!(remaining.len(), 0);
786 assert!(arp.is_eth_ipv4());
787 }
788
789 #[test]
790 fn test_arp_generic_parsing() {
791 let mut packet = vec![
793 0x00, 0x01, 0x08, 0x00, 0x08, 0x04, 0x00, 0x01, ];
799
800 packet.extend_from_slice(&[0xAA; 8]); packet.extend_from_slice(&[192, 168, 1, 2]); packet.extend_from_slice(&[0xBB; 8]); packet.extend_from_slice(&[192, 168, 1, 1]); let (arp, remaining) = ArpHeader::from_bytes(&packet).unwrap();
807
808 assert_eq!(remaining.len(), 0);
809 assert_eq!(arp.hardware_len(), 8);
810 assert_eq!(arp.protocol_len(), 4);
811 assert_eq!(arp.operation(), ArpOperation::REQUEST);
812
813 assert!(!arp.is_eth_ipv4());
815
816 assert_eq!(arp.sender_hw_addr_raw().len(), 8);
818 assert_eq!(arp.sender_proto_addr_raw(), &[192, 168, 1, 2]);
819 assert_eq!(arp.target_hw_addr_raw().len(), 8);
820 assert_eq!(arp.target_proto_addr_raw(), &[192, 168, 1, 1]);
821 }
822
823 #[test]
824 fn test_arp_deref() {
825 let packet = vec![
826 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
827 192, 168, 1, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192, 168, 1, 1,
828 ];
829
830 let (arp, _) = ArpHeader::from_bytes(&packet).unwrap();
831
832 assert_eq!(arp.hardware_type(), ArpHardwareType::ETHERNET);
834 assert_eq!(arp.protocol_type(), ArpProtocolType::IPV4);
835 }
836
837 #[test]
838 fn test_arp_zerocopy_parsing() {
839 let packet = vec![
841 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 10, 20, 30, 40, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 50, 60, 70, 80, ];
850
851 let (arp, _) = ArpHeader::from_bytes(&packet).unwrap();
852
853 assert_eq!(
855 arp.sender_hw_addr_raw(),
856 &[0x11, 0x22, 0x33, 0x44, 0x55, 0x66]
857 );
858 assert_eq!(arp.sender_proto_addr_raw(), &[10, 20, 30, 40]);
859 assert_eq!(
860 arp.target_hw_addr_raw(),
861 &[0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]
862 );
863 assert_eq!(arp.target_proto_addr_raw(), &[50, 60, 70, 80]);
864
865 assert!(arp.sender_hw_addr().is_some());
867 assert_eq!(
868 arp.sender_hw_addr().unwrap().to_string(),
869 "11:22:33:44:55:66"
870 );
871
872 assert!(arp.target_hw_addr().is_some());
873 assert_eq!(
874 arp.target_hw_addr().unwrap().to_string(),
875 "aa:bb:cc:dd:ee:ff"
876 );
877
878 assert_eq!(arp.sender_proto_addr().unwrap(), [10, 20, 30, 40]);
880 assert_eq!(arp.target_proto_addr().unwrap(), [50, 60, 70, 80]);
881
882 assert_eq!(arp.sender_ipv4().unwrap(), Ipv4Addr::new(10, 20, 30, 40));
884 assert_eq!(arp.target_ipv4().unwrap(), Ipv4Addr::new(50, 60, 70, 80));
885 }
886
887 #[test]
888 fn test_arp_non_eth_ipv4_returns_none() {
889 let mut packet = vec![
891 0x00, 0x01, 0x08, 0x00, 0x07, 0x04, 0x00, 0x01, ];
897
898 packet.extend_from_slice(&[0xAA; 7]); packet.extend_from_slice(&[192, 168, 1, 2]); packet.extend_from_slice(&[0xBB; 7]); packet.extend_from_slice(&[192, 168, 1, 1]); let (arp, _) = ArpHeader::from_bytes(&packet).unwrap();
905
906 assert!(!arp.is_eth_ipv4());
908
909 assert!(arp.sender_hw_addr().is_none());
911 assert!(arp.target_hw_addr().is_none());
912 assert!(arp.sender_proto_addr().is_none());
913 assert!(arp.target_proto_addr().is_none());
914 assert!(arp.sender_ipv4().is_none());
915 assert!(arp.target_ipv4().is_none());
916
917 assert_eq!(arp.sender_hw_addr_raw().len(), 7);
919 assert_eq!(arp.sender_proto_addr_raw(), &[192, 168, 1, 2]);
920 }
921
922 #[test]
923 fn test_arp_ipv4addr_parsing() {
924 let packet = vec![
926 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
927 192, 168, 1, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192, 168, 1, 1,
928 ];
929
930 let (arp, _) = ArpHeader::from_bytes(&packet).unwrap();
931
932 assert_eq!(
934 arp.sender_ipv4().unwrap(),
935 "192.168.1.2".parse::<Ipv4Addr>().unwrap()
936 );
937 assert_eq!(
938 arp.target_ipv4().unwrap(),
939 "192.168.1.1".parse::<Ipv4Addr>().unwrap()
940 );
941
942 let sender_ip = arp.sender_ipv4().unwrap();
944 assert_eq!(sender_ip.to_string(), "192.168.1.2");
945
946 let target_ip = arp.target_ipv4().unwrap();
947 assert_eq!(target_ip.to_string(), "192.168.1.1");
948 }
949}