1use crate::ethernet::{EtherType, ETHERNET_HEADER_LEN};
4use crate::PrimitiveValues;
5
6use alloc::vec::Vec;
7
8use std::net::Ipv4Addr;
9use xenet_core::mac::MacAddr;
10use xenet_macro::packet;
11
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15pub const ARP_HEADER_LEN: usize = 28;
17pub const ARP_PACKET_LEN: usize = ETHERNET_HEADER_LEN + ARP_HEADER_LEN;
19
20#[derive(Clone, Debug, PartialEq, Eq)]
22#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23pub struct ArpHeader {
24 pub hardware_type: ArpHardwareType,
25 pub protocol_type: EtherType,
26 pub hw_addr_len: u8,
27 pub proto_addr_len: u8,
28 pub operation: ArpOperation,
29 pub sender_hw_addr: MacAddr,
30 pub sender_proto_addr: Ipv4Addr,
31 pub target_hw_addr: MacAddr,
32 pub target_proto_addr: Ipv4Addr,
33}
34
35impl ArpHeader {
36 pub fn from_bytes(packet: &[u8]) -> Result<ArpHeader, String> {
38 if packet.len() < ARP_HEADER_LEN {
39 return Err("Packet is too small for ARP header".to_string());
40 }
41 match ArpPacket::new(packet) {
42 Some(arp_packet) => Ok(ArpHeader {
43 hardware_type: arp_packet.get_hardware_type(),
44 protocol_type: arp_packet.get_protocol_type(),
45 hw_addr_len: arp_packet.get_hw_addr_len(),
46 proto_addr_len: arp_packet.get_proto_addr_len(),
47 operation: arp_packet.get_operation(),
48 sender_hw_addr: arp_packet.get_sender_hw_addr(),
49 sender_proto_addr: arp_packet.get_sender_proto_addr(),
50 target_hw_addr: arp_packet.get_target_hw_addr(),
51 target_proto_addr: arp_packet.get_target_proto_addr(),
52 }),
53 None => Err("Failed to parse ARP packet".to_string()),
54 }
55 }
56 pub(crate) fn from_packet(packet: &ArpPacket) -> ArpHeader {
58 ArpHeader {
59 hardware_type: packet.get_hardware_type(),
60 protocol_type: packet.get_protocol_type(),
61 hw_addr_len: packet.get_hw_addr_len(),
62 proto_addr_len: packet.get_proto_addr_len(),
63 operation: packet.get_operation(),
64 sender_hw_addr: packet.get_sender_hw_addr(),
65 sender_proto_addr: packet.get_sender_proto_addr(),
66 target_hw_addr: packet.get_target_hw_addr(),
67 target_proto_addr: packet.get_target_proto_addr(),
68 }
69 }
70}
71
72#[repr(u16)]
74#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
75#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
76pub enum ArpOperation {
77 Request = 1,
79 Reply = 2,
81 RarpRequest = 3,
83 RarpReply = 4,
85 InRequest = 8,
87 InReply = 9,
89 Nak = 10,
91 Unknown(u16),
93}
94
95impl ArpOperation {
96 pub fn new(value: u16) -> ArpOperation {
98 match value {
99 1 => ArpOperation::Request,
100 2 => ArpOperation::Reply,
101 3 => ArpOperation::RarpRequest,
102 4 => ArpOperation::RarpReply,
103 8 => ArpOperation::InRequest,
104 9 => ArpOperation::InReply,
105 10 => ArpOperation::Nak,
106 _ => ArpOperation::Unknown(value),
107 }
108 }
109}
110
111impl PrimitiveValues for ArpOperation {
112 type T = (u16,);
113 fn to_primitive_values(&self) -> (u16,) {
114 match *self {
115 ArpOperation::Request => (1,),
116 ArpOperation::Reply => (2,),
117 ArpOperation::RarpRequest => (3,),
118 ArpOperation::RarpReply => (4,),
119 ArpOperation::InRequest => (8,),
120 ArpOperation::InReply => (9,),
121 ArpOperation::Nak => (10,),
122 ArpOperation::Unknown(n) => (n,),
123 }
124 }
125}
126
127#[repr(u16)]
129#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
130#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
131pub enum ArpHardwareType {
132 Ethernet = 1,
134 ExperimentalEthernet = 2,
136 AmateurRadioAX25 = 3,
138 ProteonProNETTokenRing = 4,
140 Chaos = 5,
142 IEEE802Networks = 6,
144 ARCNET = 7,
146 Hyperchannel = 8,
148 Lanstar = 9,
150 AutonetShortAddress = 10,
152 LocalTalk = 11,
154 LocalNet = 12,
156 UltraLink = 13,
158 SMDS = 14,
160 FrameRelay = 15,
162 AsynchronousTransmissionMode = 16,
164 HDLC = 17,
166 FibreChannel = 18,
168 AsynchronousTransmissionMode2 = 19,
170 SerialLine = 20,
172 AsynchronousTransmissionMode3 = 21,
174 MILSTD188220 = 22,
176 Metricom = 23,
178 IEEE13941995 = 24,
180 MAPOS = 25,
182 Twinaxial = 26,
184 EUI64 = 27,
186 HIPARP = 28,
188 IPandARPoverISO78163 = 29,
190 ARPSec = 30,
192 IPsecTunnel = 31,
194 InfiniBand = 32,
196 TIA102Project25CommonAirInterface = 16384,
198 WiegandInterface = 16385,
200 PureIP = 16386,
202 HWEXP1 = 65280,
204 HWEXP2 = 65281,
206 AEthernet = 65282,
208 Unknown(u16),
210}
211
212impl ArpHardwareType {
213 pub fn new(value: u16) -> ArpHardwareType {
214 match value {
215 1 => ArpHardwareType::Ethernet,
216 2 => ArpHardwareType::ExperimentalEthernet,
217 3 => ArpHardwareType::AmateurRadioAX25,
218 4 => ArpHardwareType::ProteonProNETTokenRing,
219 5 => ArpHardwareType::Chaos,
220 6 => ArpHardwareType::IEEE802Networks,
221 7 => ArpHardwareType::ARCNET,
222 8 => ArpHardwareType::Hyperchannel,
223 9 => ArpHardwareType::Lanstar,
224 10 => ArpHardwareType::AutonetShortAddress,
225 11 => ArpHardwareType::LocalTalk,
226 12 => ArpHardwareType::LocalNet,
227 13 => ArpHardwareType::UltraLink,
228 14 => ArpHardwareType::SMDS,
229 15 => ArpHardwareType::FrameRelay,
230 16 => ArpHardwareType::AsynchronousTransmissionMode,
231 17 => ArpHardwareType::HDLC,
232 18 => ArpHardwareType::FibreChannel,
233 19 => ArpHardwareType::AsynchronousTransmissionMode2,
234 20 => ArpHardwareType::SerialLine,
235 21 => ArpHardwareType::AsynchronousTransmissionMode3,
236 22 => ArpHardwareType::MILSTD188220,
237 23 => ArpHardwareType::Metricom,
238 24 => ArpHardwareType::IEEE13941995,
239 25 => ArpHardwareType::MAPOS,
240 26 => ArpHardwareType::Twinaxial,
241 27 => ArpHardwareType::EUI64,
242 28 => ArpHardwareType::HIPARP,
243 29 => ArpHardwareType::IPandARPoverISO78163,
244 30 => ArpHardwareType::ARPSec,
245 31 => ArpHardwareType::IPsecTunnel,
246 32 => ArpHardwareType::InfiniBand,
247 16384 => ArpHardwareType::TIA102Project25CommonAirInterface,
248 16385 => ArpHardwareType::WiegandInterface,
249 16386 => ArpHardwareType::PureIP,
250 65280 => ArpHardwareType::HWEXP1,
251 65281 => ArpHardwareType::HWEXP2,
252 65282 => ArpHardwareType::AEthernet,
253 _ => ArpHardwareType::Unknown(value),
254 }
255 }
256}
257
258impl PrimitiveValues for ArpHardwareType {
259 type T = (u16,);
260 fn to_primitive_values(&self) -> (u16,) {
261 match *self {
262 ArpHardwareType::Ethernet => (1,),
263 ArpHardwareType::ExperimentalEthernet => (2,),
264 ArpHardwareType::AmateurRadioAX25 => (3,),
265 ArpHardwareType::ProteonProNETTokenRing => (4,),
266 ArpHardwareType::Chaos => (5,),
267 ArpHardwareType::IEEE802Networks => (6,),
268 ArpHardwareType::ARCNET => (7,),
269 ArpHardwareType::Hyperchannel => (8,),
270 ArpHardwareType::Lanstar => (9,),
271 ArpHardwareType::AutonetShortAddress => (10,),
272 ArpHardwareType::LocalTalk => (11,),
273 ArpHardwareType::LocalNet => (12,),
274 ArpHardwareType::UltraLink => (13,),
275 ArpHardwareType::SMDS => (14,),
276 ArpHardwareType::FrameRelay => (15,),
277 ArpHardwareType::AsynchronousTransmissionMode => (16,),
278 ArpHardwareType::HDLC => (17,),
279 ArpHardwareType::FibreChannel => (18,),
280 ArpHardwareType::AsynchronousTransmissionMode2 => (19,),
281 ArpHardwareType::SerialLine => (20,),
282 ArpHardwareType::AsynchronousTransmissionMode3 => (21,),
283 ArpHardwareType::MILSTD188220 => (22,),
284 ArpHardwareType::Metricom => (23,),
285 ArpHardwareType::IEEE13941995 => (24,),
286 ArpHardwareType::MAPOS => (25,),
287 ArpHardwareType::Twinaxial => (26,),
288 ArpHardwareType::EUI64 => (27,),
289 ArpHardwareType::HIPARP => (28,),
290 ArpHardwareType::IPandARPoverISO78163 => (29,),
291 ArpHardwareType::ARPSec => (30,),
292 ArpHardwareType::IPsecTunnel => (31,),
293 ArpHardwareType::InfiniBand => (32,),
294 ArpHardwareType::TIA102Project25CommonAirInterface => (16384,),
295 ArpHardwareType::WiegandInterface => (16385,),
296 ArpHardwareType::PureIP => (16386,),
297 ArpHardwareType::HWEXP1 => (65280,),
298 ArpHardwareType::HWEXP2 => (65281,),
299 ArpHardwareType::AEthernet => (65282,),
300 ArpHardwareType::Unknown(n) => (n,),
301 }
302 }
303}
304
305#[packet]
307#[allow(non_snake_case)]
308pub struct Arp {
309 #[construct_with(u16)]
310 pub hardware_type: ArpHardwareType,
311 #[construct_with(u16)]
312 pub protocol_type: EtherType,
313 pub hw_addr_len: u8,
314 pub proto_addr_len: u8,
315 #[construct_with(u16)]
316 pub operation: ArpOperation,
317 #[construct_with(u8, u8, u8, u8, u8, u8)]
318 pub sender_hw_addr: MacAddr,
319 #[construct_with(u8, u8, u8, u8)]
320 pub sender_proto_addr: Ipv4Addr,
321 #[construct_with(u8, u8, u8, u8, u8, u8)]
322 pub target_hw_addr: MacAddr,
323 #[construct_with(u8, u8, u8, u8)]
324 pub target_proto_addr: Ipv4Addr,
325 #[payload]
326 #[length = "0"]
327 pub payload: Vec<u8>,
328}