xenet_packet/
arp.rs

1//! ARP packet abstraction.
2
3use 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
15/// ARP Header Length.
16pub const ARP_HEADER_LEN: usize = 28;
17/// ARP Minimum Packet Length.
18pub const ARP_PACKET_LEN: usize = ETHERNET_HEADER_LEN + ARP_HEADER_LEN;
19
20/// Represents the ARP header.
21#[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    /// Construct an ARP header from a byte slice.
37    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    /// Construct an ARP header from an ArpPacket.
57    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/// Represents the ARP operation types.
73#[repr(u16)]
74#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
75#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
76pub enum ArpOperation {
77    /// ARP request
78    Request = 1,
79    /// ARP reply
80    Reply = 2,
81    /// RARP request
82    RarpRequest = 3,
83    /// RARP reply
84    RarpReply = 4,
85    /// InARP request
86    InRequest = 8,
87    /// InARP reply
88    InReply = 9,
89    /// ARP NAK
90    Nak = 10,
91    /// Unknown ARP operation
92    Unknown(u16),
93}
94
95impl ArpOperation {
96    /// Constructs a new ArpOperation from u16
97    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/// Represents the ARP hardware types.
128#[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 (10Mb)
133    Ethernet = 1,
134    /// Experimental Ethernet (3Mb)
135    ExperimentalEthernet = 2,
136    /// Amateur Radio AX.25
137    AmateurRadioAX25 = 3,
138    /// Proteon ProNET Token Ring
139    ProteonProNETTokenRing = 4,
140    /// Chaos
141    Chaos = 5,
142    /// IEEE 802 Networks
143    IEEE802Networks = 6,
144    /// ARCNET
145    ARCNET = 7,
146    /// Hyperchannel
147    Hyperchannel = 8,
148    /// Lanstar
149    Lanstar = 9,
150    /// Autonet Short Address
151    AutonetShortAddress = 10,
152    /// LocalTalk
153    LocalTalk = 11,
154    /// LocalNet (IBM PCNet or SYTEK LocalNET)
155    LocalNet = 12,
156    /// Ultra link
157    UltraLink = 13,
158    /// SMDS
159    SMDS = 14,
160    /// Frame Relay
161    FrameRelay = 15,
162    /// Asynchronous Transmission Mode (ATM)
163    AsynchronousTransmissionMode = 16,
164    /// HDLC
165    HDLC = 17,
166    /// Fibre Channel
167    FibreChannel = 18,
168    /// Asynchronous Transmission Mode (ATM)
169    AsynchronousTransmissionMode2 = 19,
170    /// Serial Line
171    SerialLine = 20,
172    /// Asynchronous Transmission Mode (ATM)
173    AsynchronousTransmissionMode3 = 21,
174    /// MIL-STD-188-220
175    MILSTD188220 = 22,
176    /// Metricom
177    Metricom = 23,
178    /// IEEE 1394.1995
179    IEEE13941995 = 24,
180    /// MAPOS
181    MAPOS = 25,
182    /// Twinaxial
183    Twinaxial = 26,
184    /// EUI-64
185    EUI64 = 27,
186    /// HIPARP
187    HIPARP = 28,
188    /// IP and ARP over ISO 7816-3
189    IPandARPoverISO78163 = 29,
190    /// ARPSec
191    ARPSec = 30,
192    /// IPsec tunnel
193    IPsecTunnel = 31,
194    /// InfiniBand (TM)
195    InfiniBand = 32,
196    /// TIA-102 Project 25 Common Air Interface
197    TIA102Project25CommonAirInterface = 16384,
198    /// Wiegand Interface
199    WiegandInterface = 16385,
200    /// Pure IP
201    PureIP = 16386,
202    /// HW_EXP1
203    HWEXP1 = 65280,
204    /// HW_EXP2
205    HWEXP2 = 65281,
206    /// AEthernet
207    AEthernet = 65282,
208    /// Unknown ARP hardware type
209    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/// Represents an ARP Packet.
306#[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}