1use crate::datalink::MacAddr;
2use crate::packet::ethernet::{ETHERNET_HEADER_LEN, EtherType};
3use pnet::packet::Packet;
4use std::net::Ipv4Addr;
5
6pub const ARP_HEADER_LEN: usize = 28;
8pub const ARP_PACKET_LEN: usize = ETHERNET_HEADER_LEN + ARP_HEADER_LEN;
10
11#[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 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#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
41pub enum ArpHardwareType {
42 Ethernet = 1,
44 ExperimentalEthernet = 2,
46 AmateurRadioAX25 = 3,
48 ProteonProNETTokenRing = 4,
50 Chaos = 5,
52 IEEE802Networks = 6,
54 ARCNET = 7,
56 Hyperchannel = 8,
58 Lanstar = 9,
60 AutonetShortAddress = 10,
62 LocalTalk = 11,
64 LocalNet = 12,
66 UltraLink = 13,
68 SMDS = 14,
70 FrameRelay = 15,
72 AsynchronousTransmissionMode = 16,
74 HDLC = 17,
76 FibreChannel = 18,
78 AsynchronousTransmissionMode2 = 19,
80 SerialLine = 20,
82 AsynchronousTransmissionMode3 = 21,
84 MILSTD188220 = 22,
86 Metricom = 23,
88 IEEE13941995 = 24,
90 MAPOS = 25,
92 Twinaxial = 26,
94 EUI64 = 27,
96 HIPARP = 28,
98 IPandARPoverISO78163 = 29,
100 ARPSec = 30,
102 IPsecTunnel = 31,
104 InfiniBand = 32,
106 TIA102Project25CommonAirInterface = 16384,
108 WiegandInterface = 16385,
110 PureIP = 16386,
112 HWEXP1 = 65280,
114 HWEXP2 = 65281,
116 AEthernet = 65282,
118}
119
120impl ArpHardwareType {
121 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#[derive(Clone, Debug)]
169pub struct ArpPacket {
170 pub hardware_type: ArpHardwareType,
172 pub protocol_type: EtherType,
174 pub operation: ArpOperation,
176 pub sender_hw_addr: MacAddr,
178 pub sender_proto_addr: Ipv4Addr,
180 pub target_hw_addr: MacAddr,
182 pub target_proto_addr: Ipv4Addr,
184 pub payload: Vec<u8>,
186}
187
188impl ArpPacket {
189 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 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
209pub(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#[derive(Clone, Debug)]
230pub struct ArpPacketBuilder {
231 pub src_mac: MacAddr,
233 pub dst_mac: MacAddr,
235 pub src_ip: Ipv4Addr,
237 pub dst_ip: Ipv4Addr,
239}
240
241impl ArpPacketBuilder {
242 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 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}