Skip to content

Instantly share code, notes, and snippets.

@tjamaan

tjamaan/tun.rs Secret

Last active February 26, 2018 11:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tjamaan/37350a418f37b5a7fc77e4a6956b0cee to your computer and use it in GitHub Desktop.
Save tjamaan/37350a418f37b5a7fc77e4a6956b0cee to your computer and use it in GitHub Desktop.
#[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