1use crate::arp;
2use crate::interfaces::MacAddr;
3use crate::{arp::ArpMessage, interfaces::Interface};
4use pnet::{
5 datalink::DataLinkReceiver,
6 packet::{
7 arp::ArpPacket,
8 ethernet::{EtherTypes, EthernetPacket, MutableEthernetPacket},
9 },
10};
11use std::convert::TryInto;
12use std::time::Duration;
13use std::{
14 io::{Error, ErrorKind},
15 net::Ipv4Addr,
16 time::Instant,
17};
18
19pub struct ArpClient {
21 rx_channel: Box<dyn DataLinkReceiver>,
22 interface: Interface,
23}
24
25impl ArpClient {
26 pub fn new() -> Result<Self, Error> {
28 ArpClient::new_with_iface(&Interface::new()?)
29 }
30
31 pub fn new_with_iface_name(iface_name: &str) -> Result<Self, Error> {
33 let iface = Interface::new_by_name(iface_name);
34
35 match iface {
36 Some(iface) => ArpClient::new_with_iface(&iface),
37 None => Err(Error::new(ErrorKind::NotFound, "No such interface.")),
38 }
39 }
40
41 pub fn new_with_iface(interface: &Interface) -> Result<Self, Error> {
43 let result = interface.create_tx_rx_channels();
44
45 match result {
46 Ok((_, rx)) => Ok(ArpClient {
47 rx_channel: rx,
48 interface: interface.clone(),
49 }),
50 Err(err) => Err(err),
51 }
52 }
53
54 #[maybe_async::maybe_async]
57 pub async fn send_message(
58 &mut self,
59 timeout: Option<Duration>,
60 message: ArpMessage,
61 ) -> Result<ArpMessage, Error> {
62 self.send_message_with_check(timeout, message, |arp_message| Some(arp_message))
63 .await
64 }
65
66 #[maybe_async::maybe_async]
70 pub async fn send_message_with_check<T>(
71 &mut self,
72 timeout: Option<Duration>,
73 message: ArpMessage,
74 check_answer: impl Fn(ArpMessage) -> Option<T>,
75 ) -> Result<T, Error> {
76 let unpacked_timeout = match timeout {
77 Some(t) => t,
78 None => Duration::from_secs(u64::MAX),
80 };
81
82 match message.send(&self.interface) {
83 Err(e) => return Err(e),
84 _ => {}
85 }
86
87 let start_time = Instant::now();
88 while Instant::now() - start_time < unpacked_timeout {
89 match self.receive_next().await {
90 Some(arp_message) => match check_answer(arp_message) {
91 Some(result) => return Ok(result),
92 None => {}
93 },
94 _ => {}
95 }
96 }
97
98 return Err(Error::new(ErrorKind::TimedOut, "Timeout"));
99 }
100
101 #[maybe_async::maybe_async]
104 pub async fn ip_to_mac(
105 &mut self,
106 ip_addr: Ipv4Addr,
107 timeout: Option<Duration>,
108 ) -> Result<MacAddr, Error> {
109 let message = ArpMessage::new_arp_request(
110 self.interface.get_mac()?,
111 self.interface.get_ip()?,
112 ip_addr,
113 );
114
115 self.send_message_with_check(timeout, message, |arp_message| {
116 return if arp_message.source_protocol_address == ip_addr
117 && arp_message.operation == arp::Operation::ArpResponse
118 {
119 Some(arp_message.source_hardware_address.into())
120 } else {
121 None
122 };
123 })
124 .await
125 }
126
127 #[maybe_async::maybe_async]
130 pub async fn mac_to_ip(
131 &mut self,
132 mac_addr: MacAddr,
133 timeout: Option<Duration>,
134 ) -> Result<Ipv4Addr, Error> {
135 let message =
136 ArpMessage::new_rarp_request(self.interface.get_mac()?.into(), mac_addr.into());
137
138 self.send_message_with_check(timeout, message, |arp_message| {
139 let source_mac: MacAddr = arp_message.source_hardware_address.into();
140
141 if source_mac == mac_addr && arp_message.operation == arp::Operation::RarpResponse {
142 Some(arp_message.target_protocol_address)
143 } else {
144 None
145 }
146 })
147 .await
148 }
149
150 #[maybe_async::maybe_async]
152 pub async fn send(&self, arp_message: &ArpMessage) -> Result<(), Error> {
153 arp_message.send(&self.interface)
154 }
155
156 #[maybe_async::maybe_async]
159 pub async fn receive_next(&mut self) -> Option<ArpMessage> {
160 let rx_ethernet_packet = self.next_ethernet_frame().await;
161
162 match rx_ethernet_packet {
163 Some((packet, bytes))
164 if packet.get_ethertype() == EtherTypes::Arp
165 || packet.get_ethertype() == EtherTypes::Rarp =>
166 {
167 let arp_packet =
168 ArpPacket::new(&bytes[MutableEthernetPacket::minimum_packet_size()..]).unwrap();
169
170 match arp_packet.try_into() {
171 Ok(arp_packet) => return Some(arp_packet),
172 Err(_) => return None,
173 }
174 }
175 _ => return None,
176 }
177 }
178
179 #[maybe_async::maybe_async]
180 async fn next_ethernet_frame(&mut self) -> Option<(EthernetPacket<'_>, &[u8])> {
181 let rx_bytes = match self.rx_channel.next() {
182 Ok(rx_bytes) => rx_bytes,
183 Err(_) => return None,
184 };
185
186 match EthernetPacket::new(&rx_bytes) {
187 Some(frame) => Some((frame, rx_bytes)),
188 None => None,
189 }
190 }
191}