zero_packet/datalink/
arp.rs1use crate::misc::{bytes_to_mac, IpFormatter};
2use core::{fmt, str::from_utf8};
3
4pub const ARP_HEADER_LENGTH: usize = 28;
6
7pub struct ArpWriter<'a> {
9 pub bytes: &'a mut [u8],
10}
11
12impl<'a> ArpWriter<'a> {
13 #[inline]
15 pub fn new(bytes: &'a mut [u8]) -> Result<Self, &'static str> {
16 if bytes.len() < ARP_HEADER_LENGTH {
17 return Err("Slice is too short to contain an ARP header.");
18 }
19
20 Ok(Self { bytes })
21 }
22
23 #[inline]
25 pub fn header_len(&self) -> usize {
26 ARP_HEADER_LENGTH
27 }
28
29 #[inline]
33 pub fn set_htype(&mut self, hardware_type: u16) {
34 self.bytes[0] = (hardware_type >> 8) as u8;
35 self.bytes[1] = hardware_type as u8;
36 }
37
38 #[inline]
42 pub fn set_ptype(&mut self, protocol_type: u16) {
43 self.bytes[2] = (protocol_type >> 8) as u8;
44 self.bytes[3] = protocol_type as u8;
45 }
46
47 #[inline]
51 pub fn set_hlen(&mut self, hardware_address_length: u8) {
52 self.bytes[4] = hardware_address_length;
53 }
54
55 #[inline]
59 pub fn set_plen(&mut self, protocol_address_length: u8) {
60 self.bytes[5] = protocol_address_length;
61 }
62
63 #[inline]
67 pub fn set_oper(&mut self, operation: u16) {
68 self.bytes[6] = (operation >> 8) as u8;
69 self.bytes[7] = operation as u8;
70 }
71
72 #[inline]
76 pub fn set_sha(&mut self, sender_hardware_address: &[u8; 6]) {
77 self.bytes[8] = sender_hardware_address[0];
78 self.bytes[9] = sender_hardware_address[1];
79 self.bytes[10] = sender_hardware_address[2];
80 self.bytes[11] = sender_hardware_address[3];
81 self.bytes[12] = sender_hardware_address[4];
82 self.bytes[13] = sender_hardware_address[5];
83 }
84
85 #[inline]
89 pub fn set_spa(&mut self, sender_protocol_address: &[u8; 4]) {
90 self.bytes[14] = sender_protocol_address[0];
91 self.bytes[15] = sender_protocol_address[1];
92 self.bytes[16] = sender_protocol_address[2];
93 self.bytes[17] = sender_protocol_address[3];
94 }
95
96 #[inline]
100 pub fn set_tha(&mut self, target_hardware_address: &[u8; 6]) {
101 self.bytes[18] = target_hardware_address[0];
102 self.bytes[19] = target_hardware_address[1];
103 self.bytes[20] = target_hardware_address[2];
104 self.bytes[21] = target_hardware_address[3];
105 self.bytes[22] = target_hardware_address[4];
106 self.bytes[23] = target_hardware_address[5];
107 }
108
109 #[inline]
113 pub fn set_tpa(&mut self, target_protocol_address: &[u8; 4]) {
114 self.bytes[24] = target_protocol_address[0];
115 self.bytes[25] = target_protocol_address[1];
116 self.bytes[26] = target_protocol_address[2];
117 self.bytes[27] = target_protocol_address[3];
118 }
119}
120
121#[derive(PartialEq)]
123pub struct ArpReader<'a> {
124 pub bytes: &'a [u8],
125}
126
127impl<'a> ArpReader<'a> {
128 #[inline]
130 pub fn new(bytes: &'a [u8]) -> Result<Self, &'static str> {
131 if bytes.len() < ARP_HEADER_LENGTH {
132 return Err("Slice is too short to contain an ARP header.");
133 }
134
135 Ok(Self { bytes })
136 }
137
138 #[inline]
142 pub fn htype(&self) -> u16 {
143 ((self.bytes[0] as u16) << 8) | (self.bytes[1] as u16)
144 }
145
146 #[inline]
150 pub fn ptype(&self) -> u16 {
151 ((self.bytes[2] as u16) << 8) | (self.bytes[3] as u16)
152 }
153
154 #[inline]
158 pub fn hlen(&self) -> u8 {
159 self.bytes[4]
160 }
161
162 #[inline]
166 pub fn plen(&self) -> u8 {
167 self.bytes[5]
168 }
169
170 #[inline]
174 pub fn oper(&self) -> u16 {
175 ((self.bytes[6] as u16) << 8) | (self.bytes[7] as u16)
176 }
177
178 #[inline]
182 pub fn sha(&self) -> &[u8] {
183 &self.bytes[8..14]
184 }
185
186 #[inline]
190 pub fn spa(&self) -> &[u8] {
191 &self.bytes[14..18]
192 }
193
194 #[inline]
198 pub fn tha(&self) -> &[u8] {
199 &self.bytes[18..24]
200 }
201
202 #[inline]
206 pub fn tpa(&self) -> &[u8] {
207 &self.bytes[24..28]
208 }
209
210 #[inline]
212 pub fn header_len(&self) -> usize {
213 ARP_HEADER_LENGTH
214 }
215
216 #[inline]
218 pub fn header(&self) -> &'a [u8] {
219 &self.bytes[..ARP_HEADER_LENGTH]
220 }
221
222 #[inline]
224 pub fn payload(&self) -> &[u8] {
225 &self.bytes[ARP_HEADER_LENGTH..]
226 }
227}
228
229impl fmt::Debug for ArpReader<'_> {
230 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231 let sender_ip = self.spa();
232 let target_ip = self.tpa();
233 let mut sha_buf = [0u8; 18];
234 let sha_len = bytes_to_mac(self.sha(), &mut sha_buf);
235 let sha_hex = from_utf8(&sha_buf[..sha_len]).unwrap();
236 let mut tha_buf = [0u8; 18];
237 let tha_len = bytes_to_mac(self.tha(), &mut tha_buf);
238 let tha_hex = from_utf8(&tha_buf[..tha_len]).unwrap();
239 f.debug_struct("Arp")
240 .field("hardware_type", &self.htype())
241 .field("protocol_type", &self.ptype())
242 .field("hardware_address_length", &self.hlen())
243 .field("protocol_address_length", &self.plen())
244 .field("operation", &self.oper())
245 .field("sender_hardware_address", &sha_hex)
246 .field("sender_protocol_address", &IpFormatter(sender_ip))
247 .field("target_hardware_address", &tha_hex)
248 .field("target_protocol_address", &IpFormatter(target_ip))
249 .finish()
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256
257 #[test]
258 fn getters_and_setters() {
259 let mut bytes = [0; 28];
261
262 let mut writer = ArpWriter::new(&mut bytes).unwrap();
264
265 writer.set_htype(1);
267 writer.set_ptype(2);
268 writer.set_hlen(3);
269 writer.set_plen(4);
270 writer.set_oper(5);
271 writer.set_sha(&[6, 7, 8, 9, 10, 11]);
272 writer.set_spa(&[12, 13, 14, 15]);
273 writer.set_tha(&[16, 17, 18, 19, 20, 21]);
274 writer.set_tpa(&[22, 23, 24, 25]);
275
276 let reader = ArpReader::new(&bytes).unwrap();
278
279 assert_eq!(reader.ptype(), 2);
281 assert_eq!(reader.htype(), 1);
282 assert_eq!(reader.hlen(), 3);
283 assert_eq!(reader.plen(), 4);
284 assert_eq!(reader.oper(), 5);
285 assert_eq!(reader.sha(), &[6, 7, 8, 9, 10, 11]);
286 assert_eq!(reader.spa(), &[12, 13, 14, 15]);
287 assert_eq!(reader.tha(), &[16, 17, 18, 19, 20, 21]);
288 assert_eq!(reader.tpa(), &[22, 23, 24, 25]);
289 }
290}