1use crate::{
4 ethernet::{ETHERNET_HEADER_LEN, EtherType},
5 packet::{MutablePacket, Packet},
6};
7
8use bytes::{Bytes, BytesMut};
9use core::fmt;
10use nex_core::mac::MacAddr;
11use std::net::Ipv4Addr;
12
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15
16pub const ARP_HEADER_LEN: usize = 28;
18pub const ARP_PACKET_LEN: usize = ETHERNET_HEADER_LEN + ARP_HEADER_LEN;
20
21#[repr(u16)]
23#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub enum ArpOperation {
26 Request = 1,
28 Reply = 2,
30 RarpRequest = 3,
32 RarpReply = 4,
34 InRequest = 8,
36 InReply = 9,
38 Nak = 10,
40 Unknown(u16),
42}
43
44impl ArpOperation {
45 pub fn new(value: u16) -> ArpOperation {
47 match value {
48 1 => ArpOperation::Request,
49 2 => ArpOperation::Reply,
50 3 => ArpOperation::RarpRequest,
51 4 => ArpOperation::RarpReply,
52 8 => ArpOperation::InRequest,
53 9 => ArpOperation::InReply,
54 10 => ArpOperation::Nak,
55 _ => ArpOperation::Unknown(value),
56 }
57 }
58 pub fn name(&self) -> &str {
60 match self {
61 ArpOperation::Request => "ARP Request",
62 ArpOperation::Reply => "ARP Reply",
63 ArpOperation::RarpRequest => "RARP Request",
64 ArpOperation::RarpReply => "RARP Reply",
65 ArpOperation::InRequest => "InARP Request",
66 ArpOperation::InReply => "InARP Reply",
67 ArpOperation::Nak => "ARP NAK",
68 ArpOperation::Unknown(_) => "Unknown ARP Operation",
69 }
70 }
71 pub fn value(&self) -> u16 {
73 match self {
74 ArpOperation::Request => 1,
75 ArpOperation::Reply => 2,
76 ArpOperation::RarpRequest => 3,
77 ArpOperation::RarpReply => 4,
78 ArpOperation::InRequest => 8,
79 ArpOperation::InReply => 9,
80 ArpOperation::Nak => 10,
81 ArpOperation::Unknown(value) => *value,
82 }
83 }
84}
85
86#[repr(u16)]
88#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
89#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
90pub enum ArpHardwareType {
91 Ethernet = 1,
93 ExperimentalEthernet = 2,
95 AmateurRadioAX25 = 3,
97 ProteonProNETTokenRing = 4,
99 Chaos = 5,
101 IEEE802Networks = 6,
103 ARCNET = 7,
105 Hyperchannel = 8,
107 Lanstar = 9,
109 AutonetShortAddress = 10,
111 LocalTalk = 11,
113 LocalNet = 12,
115 UltraLink = 13,
117 SMDS = 14,
119 FrameRelay = 15,
121 AsynchronousTransmissionMode = 16,
123 HDLC = 17,
125 FibreChannel = 18,
127 AsynchronousTransmissionMode2 = 19,
129 SerialLine = 20,
131 AsynchronousTransmissionMode3 = 21,
133 MILSTD188220 = 22,
135 Metricom = 23,
137 IEEE13941995 = 24,
139 MAPOS = 25,
141 Twinaxial = 26,
143 EUI64 = 27,
145 HIPARP = 28,
147 IPandARPoverISO78163 = 29,
149 ARPSec = 30,
151 IPsecTunnel = 31,
153 InfiniBand = 32,
155 TIA102Project25CommonAirInterface = 16384,
157 WiegandInterface = 16385,
159 PureIP = 16386,
161 HWEXP1 = 65280,
163 HWEXP2 = 65281,
165 AEthernet = 65282,
167 Unknown(u16),
169}
170
171impl ArpHardwareType {
172 pub fn new(value: u16) -> ArpHardwareType {
173 match value {
174 1 => ArpHardwareType::Ethernet,
175 2 => ArpHardwareType::ExperimentalEthernet,
176 3 => ArpHardwareType::AmateurRadioAX25,
177 4 => ArpHardwareType::ProteonProNETTokenRing,
178 5 => ArpHardwareType::Chaos,
179 6 => ArpHardwareType::IEEE802Networks,
180 7 => ArpHardwareType::ARCNET,
181 8 => ArpHardwareType::Hyperchannel,
182 9 => ArpHardwareType::Lanstar,
183 10 => ArpHardwareType::AutonetShortAddress,
184 11 => ArpHardwareType::LocalTalk,
185 12 => ArpHardwareType::LocalNet,
186 13 => ArpHardwareType::UltraLink,
187 14 => ArpHardwareType::SMDS,
188 15 => ArpHardwareType::FrameRelay,
189 16 => ArpHardwareType::AsynchronousTransmissionMode,
190 17 => ArpHardwareType::HDLC,
191 18 => ArpHardwareType::FibreChannel,
192 19 => ArpHardwareType::AsynchronousTransmissionMode2,
193 20 => ArpHardwareType::SerialLine,
194 21 => ArpHardwareType::AsynchronousTransmissionMode3,
195 22 => ArpHardwareType::MILSTD188220,
196 23 => ArpHardwareType::Metricom,
197 24 => ArpHardwareType::IEEE13941995,
198 25 => ArpHardwareType::MAPOS,
199 26 => ArpHardwareType::Twinaxial,
200 27 => ArpHardwareType::EUI64,
201 28 => ArpHardwareType::HIPARP,
202 29 => ArpHardwareType::IPandARPoverISO78163,
203 30 => ArpHardwareType::ARPSec,
204 31 => ArpHardwareType::IPsecTunnel,
205 32 => ArpHardwareType::InfiniBand,
206 16384 => ArpHardwareType::TIA102Project25CommonAirInterface,
207 16385 => ArpHardwareType::WiegandInterface,
208 16386 => ArpHardwareType::PureIP,
209 65280 => ArpHardwareType::HWEXP1,
210 65281 => ArpHardwareType::HWEXP2,
211 65282 => ArpHardwareType::AEthernet,
212 _ => ArpHardwareType::Unknown(value),
213 }
214 }
215 pub fn name(&self) -> &str {
217 match self {
218 ArpHardwareType::Ethernet => "Ethernet",
219 ArpHardwareType::ExperimentalEthernet => "Experimental Ethernet",
220 ArpHardwareType::AmateurRadioAX25 => "Amateur Radio AX.25",
221 ArpHardwareType::ProteonProNETTokenRing => "Proteon ProNET Token Ring",
222 ArpHardwareType::Chaos => "Chaos",
223 ArpHardwareType::IEEE802Networks => "IEEE 802 Networks",
224 ArpHardwareType::ARCNET => "ARCNET",
225 ArpHardwareType::Hyperchannel => "Hyperchannel",
226 ArpHardwareType::Lanstar => "Lanstar",
227 ArpHardwareType::AutonetShortAddress => "Autonet Short Address",
228 ArpHardwareType::LocalTalk => "LocalTalk",
229 ArpHardwareType::LocalNet => "LocalNet (IBM PCNet or SYTEK LocalNET)",
230 ArpHardwareType::UltraLink => "Ultra link",
231 ArpHardwareType::SMDS => "SMDS",
232 ArpHardwareType::FrameRelay => "Frame Relay",
233 ArpHardwareType::AsynchronousTransmissionMode => "Asynchronous Transmission Mode (ATM)",
234 ArpHardwareType::HDLC => "HDLC",
235 ArpHardwareType::FibreChannel => "Fibre Channel",
236 ArpHardwareType::AsynchronousTransmissionMode2 => {
237 "Asynchronous Transmission Mode (ATM) 2"
238 }
239 ArpHardwareType::SerialLine => "Serial Line",
240 ArpHardwareType::AsynchronousTransmissionMode3 => {
241 "Asynchronous Transmission Mode (ATM) 3"
242 }
243 ArpHardwareType::MILSTD188220 => "MIL-STD-188-220",
244 ArpHardwareType::Metricom => "Metricom",
245 ArpHardwareType::IEEE13941995 => "IEEE 1394.1995",
246 ArpHardwareType::MAPOS => "MAPOS",
247 ArpHardwareType::Twinaxial => "Twinaxial",
248 ArpHardwareType::EUI64 => "EUI-64",
249 ArpHardwareType::HIPARP => "HIPARP",
250 ArpHardwareType::IPandARPoverISO78163 => "IP and ARP over ISO 7816-3",
251 ArpHardwareType::ARPSec => "ARPSec",
252 ArpHardwareType::IPsecTunnel => "IPsec Tunnel",
253 ArpHardwareType::InfiniBand => "InfiniBand (TM)",
254 ArpHardwareType::TIA102Project25CommonAirInterface => {
255 "TIA-102 Project 25 Common Air Interface"
256 }
257 ArpHardwareType::WiegandInterface => "Wiegand Interface",
258 ArpHardwareType::PureIP => "Pure IP",
259 ArpHardwareType::HWEXP1 => "HW_EXP1",
260 ArpHardwareType::HWEXP2 => "HW_EXP2",
261 ArpHardwareType::AEthernet => "AEthernet",
262 ArpHardwareType::Unknown(_) => "Unknown ARP Hardware Type",
263 }
264 }
265 pub fn value(&self) -> u16 {
267 match self {
268 ArpHardwareType::Ethernet => 1,
269 ArpHardwareType::ExperimentalEthernet => 2,
270 ArpHardwareType::AmateurRadioAX25 => 3,
271 ArpHardwareType::ProteonProNETTokenRing => 4,
272 ArpHardwareType::Chaos => 5,
273 ArpHardwareType::IEEE802Networks => 6,
274 ArpHardwareType::ARCNET => 7,
275 ArpHardwareType::Hyperchannel => 8,
276 ArpHardwareType::Lanstar => 9,
277 ArpHardwareType::AutonetShortAddress => 10,
278 ArpHardwareType::LocalTalk => 11,
279 ArpHardwareType::LocalNet => 12,
280 ArpHardwareType::UltraLink => 13,
281 ArpHardwareType::SMDS => 14,
282 ArpHardwareType::FrameRelay => 15,
283 ArpHardwareType::AsynchronousTransmissionMode => 16,
284 ArpHardwareType::HDLC => 17,
285 ArpHardwareType::FibreChannel => 18,
286 ArpHardwareType::AsynchronousTransmissionMode2 => 19,
287 ArpHardwareType::SerialLine => 20,
288 ArpHardwareType::AsynchronousTransmissionMode3 => 21,
289 ArpHardwareType::MILSTD188220 => 22,
290 ArpHardwareType::Metricom => 23,
291 ArpHardwareType::IEEE13941995 => 24,
292 ArpHardwareType::MAPOS => 25,
293 ArpHardwareType::Twinaxial => 26,
294 ArpHardwareType::EUI64 => 27,
295 ArpHardwareType::HIPARP => 28,
296 ArpHardwareType::IPandARPoverISO78163 => 29,
297 ArpHardwareType::ARPSec => 30,
298 ArpHardwareType::IPsecTunnel => 31,
299 ArpHardwareType::InfiniBand => 32,
300 ArpHardwareType::TIA102Project25CommonAirInterface => 16384,
301 ArpHardwareType::WiegandInterface => 16385,
302 ArpHardwareType::PureIP => 16386,
303 ArpHardwareType::HWEXP1 => 65280,
304 ArpHardwareType::HWEXP2 => 65281,
305 ArpHardwareType::AEthernet => 65282,
306 ArpHardwareType::Unknown(value) => *value,
307 }
308 }
309}
310
311#[derive(Clone, Debug, PartialEq, Eq)]
313#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
314pub struct ArpHeader {
315 pub hardware_type: ArpHardwareType,
316 pub protocol_type: EtherType,
317 pub hw_addr_len: u8,
318 pub proto_addr_len: u8,
319 pub operation: ArpOperation,
320 pub sender_hw_addr: MacAddr,
321 pub sender_proto_addr: Ipv4Addr,
322 pub target_hw_addr: MacAddr,
323 pub target_proto_addr: Ipv4Addr,
324}
325
326#[derive(Clone, Debug, PartialEq, Eq)]
328#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
329pub struct ArpPacket {
330 pub header: ArpHeader,
332 pub payload: Bytes,
334}
335
336impl Packet for ArpPacket {
337 type Header = ArpHeader;
338 fn from_buf(bytes: &[u8]) -> Option<Self> {
339 if bytes.len() < ARP_HEADER_LEN {
340 return None;
341 }
342 let hardware_type = ArpHardwareType::new(u16::from_be_bytes([bytes[0], bytes[1]]));
343 let protocol_type = EtherType::new(u16::from_be_bytes([bytes[2], bytes[3]]));
344 let hw_addr_len = bytes[4];
345 let proto_addr_len = bytes[5];
346 let operation = ArpOperation::new(u16::from_be_bytes([bytes[6], bytes[7]]));
347 let sender_hw_addr = MacAddr::from_octets(bytes[8..14].try_into().unwrap());
348 let sender_proto_addr = Ipv4Addr::new(bytes[14], bytes[15], bytes[16], bytes[17]);
349 let target_hw_addr = MacAddr::from_octets(bytes[18..24].try_into().unwrap());
350 let target_proto_addr = Ipv4Addr::new(bytes[24], bytes[25], bytes[26], bytes[27]);
351 let payload = Bytes::copy_from_slice(&bytes[ARP_HEADER_LEN..]);
352
353 Some(ArpPacket {
354 header: ArpHeader {
355 hardware_type,
356 protocol_type,
357 hw_addr_len,
358 proto_addr_len,
359 operation,
360 sender_hw_addr,
361 sender_proto_addr,
362 target_hw_addr,
363 target_proto_addr,
364 },
365 payload,
366 })
367 }
368 fn from_bytes(bytes: Bytes) -> Option<Self> {
369 Self::from_buf(&bytes)
370 }
371
372 fn to_bytes(&self) -> Bytes {
373 let mut buf = Vec::with_capacity(ARP_HEADER_LEN + self.payload.len());
374 buf.extend_from_slice(&self.header.hardware_type.value().to_be_bytes());
375 buf.extend_from_slice(&self.header.protocol_type.value().to_be_bytes());
376 buf.push(self.header.hw_addr_len);
377 buf.push(self.header.proto_addr_len);
378 buf.extend_from_slice(&self.header.operation.value().to_be_bytes());
379 buf.extend_from_slice(&self.header.sender_hw_addr.octets());
380 buf.extend_from_slice(&self.header.sender_proto_addr.octets());
381 buf.extend_from_slice(&self.header.target_hw_addr.octets());
382 buf.extend_from_slice(&self.header.target_proto_addr.octets());
383 buf.extend_from_slice(&self.payload);
384
385 Bytes::from(buf)
386 }
387
388 fn header(&self) -> Bytes {
389 self.to_bytes()
390 }
391
392 fn payload(&self) -> Bytes {
393 self.payload.clone()
394 }
395
396 fn header_len(&self) -> usize {
397 ARP_HEADER_LEN
398 }
399 fn payload_len(&self) -> usize {
400 self.payload.len()
401 }
402 fn total_len(&self) -> usize {
403 ARP_HEADER_LEN + self.payload.len()
404 }
405 fn to_bytes_mut(&self) -> BytesMut {
406 let mut buf = BytesMut::with_capacity(self.total_len());
407 buf.extend_from_slice(&self.to_bytes());
408 buf
409 }
410 fn header_mut(&self) -> BytesMut {
411 let mut buf = BytesMut::with_capacity(self.header_len());
412 buf.extend_from_slice(&self.header());
413 buf
414 }
415 fn payload_mut(&self) -> BytesMut {
416 let mut buf = BytesMut::with_capacity(self.payload_len());
417 buf.extend_from_slice(&self.payload());
418 buf
419 }
420
421 fn into_parts(self) -> (Self::Header, Bytes) {
422 (self.header, self.payload)
423 }
424}
425
426impl ArpPacket {
427 pub fn new(header: ArpHeader, payload: Bytes) -> Self {
429 ArpPacket { header, payload }
430 }
431}
432
433impl fmt::Display for ArpPacket {
434 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
435 write!(
436 f,
437 "ArpPacket {{ hardware_type: {}, protocol_type: {}, hw_addr_len: {}, proto_addr_len: {}, operation: {}, sender_hw_addr: {}, sender_proto_addr: {}, target_hw_addr: {}, target_proto_addr: {} }}",
438 self.header.hardware_type.name(),
439 self.header.protocol_type.name(),
440 self.header.hw_addr_len,
441 self.header.proto_addr_len,
442 self.header.operation.name(),
443 self.header.sender_hw_addr,
444 self.header.sender_proto_addr,
445 self.header.target_hw_addr,
446 self.header.target_proto_addr
447 )
448 }
449}
450
451pub struct MutableArpPacket<'a> {
453 buffer: &'a mut [u8],
454}
455
456impl<'a> MutablePacket<'a> for MutableArpPacket<'a> {
457 type Packet = ArpPacket;
458
459 fn new(buffer: &'a mut [u8]) -> Option<Self> {
460 if buffer.len() < ARP_HEADER_LEN {
461 None
462 } else {
463 Some(Self { buffer })
464 }
465 }
466
467 fn packet(&self) -> &[u8] {
468 &*self.buffer
469 }
470
471 fn packet_mut(&mut self) -> &mut [u8] {
472 &mut *self.buffer
473 }
474
475 fn header(&self) -> &[u8] {
476 &self.packet()[..ARP_HEADER_LEN]
477 }
478
479 fn header_mut(&mut self) -> &mut [u8] {
480 let (header, _) = (&mut *self.buffer).split_at_mut(ARP_HEADER_LEN);
481 header
482 }
483
484 fn payload(&self) -> &[u8] {
485 &self.packet()[ARP_HEADER_LEN..]
486 }
487
488 fn payload_mut(&mut self) -> &mut [u8] {
489 let (_, payload) = (&mut *self.buffer).split_at_mut(ARP_HEADER_LEN);
490 payload
491 }
492}
493
494impl<'a> MutableArpPacket<'a> {
495 pub fn new_unchecked(buffer: &'a mut [u8]) -> Self {
497 Self { buffer }
498 }
499
500 fn raw(&self) -> &[u8] {
501 &*self.buffer
502 }
503
504 fn raw_mut(&mut self) -> &mut [u8] {
505 &mut *self.buffer
506 }
507
508 pub fn get_hardware_type(&self) -> ArpHardwareType {
509 ArpHardwareType::new(u16::from_be_bytes([self.raw()[0], self.raw()[1]]))
510 }
511
512 pub fn set_hardware_type(&mut self, ty: ArpHardwareType) {
513 self.raw_mut()[0..2].copy_from_slice(&ty.value().to_be_bytes());
514 }
515
516 pub fn get_protocol_type(&self) -> EtherType {
517 EtherType::new(u16::from_be_bytes([self.raw()[2], self.raw()[3]]))
518 }
519
520 pub fn set_protocol_type(&mut self, ty: EtherType) {
521 self.raw_mut()[2..4].copy_from_slice(&ty.value().to_be_bytes());
522 }
523
524 pub fn get_hw_addr_len(&self) -> u8 {
525 self.raw()[4]
526 }
527
528 pub fn set_hw_addr_len(&mut self, len: u8) {
529 self.raw_mut()[4] = len;
530 }
531
532 pub fn get_proto_addr_len(&self) -> u8 {
533 self.raw()[5]
534 }
535
536 pub fn set_proto_addr_len(&mut self, len: u8) {
537 self.raw_mut()[5] = len;
538 }
539
540 pub fn get_operation(&self) -> ArpOperation {
541 ArpOperation::new(u16::from_be_bytes([self.raw()[6], self.raw()[7]]))
542 }
543
544 pub fn set_operation(&mut self, op: ArpOperation) {
545 self.raw_mut()[6..8].copy_from_slice(&op.value().to_be_bytes());
546 }
547
548 pub fn get_sender_hw_addr(&self) -> MacAddr {
549 MacAddr::from_octets(self.raw()[8..14].try_into().unwrap())
550 }
551
552 pub fn set_sender_hw_addr(&mut self, addr: MacAddr) {
553 self.raw_mut()[8..14].copy_from_slice(&addr.octets());
554 }
555
556 pub fn get_sender_proto_addr(&self) -> Ipv4Addr {
557 Ipv4Addr::new(
558 self.raw()[14],
559 self.raw()[15],
560 self.raw()[16],
561 self.raw()[17],
562 )
563 }
564
565 pub fn set_sender_proto_addr(&mut self, addr: Ipv4Addr) {
566 self.raw_mut()[14..18].copy_from_slice(&addr.octets());
567 }
568
569 pub fn get_target_hw_addr(&self) -> MacAddr {
570 MacAddr::from_octets(self.raw()[18..24].try_into().unwrap())
571 }
572
573 pub fn set_target_hw_addr(&mut self, addr: MacAddr) {
574 self.raw_mut()[18..24].copy_from_slice(&addr.octets());
575 }
576
577 pub fn get_target_proto_addr(&self) -> Ipv4Addr {
578 Ipv4Addr::new(
579 self.raw()[24],
580 self.raw()[25],
581 self.raw()[26],
582 self.raw()[27],
583 )
584 }
585
586 pub fn set_target_proto_addr(&mut self, addr: Ipv4Addr) {
587 self.raw_mut()[24..28].copy_from_slice(&addr.octets());
588 }
589}
590
591#[cfg(test)]
592mod tests {
593 use super::*;
594 #[test]
595 fn test_parse_valid_arp_packet() {
596 let raw = [
597 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 192, 168, 1, 1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192, 168, 1, 2, ];
607
608 let padded = [&raw[..], &[0xde, 0xad, 0xbe, 0xef]].concat();
609 let packet = ArpPacket::from_bytes(Bytes::copy_from_slice(&padded)).unwrap();
610
611 assert_eq!(packet.header.hardware_type, ArpHardwareType::Ethernet);
612 assert_eq!(packet.header.protocol_type, EtherType::Ipv4);
613 assert_eq!(packet.header.hw_addr_len, 6);
614 assert_eq!(packet.header.proto_addr_len, 4);
615 assert_eq!(packet.header.operation, ArpOperation::Request);
616 assert_eq!(
617 packet.header.sender_hw_addr,
618 MacAddr::from_octets([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff])
619 );
620 assert_eq!(
621 packet.header.sender_proto_addr,
622 Ipv4Addr::new(192, 168, 1, 1)
623 );
624 assert_eq!(
625 packet.header.target_hw_addr,
626 MacAddr::from_octets([0, 0, 0, 0, 0, 0])
627 );
628 assert_eq!(
629 packet.header.target_proto_addr,
630 Ipv4Addr::new(192, 168, 1, 2)
631 );
632 assert_eq!(
633 packet.payload,
634 Bytes::from_static(&[0xde, 0xad, 0xbe, 0xef])
635 );
636 }
637
638 #[test]
639 fn test_serialize_roundtrip() {
640 let original = ArpPacket {
641 header: ArpHeader {
642 hardware_type: ArpHardwareType::Ethernet,
643 protocol_type: EtherType::Ipv4,
644 hw_addr_len: 6,
645 proto_addr_len: 4,
646 operation: ArpOperation::Reply,
647 sender_hw_addr: MacAddr::from_octets([1, 2, 3, 4, 5, 6]),
648 sender_proto_addr: Ipv4Addr::new(10, 0, 0, 1),
649 target_hw_addr: MacAddr::from_octets([10, 20, 30, 40, 50, 60]),
650 target_proto_addr: Ipv4Addr::new(10, 0, 0, 2),
651 },
652 payload: Bytes::from_static(&[0xbe, 0xef]),
653 };
654
655 let bytes = original.to_bytes();
656 let parsed = ArpPacket::from_bytes(bytes).unwrap();
657 assert_eq!(original, parsed);
658 }
659
660 #[test]
661 fn test_parse_invalid_short_packet() {
662 let short = Bytes::from_static(&[0u8; 10]);
663 assert!(ArpPacket::from_bytes(short).is_none());
664 }
665
666 #[test]
667 fn test_unknown_operation_and_hw_type() {
668 let raw = [
669 0x99, 0x99, 0x08, 0x00, 0x06, 0x04, 0x99, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 192, 168, 1, 1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 192, 168, 1, 2, 0x00, 0x01, 0x02, 0x03,
674 ];
675
676 let packet = ArpPacket::from_bytes(Bytes::copy_from_slice(&raw)).unwrap();
677 match packet.header.hardware_type {
678 ArpHardwareType::Unknown(v) => assert_eq!(v, 0x9999),
679 _ => panic!("Expected unknown hardware type"),
680 }
681 match packet.header.operation {
682 ArpOperation::Unknown(v) => assert_eq!(v, 0x9999),
683 _ => panic!("Expected unknown operation"),
684 }
685 }
686
687 #[test]
688 fn test_mutable_arp_packet_updates() {
689 let mut raw = [
690 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 192, 168, 1, 1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192, 168, 1, 2, 0xde, 0xad, 0xbe, 0xef, ];
701
702 let mut packet = MutableArpPacket::new(&mut raw).expect("mutable arp");
703 assert_eq!(packet.get_operation(), ArpOperation::Request);
704 packet.set_operation(ArpOperation::Reply);
705 packet.set_sender_proto_addr(Ipv4Addr::new(10, 0, 0, 1));
706 packet.payload_mut()[0] = 0xaa;
707
708 let frozen = packet.freeze().expect("freeze");
709 assert_eq!(frozen.header.operation, ArpOperation::Reply);
710 assert_eq!(frozen.header.sender_proto_addr, Ipv4Addr::new(10, 0, 0, 1));
711 assert_eq!(frozen.payload[0], 0xaa);
712 }
713}