cursock/
arp.rs

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    /// Initializes arp structure
15    ///
16    /// # Examples
17    /// ```
18    /// use cursock::*;
19    /// use cursock::utils::*;
20    /// #[cfg(target_os = "linux")]
21    /// let arp = Arp::new("wlan0").expect("initialize error"); // Linux
22    /// #[cfg(target_os = "windows")]
23    /// let arp = Arp::new("10").expect("initialize error"); // Windows, id of the interface you can get running "route PRINT"
24    /// ```
25    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    /// Does an arp request
34    /// # Examples
35    /// ```
36    /// use cursock::*;
37    /// use std::net::Ipv4Addr;
38    ///
39    /// let arp = Arp::new("wlan0").expect("initialize error");
40    /// let ip_addr: Ipv4Addr = Ipv4Addr::from([192, 168, 0, 1]);
41    /// let response = arp.who_has(&ip_addr).expect("send error");
42    /// ```
43    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    /// Does an arp reply
94    /// # Examples
95    /// ```
96    /// use cursock::*;
97    /// use std::net::Ipv4Addr;
98    ///
99    /// let arp = Arp::new("wlan0").expect("initialize error");
100    /// let ip_addr1: Ipv4Addr = Ipv4Addr::from([192, 168, 1, 1]);
101    /// let mac_addr1: Mac = Mac::from([0xff; 6]);
102    /// let ip_addr2: Ipv4Addr = Ipv4Addr::from([192, 168, 1, 2]);
103    /// arp.is_at(arp.get_src_mac(), &ip_addr1, &mac_addr1, &ip_addr2).expect("send error")
104    /// ```
105    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                // storing mac addresses into cache
159                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    /// Destroys arp structure
181    ///
182    /// # Examples
183    /// ```
184    /// use cursock::*;
185    ///
186    /// let arp = cursock::Arp::new("wlan0").expect("initialize error");
187    /// arp.destroy()
188    /// ```
189    pub fn destroy(&self) {
190        self.socket.destroy()
191    }
192
193    getters!(
194        pub get_socket(socket) -> Socket;
195    );
196}