1use std::collections::HashMap;
2use std::io;
3use std::net;
4
5use crate::*;
6
7#[derive(Clone)]
8pub struct Arp {
9 socket: Socket,
10 cache: HashMap<net::Ipv4Addr, Mac>,
11}
12
13impl Arp {
14 pub fn new(interface: &str) -> io::Result<Self> {
26 let socket: Socket = Socket::new(interface)?;
27
28 Ok(Self {
29 socket,
30 cache: HashMap::new(),
31 })
32 }
33 pub fn who_has(&mut self, dst_ip: &net::Ipv4Addr) -> io::Result<ArpResponse> {
44 let adapter = self.socket.get_adapter();
45 let src_ip = adapter.get_ipv4().ok_or(io::Error::new(
46 io::ErrorKind::NotFound,
47 format!(
48 "To send ARP request you need to have ipv4 source address ({})",
49 adapter.to_string()
50 ),
51 ))?;
52
53 if let Some(mac) = self.cache.get(dst_ip) {
54 return Ok(ArpResponse::new(
55 *dst_ip,
56 mac.clone(),
57 src_ip,
58 adapter.get_mac().clone(),
59 ));
60 }
61
62 const BUFFER_SIZE: usize = ETH_HEADER_SIZE + ARP_HEADER_SIZE;
63 let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
64
65 let eth_header: &mut EthHeader = unsafe { &mut *(buffer.as_mut_ptr() as *mut EthHeader) };
66 let arp_header: &mut ArpHeader =
67 unsafe { &mut *((buffer.as_mut_ptr() as usize + ETH_HEADER_SIZE) as *mut ArpHeader) };
68
69 eth_header.dest = [0xff; MAC_LEN];
70
71 eth_header.source = self.socket.get_src_mac().clone().into();
72 arp_header.target_mac = [0; MAC_LEN];
73 arp_header.sender_mac = self.socket.get_src_mac().clone().into();
74
75 eth_header.proto = u16::from_be(ARP_PROTO);
76
77 arp_header.hardware_type = u16::from_be(HW_TYPE);
78 arp_header.protocol_type = u16::from_be(IPV4_PROTO);
79 arp_header.hardware_len = MAC_LEN as u8;
80 arp_header.protocol_len = IPV4_LEN as u8;
81 arp_header.opcode = u16::from_be(ARP_REQUEST);
82
83 arp_header.sender_ip = src_ip.octets();
84 arp_header.target_ip = dst_ip.octets();
85
86 self.socket.send_raw_packet(&buffer)?;
87
88 self.read_arp(|header| {
89 u16::from_be(header.opcode) == ARP_REPLY
90 && &net::Ipv4Addr::from(header.sender_ip) == dst_ip
91 })
92 }
93 pub fn is_at(
106 &self,
107 src_mac: &Mac,
108 src_ip: &net::Ipv4Addr,
109 dst_mac: &Mac,
110 dst_ip: &net::Ipv4Addr,
111 ) -> io::Result<()> {
112 const BUFFER_SIZE: usize = ETH_HEADER_SIZE + ARP_HEADER_SIZE;
113 let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
114
115 let eth_header: &mut EthHeader = unsafe { &mut *(buffer.as_mut_ptr() as *mut EthHeader) };
116 let arp_header: &mut ArpHeader =
117 unsafe { &mut *((buffer.as_mut_ptr() as usize + ETH_HEADER_SIZE) as *mut ArpHeader) };
118
119 eth_header.dest = dst_mac.clone().into();
120
121 eth_header.source = self.socket.get_src_mac().clone().into();
122 arp_header.target_mac = dst_mac.clone().into();
123 arp_header.sender_mac = src_mac.clone().into();
124
125 eth_header.proto = u16::from_be(ARP_PROTO);
126
127 arp_header.hardware_type = u16::from_be(HW_TYPE);
128 arp_header.protocol_type = u16::from_be(IPV4_PROTO);
129 arp_header.hardware_len = MAC_LEN as u8;
130 arp_header.protocol_len = IPV4_LEN as u8;
131 arp_header.opcode = u16::from_be(ARP_REPLY);
132
133 arp_header.sender_ip = src_ip.octets();
134 arp_header.target_ip = dst_ip.octets();
135
136 self.socket.send_raw_packet(&buffer)
137 }
138
139 fn read_arp<F>(&mut self, mut closure: F) -> io::Result<ArpResponse>
140 where
141 F: FnMut(&ArpHeader) -> bool,
142 {
143 const BUFFER_SIZE: usize = 60;
144 let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
145
146 let eth_header: &EthHeader = unsafe { &*(buffer.as_ptr() as *mut EthHeader) };
147 let arp_header: &ArpHeader =
148 unsafe { &*((buffer.as_ptr() as usize + ETH_HEADER_SIZE) as *mut ArpHeader) };
149
150 loop {
151 self.socket.read_raw_packet(&mut buffer)?;
152
153 if u16::from_be(eth_header.proto) != ARP_PROTO {
154 continue;
155 }
156
157 if u16::from_be(arp_header.opcode) == ARP_REPLY {
158 self.cache.insert(
160 net::Ipv4Addr::from(arp_header.sender_ip),
161 Mac::from(arp_header.sender_mac),
162 );
163 }
164
165 if closure(arp_header) {
166 break;
167 }
168 }
169
170 let arp_response: ArpResponse = ArpResponse::new(
171 net::Ipv4Addr::from(arp_header.sender_ip),
172 Mac::from(arp_header.sender_mac),
173 net::Ipv4Addr::from(arp_header.target_ip),
174 Mac::from(arp_header.target_mac),
175 );
176
177 Ok(arp_response)
178 }
179
180 pub fn destroy(&self) {
190 self.socket.destroy()
191 }
192
193 getters!(
194 pub get_socket(socket) -> Socket;
195 );
196}