cross_socket/packet/
arp.rs

1use crate::datalink::MacAddr;
2use crate::packet::ethernet::{ETHERNET_HEADER_LEN, EtherType};
3use pnet::packet::Packet;
4use std::net::Ipv4Addr;
5
6/// ARP Header Length
7pub const ARP_HEADER_LEN: usize = 28;
8/// ARP Minimum Packet Length
9pub const ARP_PACKET_LEN: usize = ETHERNET_HEADER_LEN + ARP_HEADER_LEN;
10
11/// Represents the ARP operation types.
12#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub enum ArpOperation {
14    Request = 1,
15    Reply = 2,
16    RarpRequest = 3,
17    RarpReply = 4,
18    InRequest = 8,
19    InReply = 9,
20    Nak = 10,
21}
22
23impl ArpOperation {
24    /// Constructs a new ArpOperation from u16
25    pub fn from_u16(n: u16) -> Option<ArpOperation> {
26        match n {
27            1 => Some(ArpOperation::Request),
28            2 => Some(ArpOperation::Reply),
29            3 => Some(ArpOperation::RarpRequest),
30            4 => Some(ArpOperation::RarpReply),
31            8 => Some(ArpOperation::InRequest),
32            9 => Some(ArpOperation::InReply),
33            10 => Some(ArpOperation::Nak),
34            _ => None,
35        }
36    }
37}
38
39/// Represents the ARP hardware types.
40#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
41pub enum ArpHardwareType {
42    /// Ethernet (10Mb)
43    Ethernet = 1,
44    /// Experimental Ethernet (3Mb)
45    ExperimentalEthernet = 2,
46    /// Amateur Radio AX.25
47    AmateurRadioAX25 = 3,
48    /// Proteon ProNET Token Ring
49    ProteonProNETTokenRing = 4,
50    /// Chaos
51    Chaos = 5,
52    /// IEEE 802 Networks
53    IEEE802Networks = 6,
54    /// ARCNET
55    ARCNET = 7,
56    /// Hyperchannel
57    Hyperchannel = 8,
58    /// Lanstar
59    Lanstar = 9,
60    /// Autonet Short Address
61    AutonetShortAddress = 10,
62    /// LocalTalk
63    LocalTalk = 11,
64    /// LocalNet (IBM PCNet or SYTEK LocalNET)
65    LocalNet = 12,
66    /// Ultra link
67    UltraLink = 13,
68    /// SMDS
69    SMDS = 14,
70    /// Frame Relay
71    FrameRelay = 15,
72    /// Asynchronous Transmission Mode (ATM)
73    AsynchronousTransmissionMode = 16,
74    /// HDLC
75    HDLC = 17,
76    /// Fibre Channel
77    FibreChannel = 18,
78    /// Asynchronous Transmission Mode (ATM)
79    AsynchronousTransmissionMode2 = 19,
80    /// Serial Line
81    SerialLine = 20,
82    /// Asynchronous Transmission Mode (ATM)
83    AsynchronousTransmissionMode3 = 21,
84    /// MIL-STD-188-220
85    MILSTD188220 = 22,
86    /// Metricom
87    Metricom = 23,
88    /// IEEE 1394.1995
89    IEEE13941995 = 24,
90    /// MAPOS
91    MAPOS = 25,
92    /// Twinaxial
93    Twinaxial = 26,
94    /// EUI-64
95    EUI64 = 27,
96    /// HIPARP
97    HIPARP = 28,
98    /// IP and ARP over ISO 7816-3
99    IPandARPoverISO78163 = 29,
100    /// ARPSec
101    ARPSec = 30,
102    /// IPsec tunnel
103    IPsecTunnel = 31,
104    /// InfiniBand (TM)
105    InfiniBand = 32,
106    /// TIA-102 Project 25 Common Air Interface
107    TIA102Project25CommonAirInterface = 16384,
108    /// Wiegand Interface
109    WiegandInterface = 16385,
110    /// Pure IP
111    PureIP = 16386,
112    /// HW_EXP1
113    HWEXP1 = 65280,
114    /// HW_EXP2
115    HWEXP2 = 65281,
116    /// AEthernet
117    AEthernet = 65282,
118}
119
120impl ArpHardwareType {
121    /// Constructs a new ArpHardwareType from u16
122    pub fn from_u16(n: u16) -> Option<ArpHardwareType> {
123        match n {
124            1 => Some(ArpHardwareType::Ethernet),
125            2 => Some(ArpHardwareType::ExperimentalEthernet),
126            3 => Some(ArpHardwareType::AmateurRadioAX25),
127            4 => Some(ArpHardwareType::ProteonProNETTokenRing),
128            5 => Some(ArpHardwareType::Chaos),
129            6 => Some(ArpHardwareType::IEEE802Networks),
130            7 => Some(ArpHardwareType::ARCNET),
131            8 => Some(ArpHardwareType::Hyperchannel),
132            9 => Some(ArpHardwareType::Lanstar),
133            10 => Some(ArpHardwareType::AutonetShortAddress),
134            11 => Some(ArpHardwareType::LocalTalk),
135            12 => Some(ArpHardwareType::LocalNet),
136            13 => Some(ArpHardwareType::UltraLink),
137            14 => Some(ArpHardwareType::SMDS),
138            15 => Some(ArpHardwareType::FrameRelay),
139            16 => Some(ArpHardwareType::AsynchronousTransmissionMode),
140            17 => Some(ArpHardwareType::HDLC),
141            18 => Some(ArpHardwareType::FibreChannel),
142            19 => Some(ArpHardwareType::AsynchronousTransmissionMode2),
143            20 => Some(ArpHardwareType::SerialLine),
144            21 => Some(ArpHardwareType::AsynchronousTransmissionMode3),
145            22 => Some(ArpHardwareType::MILSTD188220),
146            23 => Some(ArpHardwareType::Metricom),
147            24 => Some(ArpHardwareType::IEEE13941995),
148            25 => Some(ArpHardwareType::MAPOS),
149            26 => Some(ArpHardwareType::Twinaxial),
150            27 => Some(ArpHardwareType::EUI64),
151            28 => Some(ArpHardwareType::HIPARP),
152            29 => Some(ArpHardwareType::IPandARPoverISO78163),
153            30 => Some(ArpHardwareType::ARPSec),
154            31 => Some(ArpHardwareType::IPsecTunnel),
155            32 => Some(ArpHardwareType::InfiniBand),
156            16384 => Some(ArpHardwareType::TIA102Project25CommonAirInterface),
157            16385 => Some(ArpHardwareType::WiegandInterface),
158            16386 => Some(ArpHardwareType::PureIP),
159            65280 => Some(ArpHardwareType::HWEXP1),
160            65281 => Some(ArpHardwareType::HWEXP2),
161            65282 => Some(ArpHardwareType::AEthernet),
162            _ => None,
163        }
164    }
165}
166
167/// Represents an ARP packet
168#[derive(Clone, Debug)]
169pub struct ArpPacket {
170    /// Hardware type
171    pub hardware_type: ArpHardwareType,
172    /// Protocol type
173    pub protocol_type: EtherType,
174    /// Operation
175    pub operation: ArpOperation,
176    /// Sender hardware address
177    pub sender_hw_addr: MacAddr,
178    /// Sender IPv4 address
179    pub sender_proto_addr: Ipv4Addr,
180    /// Target hardware address
181    pub target_hw_addr: MacAddr,
182    /// Target IPv4 address
183    pub target_proto_addr: Ipv4Addr,
184    /// Payload
185    pub payload: Vec<u8>,
186}
187
188impl ArpPacket {
189    /// Constructs a new ArpPacket from pnet::packet::arp::ArpPacket.
190    pub(crate) fn from_pnet_packet(packet: pnet::packet::arp::ArpPacket) -> ArpPacket {
191        ArpPacket {
192            hardware_type: ArpHardwareType::from_u16(packet.get_hardware_type().0).unwrap(),
193            protocol_type: EtherType::from_u16(packet.get_protocol_type().0).unwrap(),
194            operation: ArpOperation::from_u16(packet.get_operation().0).unwrap(),
195            sender_hw_addr: MacAddr::new(packet.get_sender_hw_addr().octets()),
196            sender_proto_addr: packet.get_sender_proto_addr(),
197            target_hw_addr: MacAddr::new(packet.get_target_hw_addr().octets()),
198            target_proto_addr: packet.get_target_proto_addr(),
199            payload: packet.payload().to_vec(),
200        }
201    }
202    /// Constructs a new ArpPacket from bytes
203    pub fn from_bytes(packet: &[u8]) -> ArpPacket {
204        let arp_packet = pnet::packet::arp::ArpPacket::new(packet).unwrap();
205        ArpPacket::from_pnet_packet(arp_packet)
206    }
207}
208
209/// Build ARP packet
210pub(crate) fn build_arp_packet(
211    arp_packet: &mut pnet::packet::arp::MutableArpPacket,
212    src_mac: MacAddr,
213    dst_mac: MacAddr,
214    src_ip: Ipv4Addr,
215    dst_ip: Ipv4Addr,
216) {
217    arp_packet.set_hardware_type(pnet::packet::arp::ArpHardwareTypes::Ethernet);
218    arp_packet.set_protocol_type(pnet::packet::ethernet::EtherTypes::Ipv4);
219    arp_packet.set_hw_addr_len(6);
220    arp_packet.set_proto_addr_len(4);
221    arp_packet.set_operation(pnet::packet::arp::ArpOperations::Request);
222    arp_packet.set_sender_hw_addr(pnet::datalink::MacAddr::from(src_mac.octets()));
223    arp_packet.set_sender_proto_addr(src_ip);
224    arp_packet.set_target_hw_addr(pnet::datalink::MacAddr::from(dst_mac.octets()));
225    arp_packet.set_target_proto_addr(dst_ip);
226}
227
228/// ARP Packet Builder
229#[derive(Clone, Debug)]
230pub struct ArpPacketBuilder {
231    /// Source MAC address
232    pub src_mac: MacAddr,
233    /// Destination MAC address
234    pub dst_mac: MacAddr,
235    /// Source IPv4 address
236    pub src_ip: Ipv4Addr,
237    /// Destination IPv4 address
238    pub dst_ip: Ipv4Addr,
239}
240
241impl ArpPacketBuilder {
242    /// Constructs a new ArpPacketBuilder
243    pub fn new() -> ArpPacketBuilder {
244        ArpPacketBuilder {
245            src_mac: MacAddr::new([0u8; 6]),
246            dst_mac: MacAddr::new([0u8; 6]),
247            src_ip: Ipv4Addr::new(0, 0, 0, 0),
248            dst_ip: Ipv4Addr::new(0, 0, 0, 0),
249        }
250    }
251    /// Builds ARP packet and return bytes
252    pub fn build(&self) -> Vec<u8> {
253        let mut buffer = [0u8; ARP_HEADER_LEN];
254        let mut arp_packet = pnet::packet::arp::MutableArpPacket::new(&mut buffer).unwrap();
255        build_arp_packet(
256            &mut arp_packet,
257            self.src_mac.clone(),
258            self.dst_mac.clone(),
259            self.src_ip,
260            self.dst_ip,
261        );
262        arp_packet.packet().to_vec()
263    }
264}