tap_interface.rs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. use std::io;
  2. use std::os::unix::io::{RawFd, AsRawFd};
  3. use super::*;
  4. use crate::wire::EthernetFrame;
  5. #[derive(Debug)]
  6. pub struct TapInterfaceDesc {
  7. lower: libc::c_int,
  8. ifreq: ifreq
  9. }
  10. impl AsRawFd for TapInterfaceDesc {
  11. fn as_raw_fd(&self) -> RawFd {
  12. self.lower
  13. }
  14. }
  15. impl TapInterfaceDesc {
  16. pub fn new(name: &str) -> io::Result<TapInterfaceDesc> {
  17. let lower = unsafe {
  18. let lower = libc::open("/dev/net/tun\0".as_ptr() as *const libc::c_char,
  19. libc::O_RDWR | libc::O_NONBLOCK);
  20. if lower == -1 { return Err(io::Error::last_os_error()) }
  21. lower
  22. };
  23. Ok(TapInterfaceDesc {
  24. lower: lower,
  25. ifreq: ifreq_for(name)
  26. })
  27. }
  28. pub fn attach_interface(&mut self) -> io::Result<()> {
  29. self.ifreq.ifr_data = imp::IFF_TAP | imp::IFF_NO_PI;
  30. ifreq_ioctl(self.lower, &mut self.ifreq, imp::TUNSETIFF).map(|_| ())
  31. }
  32. pub fn interface_mtu(&mut self) -> io::Result<usize> {
  33. let lower = unsafe {
  34. let lower = libc::socket(libc::AF_INET, libc::SOCK_DGRAM, libc::IPPROTO_IP);
  35. if lower == -1 { return Err(io::Error::last_os_error()) }
  36. lower
  37. };
  38. let ip_mtu = ifreq_ioctl(lower, &mut self.ifreq, imp::SIOCGIFMTU).map(|mtu| mtu as usize);
  39. unsafe { libc::close(lower); }
  40. // SIOCGIFMTU returns the IP MTU (typically 1500 bytes.)
  41. // smoltcp counts the entire Ethernet packet in the MTU, so add the Ethernet header size to it.
  42. Ok(ip_mtu? + EthernetFrame::<&[u8]>::header_len())
  43. }
  44. pub fn recv(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
  45. unsafe {
  46. let len = libc::read(self.lower, buffer.as_mut_ptr() as *mut libc::c_void,
  47. buffer.len());
  48. if len == -1 { return Err(io::Error::last_os_error()) }
  49. Ok(len as usize)
  50. }
  51. }
  52. pub fn send(&mut self, buffer: &[u8]) -> io::Result<usize> {
  53. unsafe {
  54. let len = libc::write(self.lower, buffer.as_ptr() as *const libc::c_void,
  55. buffer.len());
  56. if len == -1 { Err(io::Error::last_os_error()).unwrap() }
  57. Ok(len as usize)
  58. }
  59. }
  60. }
  61. impl Drop for TapInterfaceDesc {
  62. fn drop(&mut self) {
  63. unsafe { libc::close(self.lower); }
  64. }
  65. }