r_lanlib/packet/
arp_packet.rs

1//! Provides helpers for creating ARP packets
2
3use derive_builder::Builder;
4use pnet::{
5    packet::{MutablePacket, arp, ethernet},
6    util,
7};
8use std::net;
9
10// Constants used to help locate our nested packets
11const PKT_ETH_SIZE: usize = ethernet::EthernetPacket::minimum_packet_size();
12const PKT_ARP_SIZE: usize = arp::ArpPacket::minimum_packet_size();
13const PKT_TOTAL_SIZE: usize = PKT_ETH_SIZE + PKT_ARP_SIZE;
14
15/// Represents a generator for raw ARP packets
16#[derive(Debug, Builder)]
17#[builder(setter(into))]
18pub struct ArpPacket {
19    /// Ip of the host sending the packet
20    source_ip: net::Ipv4Addr,
21    /// Mac address of the host sending the packet
22    source_mac: util::MacAddr,
23    /// Target destination IP for the packet
24    dest_ip: net::Ipv4Addr,
25}
26
27impl ArpPacket {
28    /// Builds a new ARP request packet based on provided information
29    /// This is what the internals of the arp_scanner will send when scanning
30    /// for devices on the network
31    pub fn to_raw(&self) -> [u8; PKT_TOTAL_SIZE] {
32        let mut pkt_buf = [0u8; PKT_TOTAL_SIZE];
33
34        // Build our base ethernet frame
35        let mut pkt_eth = ethernet::MutableEthernetPacket::new(&mut pkt_buf)
36            .expect("failed to generate ethernet packet");
37
38        let mut arp_buffer = [0u8; PKT_ARP_SIZE];
39
40        let mut pkt_arp =
41            arp::MutableArpPacket::new(&mut arp_buffer).expect("failed to generate arp packet");
42
43        pkt_eth.set_destination(util::MacAddr::broadcast());
44        pkt_eth.set_source(self.source_mac);
45        pkt_eth.set_ethertype(ethernet::EtherTypes::Arp);
46
47        pkt_arp.set_hardware_type(arp::ArpHardwareTypes::Ethernet);
48        pkt_arp.set_protocol_type(ethernet::EtherTypes::Ipv4);
49        pkt_arp.set_hw_addr_len(6);
50        pkt_arp.set_proto_addr_len(4);
51        pkt_arp.set_operation(arp::ArpOperations::Request);
52        pkt_arp.set_sender_hw_addr(self.source_mac);
53        pkt_arp.set_sender_proto_addr(self.source_ip);
54        pkt_arp.set_target_hw_addr(util::MacAddr::zero());
55        pkt_arp.set_target_proto_addr(self.dest_ip);
56
57        pkt_eth.set_payload(pkt_arp.packet_mut());
58
59        pkt_buf
60    }
61}
62
63#[cfg(test)]
64#[allow(warnings)]
65#[doc(hidden)]
66// only used in tests
67pub fn create_arp_reply(
68    from_mac: util::MacAddr,
69    from_ip: net::Ipv4Addr,
70    to_mac: util::MacAddr,
71    to_ip: net::Ipv4Addr,
72    packet: &'static mut [u8; PKT_TOTAL_SIZE],
73) {
74    let mut pkt_eth =
75        ethernet::MutableEthernetPacket::new(packet).expect("failed to generate ethernet packet");
76
77    let mut arp_buffer = [0u8; PKT_ARP_SIZE];
78
79    let mut pkt_arp =
80        arp::MutableArpPacket::new(&mut arp_buffer).expect("failed to generate arp packet");
81
82    pkt_eth.set_destination(to_mac);
83    pkt_eth.set_source(from_mac);
84    pkt_eth.set_ethertype(ethernet::EtherTypes::Arp);
85
86    pkt_arp.set_hardware_type(arp::ArpHardwareTypes::Ethernet);
87    pkt_arp.set_protocol_type(ethernet::EtherTypes::Ipv4);
88    pkt_arp.set_hw_addr_len(6);
89    pkt_arp.set_proto_addr_len(4);
90    pkt_arp.set_operation(arp::ArpOperations::Reply);
91    pkt_arp.set_sender_hw_addr(from_mac);
92    pkt_arp.set_sender_proto_addr(from_ip);
93    pkt_arp.set_target_hw_addr(to_mac);
94    pkt_arp.set_target_proto_addr(to_ip);
95
96    pkt_eth.set_payload(pkt_arp.packet_mut());
97}
98
99#[cfg(test)]
100#[path = "./arp_packet_tests.rs"]
101mod tests;