etherparse/net/
arp_eth_ipv4_packet.rs1use core::net::Ipv4Addr;
2
3use crate::{ArpHardwareId, EtherType};
4
5use super::{ArpOperation, ArpPacket};
6
7#[derive(Clone, Debug, PartialEq, Eq, Hash)]
10pub struct ArpEthIpv4Packet {
11 pub operation: ArpOperation,
13
14 pub sender_mac: [u8; 6],
16
17 pub sender_ipv4: [u8; 4],
19
20 pub target_mac: [u8; 6],
22
23 pub target_ipv4: [u8; 4],
25}
26
27impl ArpEthIpv4Packet {
28 pub const LEN: usize = 8 + 6 * 2 + 4 * 2;
30
31 #[inline]
33 pub const fn sender_ipv4_addr(&self) -> Ipv4Addr {
34 Ipv4Addr::new(
35 self.sender_ipv4[0],
36 self.sender_ipv4[1],
37 self.sender_ipv4[2],
38 self.sender_ipv4[3],
39 )
40 }
41
42 #[inline]
44 pub const fn target_ipv4_addr(&self) -> Ipv4Addr {
45 Ipv4Addr::new(
46 self.target_ipv4[0],
47 self.target_ipv4[1],
48 self.target_ipv4[2],
49 self.target_ipv4[3],
50 )
51 }
52
53 pub const fn to_bytes(&self) -> [u8; Self::LEN] {
55 const ETH_HW_TYPE: [u8; 2] = ArpHardwareId::ETHERNET.0.to_be_bytes();
56 const IPV4_ETH_TYPE: [u8; 2] = EtherType::IPV4.0.to_be_bytes();
57 let op = self.operation.0.to_be_bytes();
58 [
59 ETH_HW_TYPE[0],
60 ETH_HW_TYPE[1],
61 IPV4_ETH_TYPE[0],
62 IPV4_ETH_TYPE[1],
63 6,
64 4,
65 op[0],
66 op[1],
67 self.sender_mac[0],
68 self.sender_mac[1],
69 self.sender_mac[2],
70 self.sender_mac[3],
71 self.sender_mac[4],
72 self.sender_mac[5],
73 self.sender_ipv4[0],
74 self.sender_ipv4[1],
75 self.sender_ipv4[2],
76 self.sender_ipv4[3],
77 self.target_mac[0],
78 self.target_mac[1],
79 self.target_mac[2],
80 self.target_mac[3],
81 self.target_mac[4],
82 self.target_mac[5],
83 self.target_ipv4[0],
84 self.target_ipv4[1],
85 self.target_ipv4[2],
86 self.target_ipv4[3],
87 ]
88 }
89
90 #[inline]
92 pub const fn to_arp_packet(&self) -> ArpPacket {
93 unsafe {
97 ArpPacket::new_unchecked(
98 ArpHardwareId::ETHERNET,
99 EtherType::IPV4,
100 self.operation,
101 &self.sender_mac,
102 &self.sender_ipv4,
103 &self.target_mac,
104 &self.target_ipv4,
105 )
106 }
107 }
108}
109
110impl From<ArpEthIpv4Packet> for ArpPacket {
111 fn from(value: ArpEthIpv4Packet) -> Self {
112 value.to_arp_packet()
113 }
114}
115
116impl TryFrom<ArpPacket> for ArpEthIpv4Packet {
117 type Error = crate::err::arp::ArpEthIpv4FromError;
118
119 fn try_from(value: ArpPacket) -> Result<Self, Self::Error> {
120 value.try_eth_ipv4()
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use crate::test_gens::*;
128 use proptest::prelude::*;
129
130 proptest! {
131 #[test]
132 fn sender_ipv4_addr(
133 arp in arp_eth_ipv4_packet_any()
134 ) {
135 assert_eq!(
136 arp.sender_ipv4_addr(),
137 Ipv4Addr::new(
138 arp.sender_ipv4[0],
139 arp.sender_ipv4[1],
140 arp.sender_ipv4[2],
141 arp.sender_ipv4[3]
142 )
143 )
144 }
145 }
146
147 proptest! {
148 #[test]
149 fn target_ipv4_addr(
150 arp in arp_eth_ipv4_packet_any()
151 ) {
152 assert_eq!(
153 arp.target_ipv4_addr(),
154 Ipv4Addr::new(
155 arp.target_ipv4[0],
156 arp.target_ipv4[1],
157 arp.target_ipv4[2],
158 arp.target_ipv4[3]
159 )
160 )
161 }
162 }
163
164 proptest! {
165 #[test]
166 fn to_bytes(
167 arp in arp_eth_ipv4_packet_any()
168 ) {
169 assert_eq!(
170 &arp.to_bytes()[..],
171 &arp.to_arp_packet().to_bytes()[..]
172 );
173 }
174 }
175
176 proptest! {
177 #[test]
178 fn to_arp_packet(
179 arp in arp_eth_ipv4_packet_any()
180 ) {
181 let actual = arp.to_arp_packet();
182 assert_eq!(ArpHardwareId::ETHERNET, actual.hw_addr_type);
183 assert_eq!(EtherType::IPV4, actual.proto_addr_type);
184 assert_eq!(6, actual.hw_addr_size());
185 assert_eq!(4, actual.protocol_addr_size());
186 assert_eq!(&arp.target_mac[..], actual.target_hw_addr());
187 assert_eq!(&arp.target_ipv4[..], actual.target_protocol_addr());
188 assert_eq!(&arp.sender_mac[..], actual.sender_hw_addr());
189 assert_eq!(&arp.sender_ipv4[..], actual.sender_protocol_addr());
190 }
191 }
192
193 proptest! {
194 #[test]
195 fn into_arp_packet(
196 arp in arp_eth_ipv4_packet_any()
197 ) {
198 let actual = ArpPacket::from(arp.clone());
199 assert_eq!(actual, arp.to_arp_packet());
200 }
201 }
202
203 proptest! {
204 #[test]
205 fn try_from_arp_packet(
206 arp in arp_packet_any()
207 ) {
208 let actual = ArpEthIpv4Packet::try_from(arp.clone());
209 assert_eq!(actual, arp.clone().try_eth_ipv4());
210 }
211 }
212}