1use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
2
3use crate::layer::field::{Field, FieldDesc, FieldError, FieldType, FieldValue, MacAddress};
4use crate::layer::{Layer, LayerIndex, LayerKind};
5
6pub const ARP_HEADER_LEN: usize = 28;
7pub const ARP_FIXED_HEADER_LEN: usize = 8;
8
9pub mod hardware_type {
11 pub const ETHERNET: u16 = 1;
12 pub const EXPERIMENTAL_ETHERNET: u16 = 2;
13 pub const AX25: u16 = 3;
14 pub const PRONET_TOKEN_RING: u16 = 4;
15 pub const CHAOS: u16 = 5;
16 pub const IEEE802: u16 = 6;
17 pub const ARCNET: u16 = 7;
18 pub const HYPERCHANNEL: u16 = 8;
19 pub const LANSTAR: u16 = 9;
20 pub const AUTONET: u16 = 10;
21 pub const LOCALTALK: u16 = 11;
22 pub const LOCALNET: u16 = 12;
23 pub const ULTRA_LINK: u16 = 13;
24 pub const SMDS: u16 = 14;
25 pub const FRAME_RELAY: u16 = 15;
26 pub const ATM: u16 = 16;
27 pub const HDLC: u16 = 17;
28 pub const FIBRE_CHANNEL: u16 = 18;
29 pub const ATM_2: u16 = 19;
30 pub const SERIAL_LINE: u16 = 20;
31 pub const ATM_3: u16 = 21;
32
33 #[must_use]
34 pub fn name(t: u16) -> &'static str {
35 match t {
36 ETHERNET => "Ethernet (10Mb)",
37 EXPERIMENTAL_ETHERNET => "Experimental Ethernet (3Mb)",
38 AX25 => "AX.25",
39 PRONET_TOKEN_RING => "Proteon ProNET Token Ring",
40 CHAOS => "Chaos",
41 IEEE802 => "IEEE 802 Networks",
42 ARCNET => "ARCNET",
43 HYPERCHANNEL => "Hyperchannel",
44 LANSTAR => "Lanstar",
45 AUTONET => "Autonet Short Address",
46 LOCALTALK => "LocalTalk",
47 LOCALNET => "LocalNet",
48 ULTRA_LINK => "Ultra link",
49 SMDS => "SMDS",
50 FRAME_RELAY => "Frame relay",
51 ATM | ATM_2 | ATM_3 => "ATM",
52 HDLC => "HDLC",
53 FIBRE_CHANNEL => "Fibre Channel",
54 SERIAL_LINE => "Serial Line",
55 _ => "Unknown",
56 }
57 }
58
59 #[inline]
60 #[must_use]
61 pub const fn is_ethernet_like(t: u16) -> bool {
62 matches!(t, ETHERNET | EXPERIMENTAL_ETHERNET | IEEE802)
63 }
64}
65
66pub mod protocol_type {
68 pub const IPV4: u16 = 0x0800;
69 pub const IPV6: u16 = 0x86DD;
70 pub const ARP: u16 = 0x0806;
71
72 #[inline]
73 #[must_use]
74 pub const fn is_ipv4(t: u16) -> bool {
75 t == IPV4
76 }
77 #[inline]
78 #[must_use]
79 pub const fn is_ipv6(t: u16) -> bool {
80 t == IPV6
81 }
82}
83
84pub mod opcode {
86 pub const REQUEST: u16 = 1;
87 pub const REPLY: u16 = 2;
88 pub const RARP_REQUEST: u16 = 3;
89 pub const RARP_REPLY: u16 = 4;
90 pub const DRARP_REQUEST: u16 = 5;
91 pub const DRARP_REPLY: u16 = 6;
92 pub const DRARP_ERROR: u16 = 7;
93 pub const INARP_REQUEST: u16 = 8;
94 pub const INARP_REPLY: u16 = 9;
95
96 #[must_use]
97 pub fn name(op: u16) -> &'static str {
98 match op {
99 REQUEST => "who-has",
100 REPLY => "is-at",
101 RARP_REQUEST => "RARP-req",
102 RARP_REPLY => "RARP-rep",
103 DRARP_REQUEST => "Dyn-RARP-req",
104 DRARP_REPLY => "Dyn-RARP-rep",
105 DRARP_ERROR => "Dyn-RARP-err",
106 INARP_REQUEST => "InARP-req",
107 INARP_REPLY => "InARP-rep",
108 _ => "unknown",
109 }
110 }
111
112 #[must_use]
113 pub fn from_name(name: &str) -> Option<u16> {
114 match name.to_lowercase().as_str() {
115 "who-has" | "request" | "1" => Some(REQUEST),
116 "is-at" | "reply" | "2" => Some(REPLY),
117 "rarp-req" | "3" => Some(RARP_REQUEST),
118 "rarp-rep" | "4" => Some(RARP_REPLY),
119 "dyn-rarp-req" | "5" => Some(DRARP_REQUEST),
120 "dyn-rarp-rep" | "6" => Some(DRARP_REPLY),
121 "dyn-rarp-err" | "7" => Some(DRARP_ERROR),
122 "inarp-req" | "8" => Some(INARP_REQUEST),
123 "inarp-rep" | "9" => Some(INARP_REPLY),
124 _ => None,
125 }
126 }
127
128 #[inline]
129 #[must_use]
130 pub const fn is_request(op: u16) -> bool {
131 op % 2 == 1
132 }
133 #[inline]
134 #[must_use]
135 pub const fn is_reply(op: u16) -> bool {
136 op.is_multiple_of(2) && op > 0
137 }
138 #[inline]
139 #[must_use]
140 pub const fn reply_for(request_op: u16) -> u16 {
141 request_op + 1
142 }
143}
144
145pub mod offsets {
147 pub const HWTYPE: usize = 0;
148 pub const PTYPE: usize = 2;
149 pub const HWLEN: usize = 4;
150 pub const PLEN: usize = 5;
151 pub const OP: usize = 6;
152 pub const VAR_START: usize = 8;
153}
154
155pub static FIXED_FIELDS: &[FieldDesc] = &[
156 FieldDesc::new("hwtype", offsets::HWTYPE, 2, FieldType::U16),
157 FieldDesc::new("ptype", offsets::PTYPE, 2, FieldType::U16),
158 FieldDesc::new("hwlen", offsets::HWLEN, 1, FieldType::U8),
159 FieldDesc::new("plen", offsets::PLEN, 1, FieldType::U8),
160 FieldDesc::new("op", offsets::OP, 2, FieldType::U16),
161];
162
163#[derive(Debug, Clone, PartialEq, Eq)]
165pub enum HardwareAddr {
166 Mac(MacAddress),
167 Raw(Vec<u8>),
168}
169
170impl HardwareAddr {
171 #[must_use]
172 pub fn from_bytes(bytes: &[u8]) -> Self {
173 if bytes.len() == 6 {
174 Self::Mac(MacAddress::new([
175 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5],
176 ]))
177 } else {
178 Self::Raw(bytes.to_vec())
179 }
180 }
181
182 #[must_use]
183 pub fn as_mac(&self) -> Option<MacAddress> {
184 match self {
185 Self::Mac(mac) => Some(*mac),
186 Self::Raw(bytes) if bytes.len() == 6 => Some(MacAddress::new([
187 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5],
188 ])),
189 _ => None,
190 }
191 }
192
193 #[must_use]
194 pub fn as_bytes(&self) -> &[u8] {
195 match self {
196 Self::Mac(mac) => mac.as_bytes(),
197 Self::Raw(bytes) => bytes,
198 }
199 }
200
201 #[must_use]
202 pub fn len(&self) -> usize {
203 match self {
204 Self::Mac(_) => 6,
205 Self::Raw(bytes) => bytes.len(),
206 }
207 }
208
209 #[must_use]
210 pub fn is_empty(&self) -> bool {
211 self.len() == 0
212 }
213 #[must_use]
214 pub fn is_zero(&self) -> bool {
215 self.as_bytes().iter().all(|&b| b == 0)
216 }
217 #[must_use]
218 pub fn is_broadcast(&self) -> bool {
219 self.as_bytes().iter().all(|&b| b == 0xff)
220 }
221}
222
223impl std::fmt::Display for HardwareAddr {
224 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
225 match self {
226 Self::Mac(mac) => write!(f, "{mac}"),
227 Self::Raw(bytes) => {
228 for (i, b) in bytes.iter().enumerate() {
229 if i > 0 {
230 write!(f, ":")?;
231 }
232 write!(f, "{b:02x}")?;
233 }
234 Ok(())
235 },
236 }
237 }
238}
239
240impl From<MacAddress> for HardwareAddr {
241 fn from(mac: MacAddress) -> Self {
242 Self::Mac(mac)
243 }
244}
245
246impl From<Vec<u8>> for HardwareAddr {
247 fn from(bytes: Vec<u8>) -> Self {
248 Self::from_bytes(&bytes)
249 }
250}
251
252#[derive(Debug, Clone, PartialEq, Eq)]
254pub enum ProtocolAddr {
255 Ipv4(Ipv4Addr),
256 Ipv6(Ipv6Addr),
257 Raw(Vec<u8>),
258}
259
260impl ProtocolAddr {
261 #[must_use]
262 pub fn from_bytes(bytes: &[u8], ptype: u16) -> Self {
263 match (bytes.len(), ptype) {
264 (4, protocol_type::IPV4 | _) => {
265 Self::Ipv4(Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]))
266 },
267 (16, protocol_type::IPV6) => {
268 let mut arr = [0u8; 16];
269 arr.copy_from_slice(bytes);
270 Self::Ipv6(Ipv6Addr::from(arr))
271 },
272 _ => Self::Raw(bytes.to_vec()),
273 }
274 }
275
276 #[must_use]
277 pub fn as_ipv4(&self) -> Option<Ipv4Addr> {
278 match self {
279 Self::Ipv4(ip) => Some(*ip),
280 Self::Raw(bytes) if bytes.len() == 4 => {
281 Some(Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]))
282 },
283 _ => None,
284 }
285 }
286
287 #[must_use]
288 pub fn as_ipv6(&self) -> Option<Ipv6Addr> {
289 match self {
290 Self::Ipv6(ip) => Some(*ip),
291 Self::Raw(bytes) if bytes.len() == 16 => {
292 let mut arr = [0u8; 16];
293 arr.copy_from_slice(bytes);
294 Some(Ipv6Addr::from(arr))
295 },
296 _ => None,
297 }
298 }
299
300 #[must_use]
301 pub fn as_bytes(&self) -> Vec<u8> {
302 match self {
303 Self::Ipv4(ip) => ip.octets().to_vec(),
304 Self::Ipv6(ip) => ip.octets().to_vec(),
305 Self::Raw(bytes) => bytes.clone(),
306 }
307 }
308
309 #[must_use]
310 pub fn len(&self) -> usize {
311 match self {
312 Self::Ipv4(_) => 4,
313 Self::Ipv6(_) => 16,
314 Self::Raw(bytes) => bytes.len(),
315 }
316 }
317
318 #[must_use]
319 pub fn is_empty(&self) -> bool {
320 self.len() == 0
321 }
322}
323
324impl std::fmt::Display for ProtocolAddr {
325 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
326 match self {
327 Self::Ipv4(ip) => write!(f, "{ip}"),
328 Self::Ipv6(ip) => write!(f, "{ip}"),
329 Self::Raw(bytes) => {
330 write!(f, "0x")?;
331 for b in bytes {
332 write!(f, "{b:02x}")?;
333 }
334 Ok(())
335 },
336 }
337 }
338}
339
340impl From<Ipv4Addr> for ProtocolAddr {
341 fn from(ip: Ipv4Addr) -> Self {
342 Self::Ipv4(ip)
343 }
344}
345impl From<Ipv6Addr> for ProtocolAddr {
346 fn from(ip: Ipv6Addr) -> Self {
347 Self::Ipv6(ip)
348 }
349}
350impl From<Vec<u8>> for ProtocolAddr {
351 fn from(bytes: Vec<u8>) -> Self {
352 Self::Raw(bytes)
353 }
354}
355
356#[derive(Debug, Clone, Default)]
358pub struct ArpRoute {
359 pub interface: Option<String>,
361 pub source_ip: Option<String>,
363 pub gateway: Option<String>,
365}
366
367#[derive(Debug, Clone)]
369pub struct ArpLayer {
370 pub index: LayerIndex,
371}
372
373impl ArpLayer {
374 #[inline]
375 #[must_use]
376 pub const fn new(start: usize, end: usize) -> Self {
377 Self {
378 index: LayerIndex::new(LayerKind::Arp, start, end),
379 }
380 }
381
382 #[inline]
383 #[must_use]
384 pub const fn at_offset(offset: usize) -> Self {
385 Self::new(offset, offset + ARP_HEADER_LEN)
386 }
387
388 pub fn at_offset_dynamic(buf: &[u8], offset: usize) -> Result<Self, FieldError> {
389 Self::validate(buf, offset)?;
390 let hwlen = buf[offset + offsets::HWLEN] as usize;
391 let plen = buf[offset + offsets::PLEN] as usize;
392 let total_len = ARP_FIXED_HEADER_LEN + 2 * hwlen + 2 * plen;
393 Ok(Self::new(offset, offset + total_len))
394 }
395
396 pub fn validate(buf: &[u8], offset: usize) -> Result<(), FieldError> {
397 if buf.len() < offset + ARP_FIXED_HEADER_LEN {
398 return Err(FieldError::BufferTooShort {
399 offset,
400 need: ARP_FIXED_HEADER_LEN,
401 have: buf.len().saturating_sub(offset),
402 });
403 }
404 let hwlen = buf[offset + offsets::HWLEN] as usize;
405 let plen = buf[offset + offsets::PLEN] as usize;
406 let total_len = ARP_FIXED_HEADER_LEN + 2 * hwlen + 2 * plen;
407 if buf.len() < offset + total_len {
408 return Err(FieldError::BufferTooShort {
409 offset,
410 need: total_len,
411 have: buf.len().saturating_sub(offset),
412 });
413 }
414 Ok(())
415 }
416
417 #[must_use]
418 pub fn calculate_len(&self, buf: &[u8]) -> usize {
419 let hwlen = self.hwlen(buf).unwrap_or(6) as usize;
420 let plen = self.plen(buf).unwrap_or(4) as usize;
421 ARP_FIXED_HEADER_LEN + 2 * hwlen + 2 * plen
422 }
423
424 #[inline]
426 pub fn hwtype(&self, buf: &[u8]) -> Result<u16, FieldError> {
427 u16::read(buf, self.index.start + offsets::HWTYPE)
428 }
429
430 #[inline]
431 pub fn ptype(&self, buf: &[u8]) -> Result<u16, FieldError> {
432 u16::read(buf, self.index.start + offsets::PTYPE)
433 }
434
435 #[inline]
436 pub fn hwlen(&self, buf: &[u8]) -> Result<u8, FieldError> {
437 u8::read(buf, self.index.start + offsets::HWLEN)
438 }
439
440 #[inline]
441 pub fn plen(&self, buf: &[u8]) -> Result<u8, FieldError> {
442 u8::read(buf, self.index.start + offsets::PLEN)
443 }
444
445 #[inline]
446 pub fn op(&self, buf: &[u8]) -> Result<u16, FieldError> {
447 u16::read(buf, self.index.start + offsets::OP)
448 }
449
450 #[inline]
452 pub fn set_hwtype(&self, buf: &mut [u8], val: u16) -> Result<(), FieldError> {
453 val.write(buf, self.index.start + offsets::HWTYPE)
454 }
455
456 #[inline]
457 pub fn set_ptype(&self, buf: &mut [u8], val: u16) -> Result<(), FieldError> {
458 val.write(buf, self.index.start + offsets::PTYPE)
459 }
460
461 #[inline]
462 pub fn set_hwlen(&self, buf: &mut [u8], val: u8) -> Result<(), FieldError> {
463 val.write(buf, self.index.start + offsets::HWLEN)
464 }
465
466 #[inline]
467 pub fn set_plen(&self, buf: &mut [u8], val: u8) -> Result<(), FieldError> {
468 val.write(buf, self.index.start + offsets::PLEN)
469 }
470
471 #[inline]
472 pub fn set_op(&self, buf: &mut [u8], val: u16) -> Result<(), FieldError> {
473 val.write(buf, self.index.start + offsets::OP)
474 }
475
476 #[inline]
478 fn hwsrc_offset(&self) -> usize {
479 self.index.start + offsets::VAR_START
480 }
481
482 fn psrc_offset(&self, buf: &[u8]) -> Result<usize, FieldError> {
483 Ok(self.hwsrc_offset() + self.hwlen(buf)? as usize)
484 }
485
486 fn hwdst_offset(&self, buf: &[u8]) -> Result<usize, FieldError> {
487 let hwlen = self.hwlen(buf)? as usize;
488 let plen = self.plen(buf)? as usize;
489 Ok(self.hwsrc_offset() + hwlen + plen)
490 }
491
492 fn pdst_offset(&self, buf: &[u8]) -> Result<usize, FieldError> {
493 let hwlen = self.hwlen(buf)? as usize;
494 let plen = self.plen(buf)? as usize;
495 Ok(self.hwsrc_offset() + 2 * hwlen + plen)
496 }
497
498 pub fn hwsrc_raw(&self, buf: &[u8]) -> Result<HardwareAddr, FieldError> {
500 let hwlen = self.hwlen(buf)? as usize;
501 let offset = self.hwsrc_offset();
502 if buf.len() < offset + hwlen {
503 return Err(FieldError::BufferTooShort {
504 offset,
505 need: hwlen,
506 have: buf.len().saturating_sub(offset),
507 });
508 }
509 Ok(HardwareAddr::from_bytes(&buf[offset..offset + hwlen]))
510 }
511
512 pub fn hwsrc(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
513 let hwlen = self.hwlen(buf)?;
514 if hwlen != 6 {
515 return Err(FieldError::BufferTooShort {
516 offset: self.hwsrc_offset(),
517 need: 6,
518 have: hwlen as usize,
519 });
520 }
521 MacAddress::read(buf, self.hwsrc_offset())
522 }
523
524 pub fn psrc_raw(&self, buf: &[u8]) -> Result<ProtocolAddr, FieldError> {
525 let plen = self.plen(buf)? as usize;
526 let ptype = self.ptype(buf)?;
527 let offset = self.psrc_offset(buf)?;
528 if buf.len() < offset + plen {
529 return Err(FieldError::BufferTooShort {
530 offset,
531 need: plen,
532 have: buf.len().saturating_sub(offset),
533 });
534 }
535 Ok(ProtocolAddr::from_bytes(&buf[offset..offset + plen], ptype))
536 }
537
538 pub fn psrc(&self, buf: &[u8]) -> Result<Ipv4Addr, FieldError> {
539 Ipv4Addr::read(buf, self.psrc_offset(buf)?)
540 }
541
542 pub fn psrc_v6(&self, buf: &[u8]) -> Result<Ipv6Addr, FieldError> {
543 Ipv6Addr::read(buf, self.psrc_offset(buf)?)
544 }
545
546 pub fn hwdst_raw(&self, buf: &[u8]) -> Result<HardwareAddr, FieldError> {
547 let hwlen = self.hwlen(buf)? as usize;
548 let offset = self.hwdst_offset(buf)?;
549 if buf.len() < offset + hwlen {
550 return Err(FieldError::BufferTooShort {
551 offset,
552 need: hwlen,
553 have: buf.len().saturating_sub(offset),
554 });
555 }
556 Ok(HardwareAddr::from_bytes(&buf[offset..offset + hwlen]))
557 }
558
559 pub fn hwdst(&self, buf: &[u8]) -> Result<MacAddress, FieldError> {
560 MacAddress::read(buf, self.hwdst_offset(buf)?)
561 }
562
563 pub fn pdst_raw(&self, buf: &[u8]) -> Result<ProtocolAddr, FieldError> {
564 let plen = self.plen(buf)? as usize;
565 let ptype = self.ptype(buf)?;
566 let offset = self.pdst_offset(buf)?;
567 if buf.len() < offset + plen {
568 return Err(FieldError::BufferTooShort {
569 offset,
570 need: plen,
571 have: buf.len().saturating_sub(offset),
572 });
573 }
574 Ok(ProtocolAddr::from_bytes(&buf[offset..offset + plen], ptype))
575 }
576
577 pub fn pdst(&self, buf: &[u8]) -> Result<Ipv4Addr, FieldError> {
578 Ipv4Addr::read(buf, self.pdst_offset(buf)?)
579 }
580
581 pub fn pdst_v6(&self, buf: &[u8]) -> Result<Ipv6Addr, FieldError> {
582 Ipv6Addr::read(buf, self.pdst_offset(buf)?)
583 }
584
585 pub fn set_hwsrc(&self, buf: &mut [u8], mac: MacAddress) -> Result<(), FieldError> {
587 mac.write(buf, self.hwsrc_offset())
588 }
589
590 pub fn set_hwsrc_raw(&self, buf: &mut [u8], addr: &HardwareAddr) -> Result<(), FieldError> {
591 let offset = self.hwsrc_offset();
592 let bytes = addr.as_bytes();
593 if buf.len() < offset + bytes.len() {
594 return Err(FieldError::BufferTooShort {
595 offset,
596 need: bytes.len(),
597 have: buf.len().saturating_sub(offset),
598 });
599 }
600 buf[offset..offset + bytes.len()].copy_from_slice(bytes);
601 Ok(())
602 }
603
604 pub fn set_psrc(&self, buf: &mut [u8], ip: Ipv4Addr) -> Result<(), FieldError> {
605 ip.write(buf, self.psrc_offset(buf)?)
606 }
607
608 pub fn set_psrc_v6(&self, buf: &mut [u8], ip: Ipv6Addr) -> Result<(), FieldError> {
609 ip.write(buf, self.psrc_offset(buf)?)
610 }
611
612 pub fn set_psrc_raw(&self, buf: &mut [u8], addr: &ProtocolAddr) -> Result<(), FieldError> {
613 let offset = self.psrc_offset(buf)?;
614 let bytes = addr.as_bytes();
615 if buf.len() < offset + bytes.len() {
616 return Err(FieldError::BufferTooShort {
617 offset,
618 need: bytes.len(),
619 have: buf.len().saturating_sub(offset),
620 });
621 }
622 buf[offset..offset + bytes.len()].copy_from_slice(&bytes);
623 Ok(())
624 }
625
626 pub fn set_hwdst(&self, buf: &mut [u8], mac: MacAddress) -> Result<(), FieldError> {
627 mac.write(buf, self.hwdst_offset(buf)?)
628 }
629
630 pub fn set_hwdst_raw(&self, buf: &mut [u8], addr: &HardwareAddr) -> Result<(), FieldError> {
631 let offset = self.hwdst_offset(buf)?;
632 let bytes = addr.as_bytes();
633 if buf.len() < offset + bytes.len() {
634 return Err(FieldError::BufferTooShort {
635 offset,
636 need: bytes.len(),
637 have: buf.len().saturating_sub(offset),
638 });
639 }
640 buf[offset..offset + bytes.len()].copy_from_slice(bytes);
641 Ok(())
642 }
643
644 pub fn set_pdst(&self, buf: &mut [u8], ip: Ipv4Addr) -> Result<(), FieldError> {
645 ip.write(buf, self.pdst_offset(buf)?)
646 }
647
648 pub fn set_pdst_v6(&self, buf: &mut [u8], ip: Ipv6Addr) -> Result<(), FieldError> {
649 ip.write(buf, self.pdst_offset(buf)?)
650 }
651
652 pub fn set_pdst_raw(&self, buf: &mut [u8], addr: &ProtocolAddr) -> Result<(), FieldError> {
653 let offset = self.pdst_offset(buf)?;
654 let bytes = addr.as_bytes();
655 if buf.len() < offset + bytes.len() {
656 return Err(FieldError::BufferTooShort {
657 offset,
658 need: bytes.len(),
659 have: buf.len().saturating_sub(offset),
660 });
661 }
662 buf[offset..offset + bytes.len()].copy_from_slice(&bytes);
663 Ok(())
664 }
665
666 pub fn get_field(&self, buf: &[u8], name: &str) -> Option<Result<FieldValue, FieldError>> {
668 match name {
669 "hwtype" => Some(self.hwtype(buf).map(FieldValue::U16)),
670 "ptype" => Some(self.ptype(buf).map(FieldValue::U16)),
671 "hwlen" => Some(self.hwlen(buf).map(FieldValue::U8)),
672 "plen" => Some(self.plen(buf).map(FieldValue::U8)),
673 "op" => Some(self.op(buf).map(FieldValue::U16)),
674 "hwsrc" => Some(self.hwsrc(buf).map(FieldValue::Mac)),
675 "psrc" => Some(self.psrc(buf).map(FieldValue::Ipv4)),
676 "hwdst" => Some(self.hwdst(buf).map(FieldValue::Mac)),
677 "pdst" => Some(self.pdst(buf).map(FieldValue::Ipv4)),
678 _ => None,
679 }
680 }
681
682 pub fn set_field(
683 &self,
684 buf: &mut [u8],
685 name: &str,
686 value: FieldValue,
687 ) -> Option<Result<(), FieldError>> {
688 match (name, value) {
689 ("hwtype", FieldValue::U16(v)) => Some(self.set_hwtype(buf, v)),
690 ("ptype", FieldValue::U16(v)) => Some(self.set_ptype(buf, v)),
691 ("hwlen", FieldValue::U8(v)) => Some(self.set_hwlen(buf, v)),
692 ("plen", FieldValue::U8(v)) => Some(self.set_plen(buf, v)),
693 ("op", FieldValue::U16(v)) => Some(self.set_op(buf, v)),
694 ("hwsrc", FieldValue::Mac(v)) => Some(self.set_hwsrc(buf, v)),
695 ("psrc", FieldValue::Ipv4(v)) => Some(self.set_psrc(buf, v)),
696 ("psrc", FieldValue::Ipv6(v)) => Some(self.set_psrc_v6(buf, v)),
697 ("hwdst", FieldValue::Mac(v)) => Some(self.set_hwdst(buf, v)),
698 ("pdst", FieldValue::Ipv4(v)) => Some(self.set_pdst(buf, v)),
699 ("pdst", FieldValue::Ipv6(v)) => Some(self.set_pdst_v6(buf, v)),
700 _ => None,
701 }
702 }
703
704 #[must_use]
705 pub fn field_names() -> &'static [&'static str] {
706 &[
707 "hwtype", "ptype", "hwlen", "plen", "op", "hwsrc", "psrc", "hwdst", "pdst",
708 ]
709 }
710
711 #[inline]
712 pub fn is_request(&self, buf: &[u8]) -> bool {
713 self.op(buf).map(opcode::is_request).unwrap_or(false)
714 }
715
716 #[inline]
717 pub fn is_reply(&self, buf: &[u8]) -> bool {
718 self.op(buf).map(opcode::is_reply).unwrap_or(false)
719 }
720
721 #[inline]
722 #[must_use]
723 pub fn is_who_has(&self, buf: &[u8]) -> bool {
724 self.op(buf)
725 .map(|op| op == opcode::REQUEST)
726 .unwrap_or(false)
727 }
728
729 #[inline]
730 #[must_use]
731 pub fn is_is_at(&self, buf: &[u8]) -> bool {
732 self.op(buf).map(|op| op == opcode::REPLY).unwrap_or(false)
733 }
734
735 #[must_use]
737 pub fn hashret(&self, buf: &[u8]) -> Vec<u8> {
738 let hwtype = self.hwtype(buf).unwrap_or(0);
739 let ptype = self.ptype(buf).unwrap_or(0);
740 let op = self.op(buf).unwrap_or(0);
741 let op_group = op.div_ceil(2);
742
743 let mut result = Vec::with_capacity(6);
744 result.extend_from_slice(&hwtype.to_be_bytes());
745 result.extend_from_slice(&ptype.to_be_bytes());
746 result.extend_from_slice(&op_group.to_be_bytes());
747 result
748 }
749
750 #[must_use]
752 pub fn answers(&self, buf: &[u8], other: &ArpLayer, other_buf: &[u8]) -> bool {
753 let self_op = match self.op(buf) {
754 Ok(op) => op,
755 Err(_) => return false,
756 };
757 let other_op = match other.op(other_buf) {
758 Ok(op) => op,
759 Err(_) => return false,
760 };
761
762 if self_op != other_op + 1 {
763 return false;
764 }
765
766 let self_psrc = match self.psrc_raw(buf) {
767 Ok(addr) => addr.as_bytes(),
768 Err(_) => return false,
769 };
770 let other_pdst = match other.pdst_raw(other_buf) {
771 Ok(addr) => addr.as_bytes(),
772 Err(_) => return false,
773 };
774
775 let cmp_len = self_psrc.len().min(other_pdst.len());
776 self_psrc[..cmp_len] == other_pdst[..cmp_len]
777 }
778
779 #[must_use]
781 pub fn extract_padding<'a>(&self, buf: &'a [u8]) -> (&'a [u8], &'a [u8]) {
782 let end = self.index.end.min(buf.len());
783 (&[], &buf[end..])
784 }
785
786 #[must_use]
788 pub fn route(&self, buf: &[u8]) -> ArpRoute {
789 let pdst_ip = match self.pdst_raw(buf) {
790 Ok(ProtocolAddr::Ipv4(ip)) => IpAddr::V4(ip),
791 Ok(ProtocolAddr::Ipv6(ip)) => IpAddr::V6(ip),
792 _ => return ArpRoute::default(),
793 };
794
795 let interfaces = pnet_datalink::interfaces();
796
797 for iface in &interfaces {
798 if !iface.is_up() || iface.is_loopback() {
799 continue;
800 }
801
802 for ip_net in &iface.ips {
803 if ip_net.contains(pdst_ip) {
804 return ArpRoute {
805 interface: Some(iface.name.clone()),
806 source_ip: Some(ip_net.ip().to_string()),
807 gateway: None,
808 };
809 }
810 }
811 }
812
813 if let Ok(default_iface) = default_net::get_default_interface()
814 && let Some(iface) = interfaces.iter().find(|i| i.name == default_iface.name)
815 {
816 let src_ip = iface
817 .ips
818 .iter()
819 .find(|ip| ip.is_ipv4())
820 .map(|ip| ip.ip().to_string());
821 let gw_ip = default_iface.gateway.map(|gw| gw.ip_addr.to_string());
822
823 return ArpRoute {
824 interface: Some(iface.name.clone()),
825 source_ip: src_ip,
826 gateway: gw_ip,
827 };
828 }
829
830 ArpRoute::default()
831 }
832
833 #[must_use]
835 pub fn resolve_dst_mac(&self, buf: &[u8]) -> Option<MacAddress> {
836 let op = self.op(buf).ok()?;
837 match op {
838 opcode::REQUEST => Some(MacAddress::BROADCAST), opcode::REPLY => None, _ => None,
841 }
842 }
843
844 #[inline]
845 #[must_use]
846 pub fn header_bytes<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
847 &buf[self.index.start..self.index.end.min(buf.len())]
848 }
849
850 #[inline]
851 #[must_use]
852 pub fn header_copy(&self, buf: &[u8]) -> Vec<u8> {
853 self.header_bytes(buf).to_vec()
854 }
855
856 pub fn op_name(&self, buf: &[u8]) -> &'static str {
857 self.op(buf).map(opcode::name).unwrap_or("unknown")
858 }
859
860 pub fn hwtype_name(&self, buf: &[u8]) -> &'static str {
861 self.hwtype(buf)
862 .map(hardware_type::name)
863 .unwrap_or("unknown")
864 }
865}
866
867impl Layer for ArpLayer {
868 fn kind(&self) -> LayerKind {
869 LayerKind::Arp
870 }
871
872 fn summary(&self, buf: &[u8]) -> String {
873 let op = self.op(buf).unwrap_or(0);
874 let psrc = self
875 .psrc_raw(buf)
876 .map_or_else(|_| "?".into(), |a| a.to_string());
877 let pdst = self
878 .pdst_raw(buf)
879 .map_or_else(|_| "?".into(), |a| a.to_string());
880
881 match op {
882 opcode::REQUEST => format!("ARP who has {pdst} says {psrc}"),
883 opcode::REPLY => {
884 let hwsrc = self
885 .hwsrc_raw(buf)
886 .map_or_else(|_| "?".into(), |a| a.to_string());
887 format!("ARP {psrc} is at {hwsrc}")
888 },
889 _ => format!("ARP {} {} > {}", opcode::name(op), psrc, pdst),
890 }
891 }
892
893 fn header_len(&self, buf: &[u8]) -> usize {
894 self.calculate_len(buf)
895 }
896
897 fn hashret(&self, buf: &[u8]) -> Vec<u8> {
898 self.hashret(buf)
899 }
900
901 fn answers(&self, buf: &[u8], other: &Self, other_buf: &[u8]) -> bool {
902 self.answers(buf, other, other_buf)
903 }
904
905 fn extract_padding<'a>(&self, buf: &'a [u8]) -> (&'a [u8], &'a [u8]) {
906 self.extract_padding(buf)
907 }
908}
909
910#[derive(Debug, Clone)]
915pub struct ArpBuilder {
916 hwtype: u16,
917 ptype: u16,
918 hwlen: Option<u8>,
919 plen: Option<u8>,
920 op: u16,
921 hwsrc: HardwareAddr,
922 psrc: ProtocolAddr,
923 hwdst: HardwareAddr,
924 pdst: ProtocolAddr,
925}
926
927fn get_local_mac_and_ip() -> (MacAddress, Ipv4Addr) {
929 let default_mac = MacAddress::ZERO;
930 let default_ip = Ipv4Addr::UNSPECIFIED;
931
932 let default_iface = match default_net::get_default_interface() {
933 Ok(iface) => iface,
934 Err(_) => return (default_mac, default_ip),
935 };
936
937 let interfaces = pnet_datalink::interfaces();
938 let iface = match interfaces.iter().find(|i| i.name == default_iface.name) {
939 Some(i) => i,
940 None => return (default_mac, default_ip),
941 };
942
943 let mac = iface
944 .mac
945 .map_or(default_mac, |m| MacAddress::new(m.octets()));
946
947 let ip = iface
948 .ips
949 .iter()
950 .find_map(|ip_net| {
951 if let IpAddr::V4(v4) = ip_net.ip() {
952 Some(v4)
953 } else {
954 None
955 }
956 })
957 .unwrap_or(default_ip);
958
959 (mac, ip)
960}
961
962impl Default for ArpBuilder {
963 fn default() -> Self {
964 let (local_mac, local_ip) = get_local_mac_and_ip();
965 Self {
966 hwtype: hardware_type::ETHERNET,
967 ptype: protocol_type::IPV4,
968 hwlen: None,
969 plen: None,
970 op: opcode::REQUEST,
971 hwsrc: HardwareAddr::Mac(local_mac),
972 psrc: ProtocolAddr::Ipv4(local_ip),
973 hwdst: HardwareAddr::Mac(MacAddress::ZERO),
974 pdst: ProtocolAddr::Ipv4(Ipv4Addr::UNSPECIFIED),
975 }
976 }
977}
978
979impl ArpBuilder {
980 #[must_use]
981 pub fn new() -> Self {
982 Self::default()
983 }
984
985 #[must_use]
986 pub fn who_has(pdst: Ipv4Addr) -> Self {
987 Self::default().op(opcode::REQUEST).pdst(pdst)
988 }
989
990 #[must_use]
991 pub fn is_at(psrc: Ipv4Addr, hwsrc: MacAddress) -> Self {
992 Self::default().op(opcode::REPLY).psrc(psrc).hwsrc(hwsrc)
993 }
994
995 #[must_use]
996 pub fn hwtype(mut self, v: u16) -> Self {
997 self.hwtype = v;
998 self
999 }
1000 #[must_use]
1001 pub fn ptype(mut self, v: u16) -> Self {
1002 self.ptype = v;
1003 self
1004 }
1005 #[must_use]
1006 pub fn hwlen(mut self, v: u8) -> Self {
1007 self.hwlen = Some(v);
1008 self
1009 }
1010 #[must_use]
1011 pub fn plen(mut self, v: u8) -> Self {
1012 self.plen = Some(v);
1013 self
1014 }
1015 #[must_use]
1016 pub fn op(mut self, v: u16) -> Self {
1017 self.op = v;
1018 self
1019 }
1020
1021 #[must_use]
1022 pub fn op_name(mut self, name: &str) -> Self {
1023 if let Some(op) = opcode::from_name(name) {
1024 self.op = op;
1025 }
1026 self
1027 }
1028
1029 #[must_use]
1030 pub fn hwsrc(mut self, v: MacAddress) -> Self {
1031 self.hwsrc = HardwareAddr::Mac(v);
1032 self
1033 }
1034 #[must_use]
1035 pub fn hwsrc_raw(mut self, v: HardwareAddr) -> Self {
1036 self.hwsrc = v;
1037 self
1038 }
1039 #[must_use]
1040 pub fn psrc(mut self, v: Ipv4Addr) -> Self {
1041 self.psrc = ProtocolAddr::Ipv4(v);
1042 self
1043 }
1044 #[must_use]
1045 pub fn psrc_v6(mut self, v: Ipv6Addr) -> Self {
1046 self.psrc = ProtocolAddr::Ipv6(v);
1047 self.ptype = protocol_type::IPV6;
1048 self
1049 }
1050 #[must_use]
1051 pub fn psrc_raw(mut self, v: ProtocolAddr) -> Self {
1052 self.psrc = v;
1053 self
1054 }
1055 #[must_use]
1056 pub fn hwdst(mut self, v: MacAddress) -> Self {
1057 self.hwdst = HardwareAddr::Mac(v);
1058 self
1059 }
1060 #[must_use]
1061 pub fn hwdst_raw(mut self, v: HardwareAddr) -> Self {
1062 self.hwdst = v;
1063 self
1064 }
1065 #[must_use]
1066 pub fn pdst(mut self, v: Ipv4Addr) -> Self {
1067 self.pdst = ProtocolAddr::Ipv4(v);
1068 self
1069 }
1070 #[must_use]
1071 pub fn pdst_v6(mut self, v: Ipv6Addr) -> Self {
1072 self.pdst = ProtocolAddr::Ipv6(v);
1073 self.ptype = protocol_type::IPV6;
1074 self
1075 }
1076 #[must_use]
1077 pub fn pdst_raw(mut self, v: ProtocolAddr) -> Self {
1078 self.pdst = v;
1079 self
1080 }
1081
1082 #[must_use]
1083 pub fn size(&self) -> usize {
1084 let hwlen = self.hwlen.unwrap_or(self.hwsrc.len() as u8) as usize;
1085 let plen = self.plen.unwrap_or(self.psrc.len() as u8) as usize;
1086 ARP_FIXED_HEADER_LEN + 2 * hwlen + 2 * plen
1087 }
1088
1089 #[must_use]
1090 pub fn build(&self) -> Vec<u8> {
1091 let mut buf = vec![0u8; self.size()];
1092 self.build_into(&mut buf)
1093 .expect("buffer is correctly sized");
1094 buf
1095 }
1096
1097 pub fn build_into(&self, buf: &mut [u8]) -> Result<(), FieldError> {
1098 let hwlen = self.hwlen.unwrap_or(self.hwsrc.len() as u8);
1099 let plen = self.plen.unwrap_or(self.psrc.len() as u8);
1100 let size = ARP_FIXED_HEADER_LEN + 2 * (hwlen as usize) + 2 * (plen as usize);
1101
1102 if buf.len() < size {
1103 return Err(FieldError::BufferTooShort {
1104 offset: 0,
1105 need: size,
1106 have: buf.len(),
1107 });
1108 }
1109
1110 self.hwtype.write(buf, offsets::HWTYPE)?;
1111 self.ptype.write(buf, offsets::PTYPE)?;
1112 hwlen.write(buf, offsets::HWLEN)?;
1113 plen.write(buf, offsets::PLEN)?;
1114 self.op.write(buf, offsets::OP)?;
1115
1116 let mut offset = offsets::VAR_START;
1117
1118 let hwsrc_bytes = self.hwsrc.as_bytes();
1119 let hwsrc_copy_len = hwsrc_bytes.len().min(hwlen as usize);
1120 buf[offset..offset + hwsrc_copy_len].copy_from_slice(&hwsrc_bytes[..hwsrc_copy_len]);
1121 offset += hwlen as usize;
1122
1123 let psrc_bytes = self.psrc.as_bytes();
1124 let psrc_copy_len = psrc_bytes.len().min(plen as usize);
1125 buf[offset..offset + psrc_copy_len].copy_from_slice(&psrc_bytes[..psrc_copy_len]);
1126 offset += plen as usize;
1127
1128 let hwdst_bytes = self.hwdst.as_bytes();
1129 let hwdst_copy_len = hwdst_bytes.len().min(hwlen as usize);
1130 buf[offset..offset + hwdst_copy_len].copy_from_slice(&hwdst_bytes[..hwdst_copy_len]);
1131 offset += hwlen as usize;
1132
1133 let pdst_bytes = self.pdst.as_bytes();
1134 let pdst_copy_len = pdst_bytes.len().min(plen as usize);
1135 buf[offset..offset + pdst_copy_len].copy_from_slice(&pdst_bytes[..pdst_copy_len]);
1136
1137 Ok(())
1138 }
1139}
1140
1141#[cfg(test)]
1142mod tests {
1143 use super::*;
1144
1145 #[test]
1146 fn test_arp_ipv6_fields() {
1147 let mut buf = vec![0u8; 52]; let arp = ArpLayer::at_offset(0);
1149
1150 arp.set_hwtype(&mut buf, hardware_type::ETHERNET).unwrap();
1151 arp.set_ptype(&mut buf, protocol_type::IPV6).unwrap();
1152 arp.set_hwlen(&mut buf, 6).unwrap();
1153 arp.set_plen(&mut buf, 16).unwrap();
1154 arp.set_op(&mut buf, opcode::REQUEST).unwrap();
1155
1156 let ipv6 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
1157 arp.set_psrc_v6(&mut buf, ipv6).unwrap();
1158 assert_eq!(arp.psrc_v6(&buf).unwrap(), ipv6);
1159 }
1160
1161 #[test]
1162 fn test_extract_padding() {
1163 let mut buf = vec![0u8; 60]; buf[..28].copy_from_slice(&sample_arp_request());
1165
1166 let arp = ArpLayer::at_offset(0);
1167 let (payload, padding) = arp.extract_padding(&buf);
1168
1169 assert!(payload.is_empty());
1170 assert_eq!(padding.len(), 32); }
1172
1173 #[test]
1174 fn test_route() {
1175 let buf = sample_arp_request();
1176 let arp = ArpLayer::at_offset(0);
1177 let route = arp.route(&buf);
1178
1179 assert!(route.source_ip.is_some());
1180 }
1181
1182 #[test]
1183 fn test_resolve_dst_mac() {
1184 let buf = sample_arp_request();
1185 let arp = ArpLayer::at_offset(0);
1186
1187 assert_eq!(arp.resolve_dst_mac(&buf), Some(MacAddress::BROADCAST));
1188 }
1189
1190 fn sample_arp_request() -> Vec<u8> {
1191 vec![
1192 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
1193 0xc0, 0xa8, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x01, 0x02,
1194 ]
1195 }
1196}