-
-
Save tjamaan/37350a418f37b5a7fc77e4a6956b0cee to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_use] | |
extern crate nix; | |
use nix::fcntl::{open, O_RDWR}; | |
use nix::sys::stat::Mode; | |
use std::os::unix::io::AsRawFd; | |
use std::os::raw::c_short; | |
use std::mem::size_of_val; | |
pub const IFF_TAP: c_short = 0x0002; | |
pub const IFF_NO_PI: c_short = 0x1000; | |
const INTERFACE_NAME_SIZE: usize = 16; | |
const INTERFACE_REQUEST_UNION_SIZE: usize = 24; | |
const TUN_MAGIC: u8 = b'T'; | |
const TUN_SET_IFF: u8 = 202; | |
#[repr(C)] | |
#[derive(Default)] | |
pub struct InterfaceRequest { | |
pub interface_name: [u8; INTERFACE_NAME_SIZE], | |
pub union: InterfaceRequestUnion, | |
} | |
impl InterfaceRequest { | |
pub fn with_interface_name(name: &str) -> Self { | |
let mut interface_request: Self = Default::default(); | |
interface_request.set_interface_name(name); | |
interface_request | |
} | |
pub fn set_interface_name(&mut self, name: &str) { | |
let name_len = name.len(); | |
let mut name = Vec::from(name); | |
if name_len < INTERFACE_NAME_SIZE { | |
name.resize(INTERFACE_NAME_SIZE, 0); | |
} else { | |
panic!("interface name too long"); | |
} | |
assert_eq!(name.len(), INTERFACE_NAME_SIZE); | |
self.interface_name.clone_from_slice(&name); | |
} | |
} | |
#[repr(C)] | |
pub union InterfaceRequestUnion { | |
pub data: [u8; INTERFACE_REQUEST_UNION_SIZE], | |
pub flags: c_short, | |
} | |
impl Default for InterfaceRequestUnion { | |
fn default() -> Self { | |
InterfaceRequestUnion { | |
data: Default::default(), | |
} | |
} | |
} | |
ioctl!(write_ptr tun_set_iff with TUN_MAGIC, TUN_SET_IFF; InterfaceRequest); | |
pub fn tun_alloc(name: &str, flags: c_short) { | |
let clone_dev = open("/dev/net/tun", O_RDWR, Mode::empty()); | |
let clone_dev = match clone_dev { | |
Ok(x) => x, | |
Err(e) => { | |
panic!("couldn't open clone device: {}", e); | |
} | |
}; | |
println!("clone_dev = {}", clone_dev); | |
let mut ifr = InterfaceRequest::with_interface_name(name); | |
ifr.union.flags = flags; | |
println!("sizeof ifr = {}", size_of_val(&ifr)); | |
println!("sizeof ifr.interface_name = {}", size_of_val(&ifr.interface_name)); | |
println!("sizeof ifr.union = {}", size_of_val(&ifr.union)); | |
println!("ifr.interface_name = {}", String::from_utf8_lossy(&ifr.interface_name)); | |
println!("ifr.data = {:?}", unsafe { ifr.union.data }); | |
match unsafe { tun_set_iff(clone_dev, &mut ifr as *mut _) } { | |
Ok(ret) => println!("tun_set_iff succeeded with ret = {}", ret), | |
Err(e) => println!("tun_set_iff failed with error: {}", e), | |
} | |
println!("ifr.interface_name = {}", String::from_utf8_lossy(&ifr.interface_name)); | |
println!("ifr.data = {:?}", unsafe { ifr.union.data }); | |
} | |
fn main() { | |
println!("Hello, world!"); | |
tun_alloc("my_premade_tap", IFF_TAP | IFF_NO_PI); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment