Thanks to visit codestin.com
Credit goes to docs.rs

etherparse/net/
arp_packet.rs

1use arrayvec::ArrayVec;
2use err::arp::{ArpHwAddrError, ArpNewError, ArpProtoAddrError};
3
4use crate::*;
5use core::mem::MaybeUninit;
6
7/// "Address Resolution Protocol" Packet.
8#[derive(Clone)]
9pub 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
38impl 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.
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 verified the len to be less equal then 255.
82            hw_addr_size: sender_hw_addr.len() as u8,
83            // cast ok as we verified 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 guaranteed to be <= 255 (checked in if above)
90                // * memory areas guaranteed 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 guaranteed to be <= 255 (checked in if above)
104                // * memory areas guaranteed 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 guaranteed to be <= 255 (checked in if above)
118                // * memory areas guaranteed 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 guaranteed to be <= 255 (checked in if above)
132                // * memory areas guaranteed 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 guarantee 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 guarantees the caller must fulfill 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`
164    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 verified the len to be less equal then 255.
182            hw_addr_size: sender_hw_addr.len() as u8,
183            // cast ok as we verified 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 guarantee that sender_hw_addr.len() is <= 255
190                // * memory areas guaranteed 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 guarantee that sender_protocol_addr.len() is <= 255
204                // * memory areas guaranteed 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 guarantee that target_hw_addr.len() is <= 255
218                // * memory areas guaranteed 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 guarantee that target_protocol_addr.len() is <= 255
232                // * memory areas guaranteed 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.
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]
252    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]
258    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]
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]
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]
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]
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]
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 guarantee that sender_hw_addr.len() is <= 255
325            // * memory areas guaranteed 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 guarantee that target_hw_addr.len() is <= 255
337            // * memory areas guaranteed 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]
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 guaranteed to be <= 255 (checked in if above)
369            // * memory areas guaranteed 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 guaranteed to be <= 255 (checked in if above)
381            // * memory areas guaranteed 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]
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    /// Returns the serialized header.
401    #[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    /// Writes the header to the given writer.
429    #[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            // 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.
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
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        // 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]
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]
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]
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]
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}