• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use arrayvec::ArrayVec;
2 use err::arp::{ArpHwAddrError, ArpNewError, ArpProtoAddrError};
3 
4 use crate::*;
5 use core::mem::MaybeUninit;
6 
7 /// "Address Resolution Protocol" Packet.
8 #[derive(Clone)]
9 pub struct ArpPacket {
10     /// Network link protocol type (e.g. `ArpHardwareId::ETHERNET`).
11     pub hw_addr_type: ArpHardwareId,
12 
13     /// Protocol for which the ARP request is intended (e.g. `EtherType::IPV4`).
14     pub proto_addr_type: EtherType,
15 
16     /// Length (in octets) of a hardware address (e.g. 6 for Ethernet).
17     hw_addr_size: u8,
18 
19     /// Length (in octets) of internetwork addresses (e.g. 4 for IPv4 or 16 for IPv6).
20     proto_addr_size: u8,
21 
22     /// Specifies the operation that the sender is performing
23     pub operation: ArpOperation,
24 
25     /// Buffer containing the sender hardware address (e.g. MAC address).
26     sender_hw_addr_buf: [MaybeUninit<u8>; 0xff],
27 
28     /// Buffer containing the sender protocol address (e.g. IPv4 address).
29     sender_protocol_addr_buf: [MaybeUninit<u8>; 0xff],
30 
31     /// Buffer containing the target hardware address (e.g. MAC address).
32     target_hw_addr_buf: [MaybeUninit<u8>; 0xff],
33 
34     /// Buffer containing the target protocol address (e.g. IPv4 address)..
35     target_protocol_addr_buf: [MaybeUninit<u8>; 0xff],
36 }
37 
38 impl ArpPacket {
39     /// Maximum length of an ARP packet in bytes/octets.
40     ///
41     /// This number is calculated by taking the maximum values
42     /// that `hw_addr_size`(255/u8::MAX) & `proto_addr_size` (255/u8::MAX)
43     /// can take and calculate the maximum packet size from that.
44     pub const MAX_LEN: usize = 8 + 2 * 255 + 2 * 255;
45 
46     /// Create a new ARP packet with the given values.
new( hw_addr_type: ArpHardwareId, proto_addr_type: EtherType, operation: ArpOperation, sender_hw_addr: &[u8], sender_protocol_addr: &[u8], target_hw_addr: &[u8], target_protocol_addr: &[u8], ) -> Result<ArpPacket, ArpNewError>47     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             // cast ok as we verfied the len to be less equal then 255.
82             hw_addr_size: sender_hw_addr.len() as u8,
83             // cast ok as we verfied the len to be less equal then 255.
84             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                 // SAFETY: Safe as
89                 // * sender_hw_addr.len() is guranteed to be <= 255 (checked in if above)
90                 // * memory areas guranteed to be non overlapping (buf created in this function).
91                 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                 // SAFETY: Safe as
103                 // * sender_protocol_addr.len() is guranteed to be <= 255 (checked in if above)
104                 // * memory areas guranteed to be non overlapping (buf created in this function).
105                 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                 // SAFETY: Safe as
117                 // * target_hw_addr.len() is guranteed to be <= 255 (checked in if above)
118                 // * memory areas guranteed to be non overlapping (buf created in this function).
119                 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                 // SAFETY: Safe as
131                 // * target_protocol_addr.len() is guranteed to be <= 255 (checked in if above)
132                 // * memory areas guranteed to be non overlapping (buf created in this function).
133                 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     /// Create a new ARP packet with the given values without checking
146     /// hardware & protocol address sizes.
147     ///
148     /// # Safety
149     ///
150     /// The caller must gurantee that
151     ///
152     /// * `sender_hw_addr` & `target_hw_addr` have the same length and the length must be smaller or equal than 255.
153     /// * `sender_protocol_addr` & `target_protocol_addr` have the same length and the length must be smaller or equal than 255.
154     ///
155     /// The gurantees the caller must fullfill are equal to the following
156     /// preconditions:
157     ///
158     /// * `sender_hw_addr.len() == target_hw_addr.len()`
159     /// * `sender_hw_addr.len() <= 255`
160     /// * `target_hw_addr.len() <= 255`
161     /// * `sender_protocol_addr.len() == target_protocol_addr.len()`
162     /// * `sender_protocol_addr.len() <= 255`
163     /// * `target_protocol_addr.len() <= 255`
new_unchecked( hw_addr_type: ArpHardwareId, proto_addr_type: EtherType, operation: ArpOperation, sender_hw_addr: &[u8], sender_protocol_addr: &[u8], target_hw_addr: &[u8], target_protocol_addr: &[u8], ) -> ArpPacket164     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             // cast ok as we verfied the len to be less equal then 255.
182             hw_addr_size: sender_hw_addr.len() as u8,
183             // cast ok as we verfied the len to be less equal then 255.
184             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                 // SAFETY: Safe as
189                 // * the caller must gurantee that sender_hw_addr.len() is <= 255
190                 // * memory areas guranteed to be non overlapping (buf created in this function).
191                 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                 // SAFETY: Safe as
203                 // * the caller must gurantee that sender_protocol_addr.len() is <= 255
204                 // * memory areas guranteed to be non overlapping (buf created in this function).
205                 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                 // SAFETY: Safe as
217                 // * the caller must gurantee that target_hw_addr.len() is <= 255
218                 // * memory areas guranteed to be non overlapping (buf created in this function).
219                 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                 // SAFETY: Safe as
231                 // * the caller must gurantee that target_protocol_addr.len() is <= 255
232                 // * memory areas guranteed to be non overlapping (buf created in this function).
233                 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     /// Reads an ARP packet from a slice.
from_slice(slice: &[u8]) -> Result<ArpPacket, err::LenError>246     pub fn from_slice(slice: &[u8]) -> Result<ArpPacket, err::LenError> {
247         ArpPacketSlice::from_slice(slice).map(|v| v.to_packet())
248     }
249 
250     /// Length (in octets) of a hardware address (e.g. 6 for Ethernet).
251     #[inline]
hw_addr_size(&self) -> u8252     pub const fn hw_addr_size(&self) -> u8 {
253         self.hw_addr_size
254     }
255 
256     /// Length (in octets) of internetwork addresses (e.g. 4 for IPv4 or 16 for IPv6).
257     #[inline]
protocol_addr_size(&self) -> u8258     pub const fn protocol_addr_size(&self) -> u8 {
259         self.proto_addr_size
260     }
261 
262     /// Sender hardware address (e.g. MAC address).
263     #[inline]
sender_hw_addr(&self) -> &[u8]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     /// Sender protocol address (e.g. IPv4 address).
274     #[inline]
sender_protocol_addr(&self) -> &[u8]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     /// Target hardware address (e.g. MAC address).
285     #[inline]
target_hw_addr(&self) -> &[u8]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     /// Target protocol address (e.g. IPv4 address).
296     #[inline]
target_protocol_addr(&self) -> &[u8]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     /// Set the sender & target hardware addresses (e.g. MAC address).
307     #[inline]
set_hw_addrs( &mut self, sender_hw_addr: &[u8], target_hw_addr: &[u8], ) -> Result<(), ArpHwAddrError>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             // SAFETY: Safe as
324             // * the caller must gurantee that sender_hw_addr.len() is <= 255
325             // * memory areas guranteed to be non overlapping (buf created in this function).
326             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             // SAFETY: Safe as
336             // * the caller must gurantee that target_hw_addr.len() is <= 255
337             // * memory areas guranteed to be non overlapping (buf created in this function).
338             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     /// Set the sender & target protocol addresses (e.g. IPv4 address).
351     #[inline]
set_protocol_addrs( &mut self, sender_protocol_addr: &[u8], target_protocol_addr: &[u8], ) -> Result<(), ArpProtoAddrError>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             // SAFETY: Safe as
368             // * sender_protocol_addr.len() is guranteed to be <= 255 (checked in if above)
369             // * memory areas guranteed to be non overlapping (buf created in this function).
370             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             // SAFETY: Safe as
380             // * target_protocol_addr.len() is guranteed to be <= 255 (checked in if above)
381             // * memory areas guranteed to be non overlapping (buf created in this function).
382             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     /// Serialized length of this ARP packet.
395     #[inline]
packet_len(&self) -> usize396     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     /// Returns the serialized header.
401     #[inline]
to_bytes(&self) -> ArrayVec<u8,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     /// Writes the header to the given writer.
429     #[cfg(feature = "std")]
write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error>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")))]
read<T: std::io::Read + std::io::Seek + Sized>( reader: &mut T, ) -> Result<ArpPacket, std::io::Error>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             // SAFETY: Safe as the maximum u8 value is equal to the array size 255.
457             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             // SAFETY: Safe as the maximum u8 value is equal to the array size 255.
467             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             // SAFETY: Safe as the maximum u8 value is equal to the array size 255.
477             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             // SAFETY: Safe as the maximum u8 value is equal to the array size 255.
487             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     /// Returns an [`ArpEthIpv4Packet`] if the current packet
500     /// is an ethernet & IPv4 ARP packet.
try_eth_ipv4(&self) -> Result<ArpEthIpv4Packet, err::arp::ArpEthIpv4FromError>501     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                 // SAFE as we check above that hw_addr_size is 6
519                 [
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                 // SAFE as we check above that proto_addr_size is 6
530                 [
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                 // SAFE as we check above that hw_addr_size is 6
539                 [
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                 // SAFE as we check above that proto_addr_size is 6
550                 [
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 
561 impl core::fmt::Debug for ArpPacket {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result562     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 
577 impl core::cmp::PartialEq for ArpPacket {
eq(&self, other: &Self) -> bool578     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 
591 impl core::cmp::Eq for ArpPacket {}
592 
593 impl core::hash::Hash for ArpPacket {
hash<H: core::hash::Hasher>(&self, state: &mut H)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)]
608 mod tests {
609     use crate::{test_gens::*, *};
610     use err::arp::{ArpHwAddrError, ArpNewError, ArpProtoAddrError};
611     use proptest::prelude::*;
612 
613     #[test]
new()614     fn new() {
615         // ok case
616         {
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         // ok case (upper hw size)
639         {
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         // ok case (protocol hw size)
662         {
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         // hw slice len differ error
685         {
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         // protocol slice len differ error
701         {
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         // hardware length error
720         {
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         // protocol length error
737         {
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]
new_unchecked()755     fn new_unchecked() {
756         // ok case
757         {
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         // ok case (upper hw size)
781         {
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         // ok case (protocol hw size)
805         {
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]
arp_packet_works()890     fn arp_packet_works() {
891         let bytes = [
892             0, 1, // hardware type
893             8, 0, // proto type
894             6, 4, // sizes
895             0, 1, // arp operation
896             0x00, 0x1b, 0x21, 0x0f, 0x91, 0x9b, // src mac
897             10, 10, 1, 135, // src ip
898             0xde, 0xad, 0xc0, 0x00, 0xff, 0xee, // dest mac
899             192, 168, 1, 253, // dest ip
900         ];
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             // ok case
927             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             // len io error
936             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             // check that the write produces an error if not enough memory is present
956             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]
set_hw_addrs()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         // ok case
978         {
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         // non matching error
987         {
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         // above 255 error
996         {
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]
set_proto_addrs()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         // ok case
1019         {
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         // non matching error
1028         {
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         // above 255 error
1037         {
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             // ok case
1054             {
1055                 let arp: ArpPacket = arp_eth_ipv4.clone().into();
1056                 assert_eq!(arp.try_eth_ipv4(), Ok(arp_eth_ipv4.clone()));
1057             }
1058 
1059             // hw type error
1060             {
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             // proto type error
1070             {
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             // hw address size error
1080             {
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             // protocol address size error
1090             {
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 }
1101