1use arrayvec::ArrayVec;
2use err::arp::{ArpHwAddrError, ArpNewError, ArpProtoAddrError};
3
4use crate::*;
5use core::mem::MaybeUninit;
6
7#[derive(Clone)]
9pub struct ArpPacket {
10 pub hw_addr_type: ArpHardwareId,
12
13 pub proto_addr_type: EtherType,
15
16 hw_addr_size: u8,
18
19 proto_addr_size: u8,
21
22 pub operation: ArpOperation,
24
25 sender_hw_addr_buf: [MaybeUninit<u8>; 0xff],
27
28 sender_protocol_addr_buf: [MaybeUninit<u8>; 0xff],
30
31 target_hw_addr_buf: [MaybeUninit<u8>; 0xff],
33
34 target_protocol_addr_buf: [MaybeUninit<u8>; 0xff],
36}
37
38impl ArpPacket {
39 pub const MAX_LEN: usize = 8 + 2 * 255 + 2 * 255;
45
46 pub const fn new(
48 hw_addr_type: ArpHardwareId,
49 proto_addr_type: EtherType,
50 operation: ArpOperation,
51 sender_hw_addr: &[u8],
52 sender_protocol_addr: &[u8],
53 target_hw_addr: &[u8],
54 target_protocol_addr: &[u8],
55 ) -> Result<ArpPacket, ArpNewError> {
56 if sender_hw_addr.len() != target_hw_addr.len() {
57 return Err(ArpNewError::HwAddr(ArpHwAddrError::LenNonMatching(
58 sender_hw_addr.len(),
59 target_hw_addr.len(),
60 )));
61 }
62 if sender_protocol_addr.len() != target_protocol_addr.len() {
63 return Err(ArpNewError::ProtoAddr(ArpProtoAddrError::LenNonMatching(
64 sender_protocol_addr.len(),
65 target_protocol_addr.len(),
66 )));
67 }
68 if sender_hw_addr.len() > 255 {
69 return Err(ArpNewError::HwAddr(ArpHwAddrError::LenTooBig(
70 sender_hw_addr.len(),
71 )));
72 }
73 if sender_protocol_addr.len() > 255 {
74 return Err(ArpNewError::ProtoAddr(ArpProtoAddrError::LenTooBig(
75 sender_protocol_addr.len(),
76 )));
77 }
78 Ok(ArpPacket {
79 hw_addr_type,
80 proto_addr_type,
81 hw_addr_size: sender_hw_addr.len() as u8,
83 proto_addr_size: sender_protocol_addr.len() as u8,
85 operation,
86 sender_hw_addr_buf: {
87 let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
88 unsafe {
92 core::ptr::copy_nonoverlapping(
93 sender_hw_addr.as_ptr(),
94 buf.as_mut_ptr() as *mut u8,
95 sender_hw_addr.len(),
96 );
97 }
98 buf
99 },
100 sender_protocol_addr_buf: {
101 let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
102 unsafe {
106 core::ptr::copy_nonoverlapping(
107 sender_protocol_addr.as_ptr(),
108 buf.as_mut_ptr() as *mut u8,
109 sender_protocol_addr.len(),
110 );
111 }
112 buf
113 },
114 target_hw_addr_buf: {
115 let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
116 unsafe {
120 core::ptr::copy_nonoverlapping(
121 target_hw_addr.as_ptr(),
122 buf.as_mut_ptr() as *mut u8,
123 target_hw_addr.len(),
124 );
125 }
126 buf
127 },
128 target_protocol_addr_buf: {
129 let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
130 unsafe {
134 core::ptr::copy_nonoverlapping(
135 target_protocol_addr.as_ptr(),
136 buf.as_mut_ptr() as *mut u8,
137 target_protocol_addr.len(),
138 );
139 }
140 buf
141 },
142 })
143 }
144
145 pub const unsafe fn new_unchecked(
165 hw_addr_type: ArpHardwareId,
166 proto_addr_type: EtherType,
167 operation: ArpOperation,
168 sender_hw_addr: &[u8],
169 sender_protocol_addr: &[u8],
170 target_hw_addr: &[u8],
171 target_protocol_addr: &[u8],
172 ) -> ArpPacket {
173 debug_assert!(sender_hw_addr.len() == target_hw_addr.len());
174 debug_assert!(sender_protocol_addr.len() == target_protocol_addr.len());
175 debug_assert!(sender_hw_addr.len() <= 255);
176 debug_assert!(sender_protocol_addr.len() <= 255);
177
178 ArpPacket {
179 hw_addr_type,
180 proto_addr_type,
181 hw_addr_size: sender_hw_addr.len() as u8,
183 proto_addr_size: sender_protocol_addr.len() as u8,
185 operation,
186 sender_hw_addr_buf: {
187 let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
188 unsafe {
192 core::ptr::copy_nonoverlapping(
193 sender_hw_addr.as_ptr(),
194 buf.as_mut_ptr() as *mut u8,
195 sender_hw_addr.len(),
196 );
197 }
198 buf
199 },
200 sender_protocol_addr_buf: {
201 let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
202 unsafe {
206 core::ptr::copy_nonoverlapping(
207 sender_protocol_addr.as_ptr(),
208 buf.as_mut_ptr() as *mut u8,
209 sender_protocol_addr.len(),
210 );
211 }
212 buf
213 },
214 target_hw_addr_buf: {
215 let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
216 unsafe {
220 core::ptr::copy_nonoverlapping(
221 target_hw_addr.as_ptr(),
222 buf.as_mut_ptr() as *mut u8,
223 target_hw_addr.len(),
224 );
225 }
226 buf
227 },
228 target_protocol_addr_buf: {
229 let mut buf: [MaybeUninit<u8>; 255] = [const { MaybeUninit::uninit() }; 255];
230 unsafe {
234 core::ptr::copy_nonoverlapping(
235 target_protocol_addr.as_ptr(),
236 buf.as_mut_ptr() as *mut u8,
237 target_protocol_addr.len(),
238 );
239 }
240 buf
241 },
242 }
243 }
244
245 pub fn from_slice(slice: &[u8]) -> Result<ArpPacket, err::LenError> {
247 ArpPacketSlice::from_slice(slice).map(|v| v.to_packet())
248 }
249
250 #[inline]
252 pub const fn hw_addr_size(&self) -> u8 {
253 self.hw_addr_size
254 }
255
256 #[inline]
258 pub const fn protocol_addr_size(&self) -> u8 {
259 self.proto_addr_size
260 }
261
262 #[inline]
264 pub const fn sender_hw_addr(&self) -> &[u8] {
265 unsafe {
266 core::slice::from_raw_parts(
267 self.sender_hw_addr_buf.as_ptr() as *const u8,
268 self.hw_addr_size as usize,
269 )
270 }
271 }
272
273 #[inline]
275 pub const fn sender_protocol_addr(&self) -> &[u8] {
276 unsafe {
277 core::slice::from_raw_parts(
278 self.sender_protocol_addr_buf.as_ptr() as *const u8,
279 self.proto_addr_size as usize,
280 )
281 }
282 }
283
284 #[inline]
286 pub const fn target_hw_addr(&self) -> &[u8] {
287 unsafe {
288 core::slice::from_raw_parts(
289 self.target_hw_addr_buf.as_ptr() as *const u8,
290 self.hw_addr_size as usize,
291 )
292 }
293 }
294
295 #[inline]
297 pub const fn target_protocol_addr(&self) -> &[u8] {
298 unsafe {
299 core::slice::from_raw_parts(
300 self.target_protocol_addr_buf.as_ptr() as *const u8,
301 self.proto_addr_size as usize,
302 )
303 }
304 }
305
306 #[inline]
308 pub const fn set_hw_addrs(
309 &mut self,
310 sender_hw_addr: &[u8],
311 target_hw_addr: &[u8],
312 ) -> Result<(), ArpHwAddrError> {
313 if sender_hw_addr.len() != target_hw_addr.len() {
314 return Err(ArpHwAddrError::LenNonMatching(
315 sender_hw_addr.len(),
316 target_hw_addr.len(),
317 ));
318 }
319 if sender_hw_addr.len() > 255 {
320 return Err(ArpHwAddrError::LenTooBig(sender_hw_addr.len()));
321 }
322 {
323 unsafe {
327 core::ptr::copy_nonoverlapping(
328 sender_hw_addr.as_ptr(),
329 self.sender_hw_addr_buf.as_mut_ptr() as *mut u8,
330 sender_hw_addr.len(),
331 );
332 }
333 }
334 {
335 unsafe {
339 core::ptr::copy_nonoverlapping(
340 target_hw_addr.as_ptr(),
341 self.target_hw_addr_buf.as_mut_ptr() as *mut u8,
342 target_hw_addr.len(),
343 );
344 }
345 }
346 self.hw_addr_size = sender_hw_addr.len() as u8;
347 Ok(())
348 }
349
350 #[inline]
352 pub const fn set_protocol_addrs(
353 &mut self,
354 sender_protocol_addr: &[u8],
355 target_protocol_addr: &[u8],
356 ) -> Result<(), ArpProtoAddrError> {
357 if sender_protocol_addr.len() != target_protocol_addr.len() {
358 return Err(ArpProtoAddrError::LenNonMatching(
359 sender_protocol_addr.len(),
360 target_protocol_addr.len(),
361 ));
362 }
363 if sender_protocol_addr.len() > 255 {
364 return Err(ArpProtoAddrError::LenTooBig(sender_protocol_addr.len()));
365 }
366 {
367 unsafe {
371 core::ptr::copy_nonoverlapping(
372 sender_protocol_addr.as_ptr(),
373 self.sender_protocol_addr_buf.as_mut_ptr() as *mut u8,
374 sender_protocol_addr.len(),
375 );
376 }
377 }
378 {
379 unsafe {
383 core::ptr::copy_nonoverlapping(
384 target_protocol_addr.as_ptr(),
385 self.target_protocol_addr_buf.as_mut_ptr() as *mut u8,
386 target_protocol_addr.len(),
387 );
388 }
389 }
390 self.proto_addr_size = sender_protocol_addr.len() as u8;
391 Ok(())
392 }
393
394 #[inline]
396 pub fn packet_len(&self) -> usize {
397 8 + usize::from(self.hw_addr_size) * 2 + usize::from(self.proto_addr_size) * 2
398 }
399
400 #[inline]
402 pub fn to_bytes(&self) -> ArrayVec<u8, { ArpPacket::MAX_LEN }> {
403 let hw_addr_type = self.hw_addr_type.0.to_be_bytes();
404 let proto_addr_type = self.proto_addr_type.0.to_be_bytes();
405 let operation = self.operation.0.to_be_bytes();
406 let mut result = ArrayVec::<u8, { ArpPacket::MAX_LEN }>::new_const();
407 result.extend([
408 hw_addr_type[0],
409 hw_addr_type[1],
410 proto_addr_type[0],
411 proto_addr_type[1],
412 self.hw_addr_size,
413 self.proto_addr_size,
414 operation[0],
415 operation[1],
416 ]);
417 result.try_extend_from_slice(self.sender_hw_addr()).unwrap();
418 result
419 .try_extend_from_slice(self.sender_protocol_addr())
420 .unwrap();
421 result.try_extend_from_slice(self.target_hw_addr()).unwrap();
422 result
423 .try_extend_from_slice(self.target_protocol_addr())
424 .unwrap();
425 result
426 }
427
428 #[cfg(feature = "std")]
430 pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
431 writer.write_all(&self.to_bytes())?;
432 Ok(())
433 }
434
435 #[cfg(feature = "std")]
436 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
437 pub fn read<T: std::io::Read + std::io::Seek + Sized>(
438 reader: &mut T,
439 ) -> Result<ArpPacket, std::io::Error> {
440 let mut start = [0u8; 8];
441 reader.read_exact(&mut start[..])?;
442
443 let mut result = ArpPacket {
444 hw_addr_type: ArpHardwareId(u16::from_be_bytes([start[0], start[1]])),
445 proto_addr_type: EtherType(u16::from_be_bytes([start[2], start[3]])),
446 hw_addr_size: start[4],
447 proto_addr_size: start[5],
448 operation: ArpOperation(u16::from_be_bytes([start[6], start[7]])),
449 sender_hw_addr_buf: [const { MaybeUninit::uninit() }; 255],
450 sender_protocol_addr_buf: [const { MaybeUninit::uninit() }; 255],
451 target_hw_addr_buf: [const { MaybeUninit::uninit() }; 255],
452 target_protocol_addr_buf: [const { MaybeUninit::uninit() }; 255],
453 };
454
455 {
456 let sender_hw_addr_slice = unsafe {
458 core::slice::from_raw_parts_mut(
459 result.sender_hw_addr_buf.as_mut_ptr() as *mut u8,
460 result.hw_addr_size as usize,
461 )
462 };
463 reader.read_exact(sender_hw_addr_slice)?;
464 }
465 {
466 let sender_protocol_addr = unsafe {
468 core::slice::from_raw_parts_mut(
469 result.sender_protocol_addr_buf.as_mut_ptr() as *mut u8,
470 result.proto_addr_size as usize,
471 )
472 };
473 reader.read_exact(sender_protocol_addr)?;
474 }
475 {
476 let target_hw_addr = unsafe {
478 core::slice::from_raw_parts_mut(
479 result.target_hw_addr_buf.as_mut_ptr() as *mut u8,
480 result.hw_addr_size as usize,
481 )
482 };
483 reader.read_exact(target_hw_addr)?;
484 }
485 {
486 let target_protocol_addr = unsafe {
488 core::slice::from_raw_parts_mut(
489 result.target_protocol_addr_buf.as_mut_ptr() as *mut u8,
490 result.proto_addr_size as usize,
491 )
492 };
493 reader.read_exact(target_protocol_addr)?;
494 }
495
496 Ok(result)
497 }
498
499 pub fn try_eth_ipv4(&self) -> Result<ArpEthIpv4Packet, err::arp::ArpEthIpv4FromError> {
502 use err::arp::ArpEthIpv4FromError::*;
503 if self.hw_addr_type != ArpHardwareId::ETHERNET {
504 return Err(NonMatchingHwType(self.hw_addr_type));
505 }
506 if self.proto_addr_type != EtherType::IPV4 {
507 return Err(NonMatchingProtocolType(self.proto_addr_type));
508 }
509 if self.hw_addr_size != 6 {
510 return Err(NonMatchingHwAddrSize(self.hw_addr_size));
511 }
512 if self.proto_addr_size != 4 {
513 return Err(NonMatchingProtoAddrSize(self.proto_addr_size));
514 }
515 Ok(ArpEthIpv4Packet {
516 operation: self.operation,
517 sender_mac: unsafe {
518 [
520 self.sender_hw_addr_buf[0].assume_init(),
521 self.sender_hw_addr_buf[1].assume_init(),
522 self.sender_hw_addr_buf[2].assume_init(),
523 self.sender_hw_addr_buf[3].assume_init(),
524 self.sender_hw_addr_buf[4].assume_init(),
525 self.sender_hw_addr_buf[5].assume_init(),
526 ]
527 },
528 sender_ipv4: unsafe {
529 [
531 self.sender_protocol_addr_buf[0].assume_init(),
532 self.sender_protocol_addr_buf[1].assume_init(),
533 self.sender_protocol_addr_buf[2].assume_init(),
534 self.sender_protocol_addr_buf[3].assume_init(),
535 ]
536 },
537 target_mac: unsafe {
538 [
540 self.target_hw_addr_buf[0].assume_init(),
541 self.target_hw_addr_buf[1].assume_init(),
542 self.target_hw_addr_buf[2].assume_init(),
543 self.target_hw_addr_buf[3].assume_init(),
544 self.target_hw_addr_buf[4].assume_init(),
545 self.target_hw_addr_buf[5].assume_init(),
546 ]
547 },
548 target_ipv4: unsafe {
549 [
551 self.target_protocol_addr_buf[0].assume_init(),
552 self.target_protocol_addr_buf[1].assume_init(),
553 self.target_protocol_addr_buf[2].assume_init(),
554 self.target_protocol_addr_buf[3].assume_init(),
555 ]
556 },
557 })
558 }
559}
560
561impl core::fmt::Debug for ArpPacket {
562 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
563 f.debug_struct("ArpPacket")
564 .field("hw_addr_type", &self.hw_addr_type)
565 .field("proto_addr_type", &self.proto_addr_type)
566 .field("hw_addr_size", &self.hw_addr_size)
567 .field("proto_addr_size", &self.proto_addr_size)
568 .field("operation", &self.operation)
569 .field("sender_hw_addr", &self.sender_hw_addr())
570 .field("sender_protocol_addr", &self.sender_protocol_addr())
571 .field("target_hw_addr", &self.target_hw_addr())
572 .field("target_protocol_addr", &self.target_protocol_addr())
573 .finish()
574 }
575}
576
577impl core::cmp::PartialEq for ArpPacket {
578 fn eq(&self, other: &Self) -> bool {
579 self.hw_addr_type == other.hw_addr_type
580 && self.proto_addr_type == other.proto_addr_type
581 && self.hw_addr_size == other.hw_addr_size
582 && self.proto_addr_size == other.proto_addr_size
583 && self.operation == other.operation
584 && self.sender_hw_addr() == other.sender_hw_addr()
585 && self.sender_protocol_addr() == other.sender_protocol_addr()
586 && self.target_hw_addr() == other.target_hw_addr()
587 && self.target_protocol_addr() == other.target_protocol_addr()
588 }
589}
590
591impl core::cmp::Eq for ArpPacket {}
592
593impl core::hash::Hash for ArpPacket {
594 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
595 self.hw_addr_type.hash(state);
596 self.proto_addr_type.hash(state);
597 self.hw_addr_size.hash(state);
598 self.proto_addr_size.hash(state);
599 self.operation.hash(state);
600 self.sender_hw_addr().hash(state);
601 self.sender_protocol_addr().hash(state);
602 self.target_hw_addr().hash(state);
603 self.target_protocol_addr().hash(state);
604 }
605}
606
607#[cfg(test)]
608mod tests {
609 use crate::{test_gens::*, *};
610 use err::arp::{ArpHwAddrError, ArpNewError, ArpProtoAddrError};
611 use proptest::prelude::*;
612
613 #[test]
614 fn new() {
615 {
617 let actual = ArpPacket::new(
618 ArpHardwareId::ASH,
619 EtherType::PROVIDER_BRIDGING,
620 ArpOperation::REQUEST,
621 &[1, 2, 3],
622 &[4, 5, 6, 7, 8],
623 &[9, 10, 11],
624 &[12, 13, 14, 15, 16],
625 )
626 .unwrap();
627 assert_eq!(3, actual.hw_addr_size());
628 assert_eq!(5, actual.protocol_addr_size());
629 assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
630 assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
631 assert_eq!(ArpOperation::REQUEST, actual.operation);
632 assert_eq!(&[1, 2, 3], actual.sender_hw_addr());
633 assert_eq!(&[4, 5, 6, 7, 8], actual.sender_protocol_addr());
634 assert_eq!(&[9, 10, 11], actual.target_hw_addr());
635 assert_eq!(&[12, 13, 14, 15, 16], actual.target_protocol_addr());
636 }
637
638 {
640 let actual = ArpPacket::new(
641 ArpHardwareId::ASH,
642 EtherType::PROVIDER_BRIDGING,
643 ArpOperation::REQUEST,
644 &[1; 255],
645 &[4, 5, 6, 7, 8],
646 &[2; 255],
647 &[12, 13, 14, 15, 16],
648 )
649 .unwrap();
650 assert_eq!(255, actual.hw_addr_size());
651 assert_eq!(5, actual.protocol_addr_size());
652 assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
653 assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
654 assert_eq!(ArpOperation::REQUEST, actual.operation);
655 assert_eq!(&[1; 255], actual.sender_hw_addr());
656 assert_eq!(&[4, 5, 6, 7, 8], actual.sender_protocol_addr());
657 assert_eq!(&[2; 255], actual.target_hw_addr());
658 assert_eq!(&[12, 13, 14, 15, 16], actual.target_protocol_addr());
659 }
660
661 {
663 let actual = ArpPacket::new(
664 ArpHardwareId::ASH,
665 EtherType::PROVIDER_BRIDGING,
666 ArpOperation::REQUEST,
667 &[3, 4, 5],
668 &[1; 255],
669 &[6, 7, 8],
670 &[2; 255],
671 )
672 .unwrap();
673 assert_eq!(3, actual.hw_addr_size());
674 assert_eq!(255, actual.protocol_addr_size());
675 assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
676 assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
677 assert_eq!(ArpOperation::REQUEST, actual.operation);
678 assert_eq!(&[3, 4, 5], actual.sender_hw_addr());
679 assert_eq!(&[1; 255], actual.sender_protocol_addr());
680 assert_eq!(&[6, 7, 8], actual.target_hw_addr());
681 assert_eq!(&[2; 255], actual.target_protocol_addr());
682 }
683
684 {
686 let actual = ArpPacket::new(
687 ArpHardwareId::ASH,
688 EtherType::PROVIDER_BRIDGING,
689 ArpOperation::REQUEST,
690 &[1, 2, 3],
691 &[],
692 &[4, 5, 6, 7],
693 &[],
694 );
695 assert_eq!(
696 Err(ArpNewError::HwAddr(ArpHwAddrError::LenNonMatching(3, 4))),
697 actual
698 );
699 }
700 {
702 let actual = ArpPacket::new(
703 ArpHardwareId::ASH,
704 EtherType::PROVIDER_BRIDGING,
705 ArpOperation::REQUEST,
706 &[],
707 &[1, 2, 3],
708 &[],
709 &[4, 5, 6, 7],
710 );
711 assert_eq!(
712 Err(ArpNewError::ProtoAddr(ArpProtoAddrError::LenNonMatching(
713 3, 4
714 ))),
715 actual
716 );
717 }
718
719 {
721 let actual = ArpPacket::new(
722 ArpHardwareId::ASH,
723 EtherType::PROVIDER_BRIDGING,
724 ArpOperation::REQUEST,
725 &[0; 256],
726 &[1, 2, 3, 4],
727 &[0; 256],
728 &[5, 6, 7, 8],
729 );
730 assert_eq!(
731 Err(ArpNewError::HwAddr(ArpHwAddrError::LenTooBig(256))),
732 actual
733 );
734 }
735
736 {
738 let actual = ArpPacket::new(
739 ArpHardwareId::ASH,
740 EtherType::PROVIDER_BRIDGING,
741 ArpOperation::REQUEST,
742 &[1, 2, 3, 4],
743 &[0; 256],
744 &[5, 6, 7, 8],
745 &[0; 256],
746 );
747 assert_eq!(
748 Err(ArpNewError::ProtoAddr(ArpProtoAddrError::LenTooBig(256))),
749 actual
750 );
751 }
752 }
753
754 #[test]
755 fn new_unchecked() {
756 {
758 let actual = unsafe {
759 ArpPacket::new_unchecked(
760 ArpHardwareId::ASH,
761 EtherType::PROVIDER_BRIDGING,
762 ArpOperation::REQUEST,
763 &[1, 2, 3],
764 &[4, 5, 6, 7, 8],
765 &[9, 10, 11],
766 &[12, 13, 14, 15, 16],
767 )
768 };
769 assert_eq!(3, actual.hw_addr_size());
770 assert_eq!(5, actual.protocol_addr_size());
771 assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
772 assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
773 assert_eq!(ArpOperation::REQUEST, actual.operation);
774 assert_eq!(&[1, 2, 3], actual.sender_hw_addr());
775 assert_eq!(&[4, 5, 6, 7, 8], actual.sender_protocol_addr());
776 assert_eq!(&[9, 10, 11], actual.target_hw_addr());
777 assert_eq!(&[12, 13, 14, 15, 16], actual.target_protocol_addr());
778 }
779
780 {
782 let actual = unsafe {
783 ArpPacket::new_unchecked(
784 ArpHardwareId::ASH,
785 EtherType::PROVIDER_BRIDGING,
786 ArpOperation::REQUEST,
787 &[0; 255],
788 &[4, 5, 6, 7, 8],
789 &[0; 255],
790 &[12, 13, 14, 15, 16],
791 )
792 };
793 assert_eq!(255, actual.hw_addr_size());
794 assert_eq!(5, actual.protocol_addr_size());
795 assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
796 assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
797 assert_eq!(ArpOperation::REQUEST, actual.operation);
798 assert_eq!(&[0; 255], actual.sender_hw_addr());
799 assert_eq!(&[4, 5, 6, 7, 8], actual.sender_protocol_addr());
800 assert_eq!(&[0; 255], actual.target_hw_addr());
801 assert_eq!(&[12, 13, 14, 15, 16], actual.target_protocol_addr());
802 }
803
804 {
806 let actual = ArpPacket::new(
807 ArpHardwareId::ASH,
808 EtherType::PROVIDER_BRIDGING,
809 ArpOperation::REQUEST,
810 &[1, 2, 3],
811 &[0; 255],
812 &[9, 10, 11],
813 &[0; 255],
814 )
815 .unwrap();
816 assert_eq!(3, actual.hw_addr_size());
817 assert_eq!(255, actual.protocol_addr_size());
818 assert_eq!(ArpHardwareId::ASH, actual.hw_addr_type);
819 assert_eq!(EtherType::PROVIDER_BRIDGING, actual.proto_addr_type);
820 assert_eq!(ArpOperation::REQUEST, actual.operation);
821 assert_eq!(&[1, 2, 3], actual.sender_hw_addr());
822 assert_eq!(&[0; 255], actual.sender_protocol_addr());
823 assert_eq!(&[9, 10, 11], actual.target_hw_addr());
824 assert_eq!(&[0; 255], actual.target_protocol_addr());
825 }
826 }
827
828 proptest! {
829 #[test]
830 fn debug(arp in arp_packet_any()) {
831 use std::format;
832 assert_eq!(
833 format!("{:?}", arp),
834 format!(
835 "ArpPacket {{ hw_addr_type: {:?}, proto_addr_type: {:?}, hw_addr_size: {:?}, proto_addr_size: {:?}, operation: {:?}, sender_hw_addr: {:?}, sender_protocol_addr: {:?}, target_hw_addr: {:?}, target_protocol_addr: {:?} }}",
836 arp.hw_addr_type,
837 arp.proto_addr_type,
838 arp.hw_addr_size(),
839 arp.protocol_addr_size(),
840 arp.operation,
841 arp.sender_hw_addr(),
842 arp.sender_protocol_addr(),
843 arp.target_hw_addr(),
844 arp.target_protocol_addr()
845 )
846 );
847 }
848 }
849
850 proptest! {
851 #[test]
852 fn clone_eq(arp in arp_packet_any()) {
853 assert_eq!(&arp.clone(), &arp);
854 }
855 }
856
857 proptest! {
858 #[test]
859 fn hash(arp in arp_packet_any()) {
860 use core::hash::{Hash, Hasher};
861 use std::collections::hash_map::DefaultHasher;
862
863 let expected_hash = {
864 let mut s = DefaultHasher::new();
865
866 arp.hw_addr_type.hash(&mut s);
867 arp.proto_addr_type.hash(&mut s);
868 arp.hw_addr_size().hash(&mut s);
869 arp.protocol_addr_size().hash(&mut s);
870 arp.operation.hash(&mut s);
871 arp.sender_hw_addr().hash(&mut s);
872 arp.sender_protocol_addr().hash(&mut s);
873 arp.target_hw_addr().hash(&mut s);
874 arp.target_protocol_addr().hash(&mut s);
875
876 s.finish()
877 };
878
879 let actual_hash = {
880 let mut s = DefaultHasher::new();
881 arp.hash(&mut s);
882 s.finish()
883 };
884
885 assert_eq!(expected_hash, actual_hash);
886 }
887 }
888
889 #[test]
890 fn arp_packet_works() {
891 let bytes = [
892 0, 1, 8, 0, 6, 4, 0, 1, 0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b, 10, 10, 1, 135, 0xde, 0xad, 0xc0, 0x00, 0xff, 0xee, 192, 168, 1, 253, ];
901
902 let expected = ArpPacket::new(
903 ArpHardwareId::ETHERNET,
904 EtherType::IPV4,
905 ArpOperation::REQUEST,
906 &[0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b],
907 &[10, 10, 1, 135],
908 &[0xde, 0xad, 0xc0, 0x00, 0xff, 0xee],
909 &[192, 168, 1, 253],
910 )
911 .unwrap();
912
913 let actual = ArpPacket::from_slice(&bytes).unwrap();
914
915 assert_eq!(expected, actual);
916 }
917
918 proptest! {
919 #[test]
920 fn read(
921 arp in arp_packet_any()
922 ) {
923 use std::vec::Vec;
924 use std::io::Cursor;
925
926 let mut buf = Vec::with_capacity(arp.packet_len());
928 arp.write(&mut buf).unwrap();
929 {
930 let mut cursor = Cursor::new(&buf);
931 let actual = ArpPacket::read(&mut cursor).unwrap();
932 assert_eq!(arp, actual);
933 }
934
935 for len in 0..arp.packet_len() {
937 let mut cursor = Cursor::new(&buf[..len]);
938 let actual = ArpPacket::read(&mut cursor);
939 assert!(actual.is_err());
940 }
941 }
942 }
943
944 proptest! {
945 #[test]
946 fn write_error(
947 arp in arp_packet_any()
948 ) {
949 use std::vec::Vec;
950 use std::io::Cursor;
951
952 let mut buf = Vec::with_capacity(arp.packet_len());
953 buf.resize(arp.packet_len(), 0u8);
954
955 for len in 0..arp.packet_len() {
957 let mut cursor = Cursor::new(&mut buf[..len]);
958 let actual = arp.write(&mut cursor);
959 assert!(actual.is_err());
960 }
961 }
962 }
963
964 #[test]
965 fn set_hw_addrs() {
966 let start = ArpPacket::new(
967 ArpHardwareId::ASH,
968 EtherType::PROVIDER_BRIDGING,
969 ArpOperation::REQUEST,
970 &[1, 2, 3],
971 &[4, 5, 6, 7, 8],
972 &[9, 10, 11],
973 &[12, 13, 14, 15, 16],
974 )
975 .unwrap();
976
977 {
979 let mut arp = start.clone();
980 arp.set_hw_addrs(&[17, 18], &[19, 20]).unwrap();
981 assert_eq!(2, arp.hw_addr_size());
982 assert_eq!(&[17, 18], arp.sender_hw_addr());
983 assert_eq!(&[19, 20], arp.target_hw_addr());
984 }
985
986 {
988 let mut arp = start.clone();
989 assert_eq!(
990 arp.set_hw_addrs(&[17, 18], &[19]),
991 Err(ArpHwAddrError::LenNonMatching(2, 1))
992 );
993 }
994
995 {
997 let mut arp = start.clone();
998 assert_eq!(
999 arp.set_hw_addrs(&[0; 260], &[0; 260]),
1000 Err(ArpHwAddrError::LenTooBig(260))
1001 );
1002 }
1003 }
1004
1005 #[test]
1006 fn set_proto_addrs() {
1007 let start = ArpPacket::new(
1008 ArpHardwareId::ASH,
1009 EtherType::PROVIDER_BRIDGING,
1010 ArpOperation::REQUEST,
1011 &[1, 2, 3],
1012 &[4, 5, 6, 7, 8],
1013 &[9, 10, 11],
1014 &[12, 13, 14, 15, 16],
1015 )
1016 .unwrap();
1017
1018 {
1020 let mut arp = start.clone();
1021 arp.set_protocol_addrs(&[17, 18], &[19, 20]).unwrap();
1022 assert_eq!(2, arp.protocol_addr_size());
1023 assert_eq!(&[17, 18], arp.sender_protocol_addr());
1024 assert_eq!(&[19, 20], arp.target_protocol_addr());
1025 }
1026
1027 {
1029 let mut arp = start.clone();
1030 assert_eq!(
1031 arp.set_protocol_addrs(&[17, 18], &[19]),
1032 Err(ArpProtoAddrError::LenNonMatching(2, 1))
1033 );
1034 }
1035
1036 {
1038 let mut arp = start.clone();
1039 assert_eq!(
1040 arp.set_protocol_addrs(&[0; 260], &[0; 260]),
1041 Err(ArpProtoAddrError::LenTooBig(260))
1042 );
1043 }
1044 }
1045
1046 proptest! {
1047 #[test]
1048 fn try_eth_ipv4(
1049 arp_eth_ipv4 in arp_eth_ipv4_packet_any()
1050 ) {
1051 use err::arp::ArpEthIpv4FromError::*;
1052
1053 {
1055 let arp: ArpPacket = arp_eth_ipv4.clone().into();
1056 assert_eq!(arp.try_eth_ipv4(), Ok(arp_eth_ipv4.clone()));
1057 }
1058
1059 {
1061 let mut arp: ArpPacket = arp_eth_ipv4.clone().into();
1062 arp.hw_addr_type = ArpHardwareId::AX25;
1063 assert_eq!(
1064 arp.try_eth_ipv4(),
1065 Err(NonMatchingHwType(ArpHardwareId::AX25))
1066 );
1067 }
1068
1069 {
1071 let mut arp: ArpPacket = arp_eth_ipv4.clone().into();
1072 arp.proto_addr_type = EtherType::IPV6;
1073 assert_eq!(
1074 arp.try_eth_ipv4(),
1075 Err(NonMatchingProtocolType(EtherType::IPV6))
1076 );
1077 }
1078
1079 {
1081 let mut arp: ArpPacket = arp_eth_ipv4.clone().into();
1082 arp.set_hw_addrs(&[1], &[2]).unwrap();
1083 assert_eq!(
1084 arp.try_eth_ipv4(),
1085 Err(NonMatchingHwAddrSize(1))
1086 );
1087 }
1088
1089 {
1091 let mut arp: ArpPacket = arp_eth_ipv4.clone().into();
1092 arp.set_protocol_addrs(&[1], &[2]).unwrap();
1093 assert_eq!(
1094 arp.try_eth_ipv4(),
1095 Err(NonMatchingProtoAddrSize(1))
1096 );
1097 }
1098 }
1099 }
1100}