1 use super::*;
2 use crate::phy::Medium;
3 use std::os::unix::io::{AsRawFd, RawFd};
4 use std::{io, mem};
5 
6 #[derive(Debug)]
7 pub struct RawSocketDesc {
8     protocol: libc::c_short,
9     lower: libc::c_int,
10     ifreq: ifreq,
11 }
12 
13 impl AsRawFd for RawSocketDesc {
as_raw_fd(&self) -> RawFd14     fn as_raw_fd(&self) -> RawFd {
15         self.lower
16     }
17 }
18 
19 impl RawSocketDesc {
new(name: &str, medium: Medium) -> io::Result<RawSocketDesc>20     pub fn new(name: &str, medium: Medium) -> io::Result<RawSocketDesc> {
21         let protocol = match medium {
22             #[cfg(feature = "medium-ethernet")]
23             Medium::Ethernet => imp::ETH_P_ALL,
24             #[cfg(feature = "medium-ip")]
25             Medium::Ip => imp::ETH_P_ALL,
26             #[cfg(feature = "medium-ieee802154")]
27             Medium::Ieee802154 => imp::ETH_P_IEEE802154,
28         };
29 
30         let lower = unsafe {
31             let lower = libc::socket(
32                 libc::AF_PACKET,
33                 libc::SOCK_RAW | libc::SOCK_NONBLOCK,
34                 protocol.to_be() as i32,
35             );
36             if lower == -1 {
37                 return Err(io::Error::last_os_error());
38             }
39             lower
40         };
41 
42         Ok(RawSocketDesc {
43             protocol,
44             lower,
45             ifreq: ifreq_for(name),
46         })
47     }
48 
interface_mtu(&mut self) -> io::Result<usize>49     pub fn interface_mtu(&mut self) -> io::Result<usize> {
50         ifreq_ioctl(self.lower, &mut self.ifreq, imp::SIOCGIFMTU).map(|mtu| mtu as usize)
51     }
52 
bind_interface(&mut self) -> io::Result<()>53     pub fn bind_interface(&mut self) -> io::Result<()> {
54         let sockaddr = libc::sockaddr_ll {
55             sll_family: libc::AF_PACKET as u16,
56             sll_protocol: self.protocol.to_be() as u16,
57             sll_ifindex: ifreq_ioctl(self.lower, &mut self.ifreq, imp::SIOCGIFINDEX)?,
58             sll_hatype: 1,
59             sll_pkttype: 0,
60             sll_halen: 6,
61             sll_addr: [0; 8],
62         };
63 
64         unsafe {
65             let res = libc::bind(
66                 self.lower,
67                 &sockaddr as *const libc::sockaddr_ll as *const libc::sockaddr,
68                 mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t,
69             );
70             if res == -1 {
71                 return Err(io::Error::last_os_error());
72             }
73         }
74 
75         Ok(())
76     }
77 
recv(&mut self, buffer: &mut [u8]) -> io::Result<usize>78     pub fn recv(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
79         unsafe {
80             let len = libc::recv(
81                 self.lower,
82                 buffer.as_mut_ptr() as *mut libc::c_void,
83                 buffer.len(),
84                 0,
85             );
86             if len == -1 {
87                 return Err(io::Error::last_os_error());
88             }
89             Ok(len as usize)
90         }
91     }
92 
send(&mut self, buffer: &[u8]) -> io::Result<usize>93     pub fn send(&mut self, buffer: &[u8]) -> io::Result<usize> {
94         unsafe {
95             let len = libc::send(
96                 self.lower,
97                 buffer.as_ptr() as *const libc::c_void,
98                 buffer.len(),
99                 0,
100             );
101             if len == -1 {
102                 return Err(io::Error::last_os_error());
103             }
104             Ok(len as usize)
105         }
106     }
107 }
108 
109 impl Drop for RawSocketDesc {
drop(&mut self)110     fn drop(&mut self) {
111         unsafe {
112             libc::close(self.lower);
113         }
114     }
115 }
116