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