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