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