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 fn field_names(&self) -> &'static [&'static str] {
910 ArpLayer::field_names()
911 }
912}
913
914#[derive(Debug, Clone)]
919pub struct ArpBuilder {
920 hwtype: u16,
921 ptype: u16,
922 hwlen: Option<u8>,
923 plen: Option<u8>,
924 op: u16,
925 hwsrc: HardwareAddr,
926 psrc: ProtocolAddr,
927 hwdst: HardwareAddr,
928 pdst: ProtocolAddr,
929}
930
931fn get_local_mac_and_ip() -> (MacAddress, Ipv4Addr) {
933 let default_mac = MacAddress::ZERO;
934 let default_ip = Ipv4Addr::UNSPECIFIED;
935
936 let default_iface = match default_net::get_default_interface() {
937 Ok(iface) => iface,
938 Err(_) => return (default_mac, default_ip),
939 };
940
941 let interfaces = pnet_datalink::interfaces();
942 let iface = match interfaces.iter().find(|i| i.name == default_iface.name) {
943 Some(i) => i,
944 None => return (default_mac, default_ip),
945 };
946
947 let mac = iface
948 .mac
949 .map_or(default_mac, |m| MacAddress::new(m.octets()));
950
951 let ip = iface
952 .ips
953 .iter()
954 .find_map(|ip_net| {
955 if let IpAddr::V4(v4) = ip_net.ip() {
956 Some(v4)
957 } else {
958 None
959 }
960 })
961 .unwrap_or(default_ip);
962
963 (mac, ip)
964}
965
966impl Default for ArpBuilder {
967 fn default() -> Self {
968 let (local_mac, local_ip) = get_local_mac_and_ip();
969 Self {
970 hwtype: hardware_type::ETHERNET,
971 ptype: protocol_type::IPV4,
972 hwlen: None,
973 plen: None,
974 op: opcode::REQUEST,
975 hwsrc: HardwareAddr::Mac(local_mac),
976 psrc: ProtocolAddr::Ipv4(local_ip),
977 hwdst: HardwareAddr::Mac(MacAddress::ZERO),
978 pdst: ProtocolAddr::Ipv4(Ipv4Addr::UNSPECIFIED),
979 }
980 }
981}
982
983impl ArpBuilder {
984 #[must_use]
985 pub fn new() -> Self {
986 Self::default()
987 }
988
989 #[must_use]
990 pub fn who_has(pdst: Ipv4Addr) -> Self {
991 Self::default().op(opcode::REQUEST).pdst(pdst)
992 }
993
994 #[must_use]
995 pub fn is_at(psrc: Ipv4Addr, hwsrc: MacAddress) -> Self {
996 Self::default().op(opcode::REPLY).psrc(psrc).hwsrc(hwsrc)
997 }
998
999 #[must_use]
1000 pub fn hwtype(mut self, v: u16) -> Self {
1001 self.hwtype = v;
1002 self
1003 }
1004 #[must_use]
1005 pub fn ptype(mut self, v: u16) -> Self {
1006 self.ptype = v;
1007 self
1008 }
1009 #[must_use]
1010 pub fn hwlen(mut self, v: u8) -> Self {
1011 self.hwlen = Some(v);
1012 self
1013 }
1014 #[must_use]
1015 pub fn plen(mut self, v: u8) -> Self {
1016 self.plen = Some(v);
1017 self
1018 }
1019 #[must_use]
1020 pub fn op(mut self, v: u16) -> Self {
1021 self.op = v;
1022 self
1023 }
1024
1025 #[must_use]
1026 pub fn op_name(mut self, name: &str) -> Self {
1027 if let Some(op) = opcode::from_name(name) {
1028 self.op = op;
1029 }
1030 self
1031 }
1032
1033 #[must_use]
1034 pub fn hwsrc(mut self, v: MacAddress) -> Self {
1035 self.hwsrc = HardwareAddr::Mac(v);
1036 self
1037 }
1038 #[must_use]
1039 pub fn hwsrc_raw(mut self, v: HardwareAddr) -> Self {
1040 self.hwsrc = v;
1041 self
1042 }
1043 #[must_use]
1044 pub fn psrc(mut self, v: Ipv4Addr) -> Self {
1045 self.psrc = ProtocolAddr::Ipv4(v);
1046 self
1047 }
1048 #[must_use]
1049 pub fn psrc_v6(mut self, v: Ipv6Addr) -> Self {
1050 self.psrc = ProtocolAddr::Ipv6(v);
1051 self.ptype = protocol_type::IPV6;
1052 self
1053 }
1054 #[must_use]
1055 pub fn psrc_raw(mut self, v: ProtocolAddr) -> Self {
1056 self.psrc = v;
1057 self
1058 }
1059 #[must_use]
1060 pub fn hwdst(mut self, v: MacAddress) -> Self {
1061 self.hwdst = HardwareAddr::Mac(v);
1062 self
1063 }
1064 #[must_use]
1065 pub fn hwdst_raw(mut self, v: HardwareAddr) -> Self {
1066 self.hwdst = v;
1067 self
1068 }
1069 #[must_use]
1070 pub fn pdst(mut self, v: Ipv4Addr) -> Self {
1071 self.pdst = ProtocolAddr::Ipv4(v);
1072 self
1073 }
1074 #[must_use]
1075 pub fn pdst_v6(mut self, v: Ipv6Addr) -> Self {
1076 self.pdst = ProtocolAddr::Ipv6(v);
1077 self.ptype = protocol_type::IPV6;
1078 self
1079 }
1080 #[must_use]
1081 pub fn pdst_raw(mut self, v: ProtocolAddr) -> Self {
1082 self.pdst = v;
1083 self
1084 }
1085
1086 #[must_use]
1087 pub fn size(&self) -> usize {
1088 let hwlen = self.hwlen.unwrap_or(self.hwsrc.len() as u8) as usize;
1089 let plen = self.plen.unwrap_or(self.psrc.len() as u8) as usize;
1090 ARP_FIXED_HEADER_LEN + 2 * hwlen + 2 * plen
1091 }
1092
1093 #[must_use]
1094 pub fn build(&self) -> Vec<u8> {
1095 let mut buf = vec![0u8; self.size()];
1096 self.build_into(&mut buf)
1097 .expect("buffer is correctly sized");
1098 buf
1099 }
1100
1101 pub fn build_into(&self, buf: &mut [u8]) -> Result<(), FieldError> {
1102 let hwlen = self.hwlen.unwrap_or(self.hwsrc.len() as u8);
1103 let plen = self.plen.unwrap_or(self.psrc.len() as u8);
1104 let size = ARP_FIXED_HEADER_LEN + 2 * (hwlen as usize) + 2 * (plen as usize);
1105
1106 if buf.len() < size {
1107 return Err(FieldError::BufferTooShort {
1108 offset: 0,
1109 need: size,
1110 have: buf.len(),
1111 });
1112 }
1113
1114 self.hwtype.write(buf, offsets::HWTYPE)?;
1115 self.ptype.write(buf, offsets::PTYPE)?;
1116 hwlen.write(buf, offsets::HWLEN)?;
1117 plen.write(buf, offsets::PLEN)?;
1118 self.op.write(buf, offsets::OP)?;
1119
1120 let mut offset = offsets::VAR_START;
1121
1122 let hwsrc_bytes = self.hwsrc.as_bytes();
1123 let hwsrc_copy_len = hwsrc_bytes.len().min(hwlen as usize);
1124 buf[offset..offset + hwsrc_copy_len].copy_from_slice(&hwsrc_bytes[..hwsrc_copy_len]);
1125 offset += hwlen as usize;
1126
1127 let psrc_bytes = self.psrc.as_bytes();
1128 let psrc_copy_len = psrc_bytes.len().min(plen as usize);
1129 buf[offset..offset + psrc_copy_len].copy_from_slice(&psrc_bytes[..psrc_copy_len]);
1130 offset += plen as usize;
1131
1132 let hwdst_bytes = self.hwdst.as_bytes();
1133 let hwdst_copy_len = hwdst_bytes.len().min(hwlen as usize);
1134 buf[offset..offset + hwdst_copy_len].copy_from_slice(&hwdst_bytes[..hwdst_copy_len]);
1135 offset += hwlen as usize;
1136
1137 let pdst_bytes = self.pdst.as_bytes();
1138 let pdst_copy_len = pdst_bytes.len().min(plen as usize);
1139 buf[offset..offset + pdst_copy_len].copy_from_slice(&pdst_bytes[..pdst_copy_len]);
1140
1141 Ok(())
1142 }
1143}
1144
1145#[cfg(test)]
1146mod tests {
1147 use super::*;
1148
1149 #[test]
1150 fn test_arp_ipv6_fields() {
1151 let mut buf = vec![0u8; 52]; let arp = ArpLayer::at_offset(0);
1153
1154 arp.set_hwtype(&mut buf, hardware_type::ETHERNET).unwrap();
1155 arp.set_ptype(&mut buf, protocol_type::IPV6).unwrap();
1156 arp.set_hwlen(&mut buf, 6).unwrap();
1157 arp.set_plen(&mut buf, 16).unwrap();
1158 arp.set_op(&mut buf, opcode::REQUEST).unwrap();
1159
1160 let ipv6 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
1161 arp.set_psrc_v6(&mut buf, ipv6).unwrap();
1162 assert_eq!(arp.psrc_v6(&buf).unwrap(), ipv6);
1163 }
1164
1165 #[test]
1166 fn test_extract_padding() {
1167 let mut buf = vec![0u8; 60]; buf[..28].copy_from_slice(&sample_arp_request());
1169
1170 let arp = ArpLayer::at_offset(0);
1171 let (payload, padding) = arp.extract_padding(&buf);
1172
1173 assert!(payload.is_empty());
1174 assert_eq!(padding.len(), 32); }
1176
1177 #[test]
1178 fn test_route() {
1179 let buf = sample_arp_request();
1180 let arp = ArpLayer::at_offset(0);
1181 let route = arp.route(&buf);
1182
1183 assert!(route.source_ip.is_some());
1184 }
1185
1186 #[test]
1187 fn test_resolve_dst_mac() {
1188 let buf = sample_arp_request();
1189 let arp = ArpLayer::at_offset(0);
1190
1191 assert_eq!(arp.resolve_dst_mac(&buf), Some(MacAddress::BROADCAST));
1192 }
1193
1194 fn sample_arp_request() -> Vec<u8> {
1195 vec![
1196 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
1197 0xc0, 0xa8, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x01, 0x02,
1198 ]
1199 }
1200}