1use byteorder::{ByteOrder, NetworkEndian};
2use core::fmt;
3
4use super::{Error, Result};
5
6pub use super::EthernetProtocol as Protocol;
7
8enum_with_unknown! {
9 pub enum Hardware(u16) {
11 Ethernet = 1
12 }
13}
14
15enum_with_unknown! {
16 pub enum Operation(u16) {
18 Request = 1,
19 Reply = 2
20 }
21}
22
23#[derive(Debug, PartialEq, Eq, Clone)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub struct Packet<T: AsRef<[u8]>> {
27 buffer: T,
28}
29
30mod field {
31 #![allow(non_snake_case)]
32
33 use crate::wire::field::*;
34
35 pub const HTYPE: Field = 0..2;
36 pub const PTYPE: Field = 2..4;
37 pub const HLEN: usize = 4;
38 pub const PLEN: usize = 5;
39 pub const OPER: Field = 6..8;
40
41 #[inline]
42 pub const fn SHA(hardware_len: u8, _protocol_len: u8) -> Field {
43 let start = OPER.end;
44 start..(start + hardware_len as usize)
45 }
46
47 #[inline]
48 pub const fn SPA(hardware_len: u8, protocol_len: u8) -> Field {
49 let start = SHA(hardware_len, protocol_len).end;
50 start..(start + protocol_len as usize)
51 }
52
53 #[inline]
54 pub const fn THA(hardware_len: u8, protocol_len: u8) -> Field {
55 let start = SPA(hardware_len, protocol_len).end;
56 start..(start + hardware_len as usize)
57 }
58
59 #[inline]
60 pub const fn TPA(hardware_len: u8, protocol_len: u8) -> Field {
61 let start = THA(hardware_len, protocol_len).end;
62 start..(start + protocol_len as usize)
63 }
64}
65
66impl<T: AsRef<[u8]>> Packet<T> {
67 pub const fn new_unchecked(buffer: T) -> Packet<T> {
69 Packet { buffer }
70 }
71
72 pub fn new_checked(buffer: T) -> Result<Packet<T>> {
77 let packet = Self::new_unchecked(buffer);
78 packet.check_len()?;
79 Ok(packet)
80 }
81
82 #[allow(clippy::if_same_then_else)]
91 pub fn check_len(&self) -> Result<()> {
92 let len = self.buffer.as_ref().len();
93 if len < field::OPER.end {
94 Err(Error)
95 } else if len < field::TPA(self.hardware_len(), self.protocol_len()).end {
96 Err(Error)
97 } else {
98 Ok(())
99 }
100 }
101
102 pub fn into_inner(self) -> T {
104 self.buffer
105 }
106
107 #[inline]
109 pub fn hardware_type(&self) -> Hardware {
110 let data = self.buffer.as_ref();
111 let raw = NetworkEndian::read_u16(&data[field::HTYPE]);
112 Hardware::from(raw)
113 }
114
115 #[inline]
117 pub fn protocol_type(&self) -> Protocol {
118 let data = self.buffer.as_ref();
119 let raw = NetworkEndian::read_u16(&data[field::PTYPE]);
120 Protocol::from(raw)
121 }
122
123 #[inline]
125 pub fn hardware_len(&self) -> u8 {
126 let data = self.buffer.as_ref();
127 data[field::HLEN]
128 }
129
130 #[inline]
132 pub fn protocol_len(&self) -> u8 {
133 let data = self.buffer.as_ref();
134 data[field::PLEN]
135 }
136
137 #[inline]
139 pub fn operation(&self) -> Operation {
140 let data = self.buffer.as_ref();
141 let raw = NetworkEndian::read_u16(&data[field::OPER]);
142 Operation::from(raw)
143 }
144
145 pub fn source_hardware_addr(&self) -> &[u8] {
147 let data = self.buffer.as_ref();
148 &data[field::SHA(self.hardware_len(), self.protocol_len())]
149 }
150
151 pub fn source_protocol_addr(&self) -> &[u8] {
153 let data = self.buffer.as_ref();
154 &data[field::SPA(self.hardware_len(), self.protocol_len())]
155 }
156
157 pub fn target_hardware_addr(&self) -> &[u8] {
159 let data = self.buffer.as_ref();
160 &data[field::THA(self.hardware_len(), self.protocol_len())]
161 }
162
163 pub fn target_protocol_addr(&self) -> &[u8] {
165 let data = self.buffer.as_ref();
166 &data[field::TPA(self.hardware_len(), self.protocol_len())]
167 }
168}
169
170impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
171 #[inline]
173 pub fn set_hardware_type(&mut self, value: Hardware) {
174 let data = self.buffer.as_mut();
175 NetworkEndian::write_u16(&mut data[field::HTYPE], value.into())
176 }
177
178 #[inline]
180 pub fn set_protocol_type(&mut self, value: Protocol) {
181 let data = self.buffer.as_mut();
182 NetworkEndian::write_u16(&mut data[field::PTYPE], value.into())
183 }
184
185 #[inline]
187 pub fn set_hardware_len(&mut self, value: u8) {
188 let data = self.buffer.as_mut();
189 data[field::HLEN] = value
190 }
191
192 #[inline]
194 pub fn set_protocol_len(&mut self, value: u8) {
195 let data = self.buffer.as_mut();
196 data[field::PLEN] = value
197 }
198
199 #[inline]
201 pub fn set_operation(&mut self, value: Operation) {
202 let data = self.buffer.as_mut();
203 NetworkEndian::write_u16(&mut data[field::OPER], value.into())
204 }
205
206 pub fn set_source_hardware_addr(&mut self, value: &[u8]) {
211 let (hardware_len, protocol_len) = (self.hardware_len(), self.protocol_len());
212 let data = self.buffer.as_mut();
213 data[field::SHA(hardware_len, protocol_len)].copy_from_slice(value)
214 }
215
216 pub fn set_source_protocol_addr(&mut self, value: &[u8]) {
221 let (hardware_len, protocol_len) = (self.hardware_len(), self.protocol_len());
222 let data = self.buffer.as_mut();
223 data[field::SPA(hardware_len, protocol_len)].copy_from_slice(value)
224 }
225
226 pub fn set_target_hardware_addr(&mut self, value: &[u8]) {
231 let (hardware_len, protocol_len) = (self.hardware_len(), self.protocol_len());
232 let data = self.buffer.as_mut();
233 data[field::THA(hardware_len, protocol_len)].copy_from_slice(value)
234 }
235
236 pub fn set_target_protocol_addr(&mut self, value: &[u8]) {
241 let (hardware_len, protocol_len) = (self.hardware_len(), self.protocol_len());
242 let data = self.buffer.as_mut();
243 data[field::TPA(hardware_len, protocol_len)].copy_from_slice(value)
244 }
245}
246
247impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
248 fn as_ref(&self) -> &[u8] {
249 self.buffer.as_ref()
250 }
251}
252
253use crate::wire::{EthernetAddress, Ipv4Address};
254
255#[derive(Debug, PartialEq, Eq, Clone, Copy)]
257#[cfg_attr(feature = "defmt", derive(defmt::Format))]
258#[non_exhaustive]
259pub enum Repr {
260 EthernetIpv4 {
262 operation: Operation,
263 source_hardware_addr: EthernetAddress,
264 source_protocol_addr: Ipv4Address,
265 target_hardware_addr: EthernetAddress,
266 target_protocol_addr: Ipv4Address,
267 },
268}
269
270impl Repr {
271 pub fn parse<T: AsRef<[u8]>>(packet: &Packet<T>) -> Result<Repr> {
274 match (
275 packet.hardware_type(),
276 packet.protocol_type(),
277 packet.hardware_len(),
278 packet.protocol_len(),
279 ) {
280 (Hardware::Ethernet, Protocol::Ipv4, 6, 4) => Ok(Repr::EthernetIpv4 {
281 operation: packet.operation(),
282 source_hardware_addr: EthernetAddress::from_bytes(packet.source_hardware_addr()),
283 source_protocol_addr: Ipv4Address::from_bytes(packet.source_protocol_addr()),
284 target_hardware_addr: EthernetAddress::from_bytes(packet.target_hardware_addr()),
285 target_protocol_addr: Ipv4Address::from_bytes(packet.target_protocol_addr()),
286 }),
287 _ => Err(Error),
288 }
289 }
290
291 pub const fn buffer_len(&self) -> usize {
293 match *self {
294 Repr::EthernetIpv4 { .. } => field::TPA(6, 4).end,
295 }
296 }
297
298 pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>) {
300 match *self {
301 Repr::EthernetIpv4 {
302 operation,
303 source_hardware_addr,
304 source_protocol_addr,
305 target_hardware_addr,
306 target_protocol_addr,
307 } => {
308 packet.set_hardware_type(Hardware::Ethernet);
309 packet.set_protocol_type(Protocol::Ipv4);
310 packet.set_hardware_len(6);
311 packet.set_protocol_len(4);
312 packet.set_operation(operation);
313 packet.set_source_hardware_addr(source_hardware_addr.as_bytes());
314 packet.set_source_protocol_addr(source_protocol_addr.as_bytes());
315 packet.set_target_hardware_addr(target_hardware_addr.as_bytes());
316 packet.set_target_protocol_addr(target_protocol_addr.as_bytes());
317 }
318 }
319 }
320}
321
322impl<T: AsRef<[u8]>> fmt::Display for Packet<T> {
323 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
324 match Repr::parse(self) {
325 Ok(repr) => write!(f, "{repr}"),
326 _ => {
327 write!(f, "ARP (unrecognized)")?;
328 write!(
329 f,
330 " htype={:?} ptype={:?} hlen={:?} plen={:?} op={:?}",
331 self.hardware_type(),
332 self.protocol_type(),
333 self.hardware_len(),
334 self.protocol_len(),
335 self.operation()
336 )?;
337 write!(
338 f,
339 " sha={:?} spa={:?} tha={:?} tpa={:?}",
340 self.source_hardware_addr(),
341 self.source_protocol_addr(),
342 self.target_hardware_addr(),
343 self.target_protocol_addr()
344 )?;
345 Ok(())
346 }
347 }
348 }
349}
350
351impl fmt::Display for Repr {
352 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
353 match *self {
354 Repr::EthernetIpv4 {
355 operation,
356 source_hardware_addr,
357 source_protocol_addr,
358 target_hardware_addr,
359 target_protocol_addr,
360 } => {
361 write!(
362 f,
363 "ARP type=Ethernet+IPv4 src={source_hardware_addr}/{source_protocol_addr} tgt={target_hardware_addr}/{target_protocol_addr} op={operation:?}"
364 )
365 }
366 }
367 }
368}
369
370use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
371
372impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
373 fn pretty_print(
374 buffer: &dyn AsRef<[u8]>,
375 f: &mut fmt::Formatter,
376 indent: &mut PrettyIndent,
377 ) -> fmt::Result {
378 match Packet::new_checked(buffer) {
379 Err(err) => write!(f, "{indent}({err})"),
380 Ok(packet) => write!(f, "{indent}{packet}"),
381 }
382 }
383}
384
385#[cfg(test)]
386mod test {
387 use super::*;
388
389 static PACKET_BYTES: [u8; 28] = [
390 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x21,
391 0x22, 0x23, 0x24, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x41, 0x42, 0x43, 0x44,
392 ];
393
394 #[test]
395 fn test_deconstruct() {
396 let packet = Packet::new_unchecked(&PACKET_BYTES[..]);
397 assert_eq!(packet.hardware_type(), Hardware::Ethernet);
398 assert_eq!(packet.protocol_type(), Protocol::Ipv4);
399 assert_eq!(packet.hardware_len(), 6);
400 assert_eq!(packet.protocol_len(), 4);
401 assert_eq!(packet.operation(), Operation::Request);
402 assert_eq!(
403 packet.source_hardware_addr(),
404 &[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]
405 );
406 assert_eq!(packet.source_protocol_addr(), &[0x21, 0x22, 0x23, 0x24]);
407 assert_eq!(
408 packet.target_hardware_addr(),
409 &[0x31, 0x32, 0x33, 0x34, 0x35, 0x36]
410 );
411 assert_eq!(packet.target_protocol_addr(), &[0x41, 0x42, 0x43, 0x44]);
412 }
413
414 #[test]
415 fn test_construct() {
416 let mut bytes = vec![0xa5; 28];
417 let mut packet = Packet::new_unchecked(&mut bytes);
418 packet.set_hardware_type(Hardware::Ethernet);
419 packet.set_protocol_type(Protocol::Ipv4);
420 packet.set_hardware_len(6);
421 packet.set_protocol_len(4);
422 packet.set_operation(Operation::Request);
423 packet.set_source_hardware_addr(&[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]);
424 packet.set_source_protocol_addr(&[0x21, 0x22, 0x23, 0x24]);
425 packet.set_target_hardware_addr(&[0x31, 0x32, 0x33, 0x34, 0x35, 0x36]);
426 packet.set_target_protocol_addr(&[0x41, 0x42, 0x43, 0x44]);
427 assert_eq!(&*packet.into_inner(), &PACKET_BYTES[..]);
428 }
429
430 fn packet_repr() -> Repr {
431 Repr::EthernetIpv4 {
432 operation: Operation::Request,
433 source_hardware_addr: EthernetAddress::from_bytes(&[
434 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
435 ]),
436 source_protocol_addr: Ipv4Address::from_bytes(&[0x21, 0x22, 0x23, 0x24]),
437 target_hardware_addr: EthernetAddress::from_bytes(&[
438 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
439 ]),
440 target_protocol_addr: Ipv4Address::from_bytes(&[0x41, 0x42, 0x43, 0x44]),
441 }
442 }
443
444 #[test]
445 fn test_parse() {
446 let packet = Packet::new_unchecked(&PACKET_BYTES[..]);
447 let repr = Repr::parse(&packet).unwrap();
448 assert_eq!(repr, packet_repr());
449 }
450
451 #[test]
452 fn test_emit() {
453 let mut bytes = vec![0xa5; 28];
454 let mut packet = Packet::new_unchecked(&mut bytes);
455 packet_repr().emit(&mut packet);
456 assert_eq!(&*packet.into_inner(), &PACKET_BYTES[..]);
457 }
458}