network_types/arp.rs
1use core::mem::{self};
2
3use crate::{getter_be, setter_be};
4
5/// Represents an Address Resolution Protocol (ARP) header.
6///
7/// The ARP header is typically found after the Ethernet header and is used to
8/// map a network protocol address (like an IPv4 address) to a hardware
9/// address (like a MAC address).
10#[repr(C)]
11#[derive(Debug, Copy, Clone, Default)]
12#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
13pub struct ArpHdr {
14 /// Hardware type (HTYPE): Specifies the network link protocol type.
15 /// E.g., Ethernet is 1.
16 pub htype: [u8; 2],
17 /// Protocol type (PTYPE): Specifies the internetwork protocol for which
18 /// the ARP request is intended. For IPv4, this has the value 0x0800.
19 pub ptype: [u8; 2],
20 /// Hardware address length (HLEN): Length in bytes of a hardware address.
21 /// Ethernet addresses size is 6.
22 pub hlen: u8,
23 /// Protocol address length (PLEN): Length in bytes of a logical address.
24 /// IPv4 addresses size is 4.
25 pub plen: u8,
26 /// Operation (OPER): Specifies the operation that the sender is performing:
27 /// 1 for request, 2 for reply.
28 pub oper: [u8; 2],
29 /// Sender hardware address (SHA): The hardware address of the sender.
30 pub sha: [u8; 6],
31 /// Sender protocol address (SPA): The protocol address of the sender.
32 pub spa: [u8; 4],
33 /// Target hardware address (THA): The hardware address of the intended
34 /// receiver. This field is ignored in an ARP request.
35 pub tha: [u8; 6],
36 /// Target protocol address (TPA): The protocol address of the intended
37 /// receiver.
38 pub tpa: [u8; 4],
39}
40
41impl ArpHdr {
42 /// The size of the ARP header in bytes.
43 pub const LEN: usize = mem::size_of::<ArpHdr>();
44
45 /// Creates a new `ArpHdr` with all fields initialized to zero.
46 /// This is an alias for `ArpHdr::default()`.
47 pub fn new() -> Self {
48 Self::default()
49 }
50
51 /// Returns the hardware type field.
52 #[inline]
53 pub fn htype(&self) -> u16 {
54 // SAFETY: Pointer arithmetic in bounds of the struct.
55 unsafe { getter_be!(self, htype, u16) }
56 }
57
58 /// Sets the hardware type field.
59 ///
60 /// # Arguments
61 ///
62 /// * `htype` - A 2-byte array representing the hardware type.
63 #[inline]
64 pub fn set_htype(&mut self, htype: u16) {
65 // SAFETY: Pointer arithmetic in bounds of the struct.
66 unsafe { setter_be!(self, htype, htype) }
67 }
68
69 /// Returns the protocol type field.
70 #[inline]
71 pub fn ptype(&self) -> u16 {
72 // SAFETY: Pointer arithmetic in bounds of the struct.
73 unsafe { getter_be!(self, ptype, u16) }
74 }
75
76 /// Sets the protocol type field.
77 ///
78 /// # Arguments
79 ///
80 /// * `ptype` - A 2-byte array representing the protocol type.
81 #[inline]
82 pub fn set_ptype(&mut self, ptype: u16) {
83 // SAFETY: Pointer arithmetic in bounds of the struct.
84 unsafe { setter_be!(self, ptype, ptype) }
85 }
86
87 /// Returns the hardware address length field.
88 #[inline]
89 pub fn hlen(&self) -> u8 {
90 self.hlen
91 }
92
93 /// Sets the hardware address length field.
94 ///
95 /// # Arguments
96 ///
97 /// * `hlen` - A u8 value for the hardware address length.
98 #[inline]
99 pub fn set_hlen(&mut self, hlen: u8) {
100 self.hlen = hlen;
101 }
102
103 /// Returns the protocol address length field.
104 #[inline]
105 pub fn plen(&self) -> u8 {
106 self.plen
107 }
108
109 /// Sets the protocol address length field.
110 ///
111 /// # Arguments
112 ///
113 /// * `plen` - A u8 value for the protocol address length.
114 #[inline]
115 pub fn set_plen(&mut self, plen: u8) {
116 self.plen = plen;
117 }
118
119 /// Returns the operation field.
120 #[inline]
121 pub fn oper(&self) -> u16 {
122 // SAFETY: Pointer arithmetic in bounds of the struct.
123 unsafe { getter_be!(self, oper, u16) }
124 }
125
126 /// Sets the operation field.
127 ///
128 /// # Arguments
129 ///
130 /// * `oper` - A 2-byte array representing the operation (e.g., request or reply).
131 #[inline]
132 pub fn set_oper(&mut self, oper: u16) {
133 // SAFETY: Pointer arithmetic in bounds of the struct.
134 unsafe { setter_be!(self, oper, oper) }
135 }
136
137 /// Returns the sender hardware address (SHA) field.
138 #[inline]
139 pub fn sha(&self) -> [u8; 6] {
140 self.sha
141 }
142
143 /// Sets the sender hardware address (SHA) field.
144 ///
145 /// # Arguments
146 ///
147 /// * `hardware_address` - A 6-byte array representing the sender's hardware address.
148 #[inline]
149 pub fn set_sha(&mut self, hardware_address: [u8; 6]) {
150 self.sha = hardware_address
151 }
152
153 /// Returns the sender protocol address (SPA) field.
154 #[inline]
155 pub fn spa(&self) -> [u8; 4] {
156 self.spa
157 }
158
159 /// Sets the sender protocol address (SPA) field.
160 ///
161 /// # Arguments
162 ///
163 /// * `protocol_address` - A 4-byte array representing the sender's protocol address.
164 #[inline]
165 pub fn set_spa(&mut self, protocol_address: [u8; 4]) {
166 self.spa = protocol_address
167 }
168
169 /// Returns the target hardware address (THA) field.
170 #[inline]
171 pub fn tha(&self) -> [u8; 6] {
172 self.tha
173 }
174
175 /// Sets the target hardware address (THA) field.
176 ///
177 /// # Arguments
178 ///
179 /// * `hardware_address` - A 6-byte array representing the target's hardware address.
180 #[inline]
181 pub fn set_tha(&mut self, hardware_address: [u8; 6]) {
182 self.tha = hardware_address
183 }
184
185 /// Returns the target protocol address (TPA) field.
186 #[inline]
187 pub fn tpa(&self) -> [u8; 4] {
188 self.tpa
189 }
190
191 /// Sets the target protocol address (TPA) field.
192 ///
193 /// # Arguments
194 ///
195 /// * `protocol_address` - A 4-byte array representing the target's protocol address.
196 #[inline]
197 pub fn set_tpa(&mut self, protocol_address: [u8; 4]) {
198 self.tpa = protocol_address
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205
206 #[test]
207 fn test_len_constant() {
208 assert_eq!(ArpHdr::LEN, 28);
209 assert_eq!(ArpHdr::LEN, mem::size_of::<ArpHdr>());
210 }
211
212 #[test]
213 fn test_htype() {
214 let mut hdr = ArpHdr::default();
215 let hw_type = 1u16;
216 hdr.set_htype(hw_type);
217 assert_eq!(hdr.htype(), hw_type);
218 }
219
220 #[test]
221 fn test_ptype() {
222 let mut hdr = ArpHdr::default();
223 let proto_type = 0x0800u16;
224 hdr.set_ptype(proto_type);
225 assert_eq!(hdr.ptype(), proto_type);
226 }
227
228 #[test]
229 fn test_hlen() {
230 let mut hdr = ArpHdr::default();
231 hdr.set_hlen(6);
232 assert_eq!(hdr.hlen(), 6);
233 }
234
235 #[test]
236 fn test_plen() {
237 let mut hdr = ArpHdr::default();
238 hdr.set_plen(4);
239 assert_eq!(hdr.plen(), 4);
240 }
241
242 #[test]
243 fn test_oper() {
244 let mut hdr = ArpHdr::default();
245 let op_request = 1u16;
246 hdr.set_oper(op_request);
247 assert_eq!(hdr.oper(), op_request);
248 let op_reply = 2u16;
249 hdr.set_oper(op_reply);
250 assert_eq!(hdr.oper(), op_reply);
251 }
252
253 #[test]
254 fn test_sha() {
255 let mut hdr = ArpHdr::default();
256 let addr = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55];
257 hdr.set_sha(addr);
258 assert_eq!(hdr.sha(), addr);
259 }
260
261 #[test]
262 fn test_spa() {
263 let mut hdr = ArpHdr::default();
264 let addr = [192, 168, 1, 1];
265 hdr.set_spa(addr);
266 assert_eq!(hdr.spa(), addr);
267 }
268
269 #[test]
270 fn test_tha() {
271 let mut hdr = ArpHdr::default();
272 let addr = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
273 hdr.set_tha(addr);
274 assert_eq!(hdr.tha(), addr);
275 }
276
277 #[test]
278 fn test_tpa() {
279 let mut hdr = ArpHdr::default();
280 let addr = [192, 168, 1, 100];
281 hdr.set_tpa(addr);
282 assert_eq!(hdr.tpa(), addr);
283 }
284}