合并tun、tap配置,减少重复代码
This commit is contained in:
@@ -1,58 +0,0 @@
|
||||
use crate::tun_device::{TunReader, TunWriter};
|
||||
|
||||
pub type TapReader = TunReader;
|
||||
pub type TapWriter = TunWriter;
|
||||
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use tun::Device;
|
||||
use parking_lot::Mutex;
|
||||
use std::io;
|
||||
|
||||
pub fn create_tap(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
) -> io::Result<(TunWriter, TunReader, [u8; 6])> {
|
||||
println!("========TAP网卡配置========");
|
||||
let mut config = tun::Configuration::default();
|
||||
|
||||
config
|
||||
.destination(gateway)
|
||||
.address(address)
|
||||
.netmask(netmask)
|
||||
.mtu(1420)
|
||||
.layer(tun::Layer::L2)
|
||||
// .queues(2) 用多个队列有兼容性问题
|
||||
.up();
|
||||
|
||||
let dev = tun::create(&config).unwrap();
|
||||
let name = dev.name();
|
||||
println!("name:{:?}", name);
|
||||
let packet_information = dev.has_packet_information();
|
||||
let queue = dev.queue(0).unwrap();
|
||||
let reader = queue.reader();
|
||||
let writer = queue.writer();
|
||||
let get_mac_cmd = format!("cat /sys/class/net/{}/address", name);
|
||||
let mac_out = std::process::Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(get_mac_cmd)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !mac_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("获取mac地址错误: {:?}", mac_out)));
|
||||
}
|
||||
let mac_str = String::from_utf8(mac_out.stdout).unwrap();
|
||||
let mut mac = [0; 6];
|
||||
let mut split = mac_str.split(":");
|
||||
for i in 0..6 {
|
||||
mac[i] = u8::from_str_radix(&split.next().unwrap()[..2], 16).unwrap();
|
||||
}
|
||||
println!("mac:{:?}", mac);
|
||||
println!("========TAP网卡配置========");
|
||||
Ok((
|
||||
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
|
||||
TunReader(reader, packet_information),
|
||||
mac
|
||||
))
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
use crate::tun_device::{TunReader, TunWriter};
|
||||
|
||||
pub type TapReader = TunReader;
|
||||
pub type TapWriter = TunWriter;
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
pub fn create_tap(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
) -> crate::error::Result<(TapWriter, TapReader, [u8; 6])> {
|
||||
unimplemented!()
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#[cfg(target_os = "windows")]
|
||||
mod windows;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
mod linux;
|
||||
#[cfg(target_os = "macos")]
|
||||
mod mac;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use mac::{TapWriter, TapReader};
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use mac::create_tap;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub use linux::{TapWriter, TapReader};
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub use linux::create_tap;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::create_tap;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::delete_tap;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::{TapReader, TapWriter};
|
||||
@@ -1,101 +0,0 @@
|
||||
use std::io;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use win_tun_tap::{IFace, TapDevice};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TapWriter(Arc<TapDevice>, Arc<Mutex<()>>);
|
||||
|
||||
impl TapWriter {
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
|
||||
pub fn change_ip(
|
||||
&self,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
old_netmask: Ipv4Addr,
|
||||
old_gateway: Ipv4Addr,
|
||||
) -> io::Result<()> {
|
||||
if let Err(e) =
|
||||
self.0.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway)
|
||||
{
|
||||
log::warn!("{:?}", e);
|
||||
}
|
||||
self.0.set_ip(address, netmask)?;
|
||||
self.0.add_route(dest(gateway, netmask), netmask, gateway)
|
||||
}
|
||||
pub fn close(&self) -> io::Result<()> {
|
||||
self.0.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
fn dest(ip: Ipv4Addr, mask: Ipv4Addr) -> Ipv4Addr {
|
||||
let ip = ip.octets();
|
||||
let mask = mask.octets();
|
||||
Ipv4Addr::from([
|
||||
ip[0] & mask[0],
|
||||
ip[1] & mask[1],
|
||||
ip[2] & mask[2],
|
||||
ip[3] & mask[3],
|
||||
])
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TapReader(Arc<TapDevice>);
|
||||
|
||||
impl TapReader {
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
pub const TAP_INTERFACE_NAME: &str = "Switch-Tap-V1";
|
||||
|
||||
pub fn create_tap(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
) -> io::Result<(TapWriter, TapReader, [u8; 6])> {
|
||||
println!("========TAP网卡配置========");
|
||||
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
|
||||
Ok(tap_device) => tap_device,
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e);
|
||||
let tap_device = TapDevice::create()?;
|
||||
tap_device.set_name(TAP_INTERFACE_NAME)?;
|
||||
tap_device
|
||||
}
|
||||
};
|
||||
let mac = tap_device.get_mac()?;
|
||||
println!("name:{:?}", tap_device.get_name()?);
|
||||
println!("version:{:x?}", tap_device.get_version()?);
|
||||
println!("mac:{:x?}", mac);
|
||||
tap_device.set_ip(address, netmask)?;
|
||||
tap_device.set_metric(1)?;
|
||||
tap_device.set_mtu(1420)?;
|
||||
tap_device.set_status(true)?;
|
||||
tap_device.add_route(address, netmask, gateway)?;
|
||||
let tap = Arc::new(tap_device);
|
||||
println!("========TAP网卡配置========");
|
||||
Ok((
|
||||
TapWriter(tap.clone(), Arc::default()),
|
||||
TapReader(tap),
|
||||
mac
|
||||
))
|
||||
}
|
||||
|
||||
pub fn delete_tap() {
|
||||
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
|
||||
Ok(tap_device) => tap_device,
|
||||
Err(_) => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let _ = tap_device.delete();
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
use std::io;
|
||||
use crate::tun_device::{TunReader, TunWriter};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use tun::Device;
|
||||
use parking_lot::Mutex;
|
||||
use std::process::Command;
|
||||
|
||||
pub fn create_tun(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
) -> crate::error::Result<(TunWriter, TunReader)> {
|
||||
println!("========TUN网卡配置========");
|
||||
let mut config = tun::Configuration::default();
|
||||
|
||||
config
|
||||
.destination(gateway)
|
||||
.address(address)
|
||||
.netmask(netmask)
|
||||
.mtu(1420)
|
||||
// .queues(2) 用多个队列有兼容性问题
|
||||
.up();
|
||||
|
||||
let dev = tun::create(&config).unwrap();
|
||||
let packet_information = dev.has_packet_information();
|
||||
let queue = dev.queue(0).unwrap();
|
||||
let reader = queue.reader();
|
||||
let writer = queue.writer();
|
||||
let name = dev.name();
|
||||
println!("name:{:?}", name);
|
||||
for (address, netmask) in in_ips {
|
||||
add_route(name, address, netmask)?;
|
||||
}
|
||||
println!("========TUN网卡配置========");
|
||||
Ok((
|
||||
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
|
||||
TunReader(reader, packet_information),
|
||||
))
|
||||
}
|
||||
|
||||
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
||||
let route_add_str: String = format!(
|
||||
"ip route add {:?}/{:?} dev {}",
|
||||
address, netmask, name
|
||||
);
|
||||
let route_add_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(route_add_str)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !route_add_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", route_add_out)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
use std::net::Ipv4Addr;
|
||||
use std::process::Command;
|
||||
use std::io;
|
||||
use tun::Device;
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::tun_device::{TunReader, TunWriter};
|
||||
|
||||
pub fn create_tun(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
) -> crate::error::Result<(TunWriter, TunReader)> {
|
||||
println!("========TUN网卡配置========");
|
||||
let mut config = tun::Configuration::default();
|
||||
|
||||
config
|
||||
.destination(gateway)
|
||||
.address(address)
|
||||
.netmask(netmask)
|
||||
.mtu(1420)
|
||||
.up();
|
||||
|
||||
let dev = tun::create(&config).unwrap();
|
||||
let name = dev.name();
|
||||
config_ip(name, address, netmask, gateway)?;
|
||||
add_route(name, address, netmask)?;
|
||||
for (address, netmask) in in_ips {
|
||||
add_route(name, address, netmask)?;
|
||||
}
|
||||
let packet_information = dev.has_packet_information();
|
||||
let queue = dev.queue(0).unwrap();
|
||||
let reader = queue.reader();
|
||||
let writer = queue.writer();
|
||||
println!("name:{:?}", name);
|
||||
println!("========TUN网卡配置========");
|
||||
Ok((
|
||||
TunWriter(writer, packet_information, Arc::new(Mutex::new(dev))),
|
||||
TunReader(reader, packet_information),
|
||||
))
|
||||
}
|
||||
|
||||
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
||||
let route_add_str: String = format!(
|
||||
"sudo route -n add -net {:?}/{:?} -interface {}",
|
||||
address, netmask, name
|
||||
);
|
||||
let route_add_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(route_add_str)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !route_add_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: {:?}", route_add_out)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn config_ip(name: &str, address: Ipv4Addr, netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
||||
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", name, address, gateway);
|
||||
let up_eth_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(up_eth_str)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !up_eth_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: {:?}", up_eth_out)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub use linux::create_tun;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use mac::create_tun;
|
||||
#[cfg(any(unix))]
|
||||
pub use unix::{TunReader, TunWriter};
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::create_tun;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::delete_tun;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::{TunReader, TunWriter};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub mod linux;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod mac;
|
||||
#[cfg(any(unix))]
|
||||
pub mod unix;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub mod windows;
|
||||
@@ -1,72 +0,0 @@
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
|
||||
use bytes::BufMut;
|
||||
use tun::platform::posix::{Reader, Writer};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use tun::platform::linux::Device;
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
use tun::platform::macos::Device;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TunReader(pub(crate) Reader, pub(crate) bool);
|
||||
|
||||
impl TunReader {
|
||||
pub fn read(&self, buf: & mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TunWriter(pub(crate) Writer, pub(crate) bool, pub(crate) Arc<Mutex<Device>>);
|
||||
|
||||
impl TunWriter {
|
||||
pub fn write(&self, packet: &[u8]) -> io::Result<()> {
|
||||
if self.1 {
|
||||
let mut buf = Vec::<u8>::with_capacity(4 + packet.len());
|
||||
buf.put_u16(0);
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
buf.put_u16(libc::PF_INET as u16);
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
buf.put_u16(libc::ETH_P_IP as u16);
|
||||
buf.extend_from_slice(packet);
|
||||
self.0.write_all(&buf)
|
||||
} else {
|
||||
self.0.write_all(packet)
|
||||
}
|
||||
}
|
||||
pub fn close(&self) -> io::Result<()>{
|
||||
unsafe {
|
||||
let raw = self.0.as_raw_fd();
|
||||
if raw >= 0 {
|
||||
libc::close(raw);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
|
||||
let mut config = tun::Configuration::default();
|
||||
use tun::Device;
|
||||
config
|
||||
.destination(gateway)
|
||||
.address(address)
|
||||
.netmask(netmask)
|
||||
.mtu(1420)
|
||||
// .queues(2)
|
||||
.up();
|
||||
let mut dev = self.2.lock();
|
||||
if let Err(e) = dev.configure(&config) {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
if let Err(e) = crate::tun_device::mac::config_ip(dev.name(), address, netmask, gateway){
|
||||
log::error!("{}",e);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
use std::{io, thread};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use libloading::Library;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use win_tun_tap::{IFace, TunDevice};
|
||||
use win_tun_tap::packet::TunPacket;
|
||||
|
||||
pub const TUN_INTERFACE_NAME: &str = "Switch-V1";
|
||||
pub const TUN_POOL_NAME: &str = "Switch-V1";
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TunWriter(Arc<TunDevice>, Arc<Mutex<()>>);
|
||||
|
||||
impl TunWriter {
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<()> {
|
||||
let mut packet = self.0.allocate_send_packet(buf.len() as u16)?;
|
||||
packet.bytes_mut().copy_from_slice(buf);
|
||||
self.0.send_packet(packet);
|
||||
return Ok(());
|
||||
}
|
||||
pub fn change_ip(
|
||||
&self,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
old_netmask: Ipv4Addr,
|
||||
old_gateway: Ipv4Addr,
|
||||
) -> io::Result<()> {
|
||||
if let Err(e) =
|
||||
self.0.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway)
|
||||
{
|
||||
log::warn!("{:?}", e);
|
||||
}
|
||||
self.0.set_ip(address, netmask)?;
|
||||
self.0.add_route(dest(gateway, netmask), netmask, gateway)
|
||||
}
|
||||
pub fn close(&self) -> io::Result<()> {
|
||||
self.0.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
fn dest(ip: Ipv4Addr, mask: Ipv4Addr) -> Ipv4Addr {
|
||||
let ip = ip.octets();
|
||||
let mask = mask.octets();
|
||||
Ipv4Addr::from([
|
||||
ip[0] & mask[0],
|
||||
ip[1] & mask[1],
|
||||
ip[2] & mask[2],
|
||||
ip[3] & mask[3],
|
||||
])
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TunReader(Arc<TunDevice>);
|
||||
|
||||
|
||||
impl TunReader {
|
||||
pub fn next(&self) -> io::Result<TunPacket> {
|
||||
self.0.receive_blocking()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_tun(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips:Vec<(Ipv4Addr,Ipv4Addr)>
|
||||
) -> io::Result<(TunWriter, TunReader)> {
|
||||
unsafe {
|
||||
println!("========TUN网卡配置========");
|
||||
match Library::new("wintun.dll") {
|
||||
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
|
||||
Ok(_) => {
|
||||
thread::sleep(Duration::from_millis(5));
|
||||
}
|
||||
Err(_) => {}
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("wintun.dll not found");
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("wintun.dll not found {:?}", e),
|
||||
));
|
||||
}
|
||||
}
|
||||
let tun_device = match TunDevice::create(
|
||||
Library::new("wintun.dll").unwrap(),
|
||||
TUN_POOL_NAME,
|
||||
TUN_INTERFACE_NAME,
|
||||
) {
|
||||
Ok(tun_device) => tun_device,
|
||||
Err(_) => {
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
match TunDevice::create(
|
||||
Library::new("wintun.dll").unwrap(),
|
||||
TUN_POOL_NAME,
|
||||
TUN_INTERFACE_NAME,
|
||||
) {
|
||||
Ok(tun_device) => tun_device,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("{:?}", e),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
println!("name:{:?}", tun_device.get_name()?);
|
||||
println!("version:{:?}", tun_device.version()?);
|
||||
tun_device.set_ip(address, netmask)?;
|
||||
tun_device.set_metric(1)?;
|
||||
tun_device.set_mtu(1420)?;
|
||||
for (address, netmask) in in_ips {
|
||||
tun_device.add_route(address, netmask, gateway)?;
|
||||
}
|
||||
tun_device.add_route(address, netmask, gateway)?;
|
||||
let device = Arc::new(tun_device);
|
||||
println!("========TUN网卡配置========");
|
||||
Ok((
|
||||
TunWriter(device.clone(), Arc::default()),
|
||||
TunReader(device),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_tun() {
|
||||
unsafe {
|
||||
match Library::new("wintun.dll") {
|
||||
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
|
||||
Ok(_) => {
|
||||
}
|
||||
Err(_) => {}
|
||||
},
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
use std::io;
|
||||
use std::net::Ipv4Addr;
|
||||
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter};
|
||||
use tun::Device;
|
||||
use parking_lot::Mutex;
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
use crate::tun_tap_device::unix::DeviceW;
|
||||
|
||||
impl DeviceWriter {
|
||||
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
|
||||
let mut config = tun::Configuration::default();
|
||||
config
|
||||
.destination(gateway)
|
||||
.address(address)
|
||||
.netmask(netmask)
|
||||
.mtu(1420)
|
||||
// .queues(2)
|
||||
.up();
|
||||
let mut dev = self.lock.lock();
|
||||
if let Err(e) = dev.configure(&config) {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
|
||||
}
|
||||
let name = dev.name();
|
||||
for (address, netmask) in &self.in_ips {
|
||||
add_route(name, *address, *netmask)?;
|
||||
}
|
||||
// 当前网段路由
|
||||
// add_route(name, address, netmask)?;
|
||||
// 广播和组播路由
|
||||
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
||||
let route_add_str: String = format!(
|
||||
"ip route add {:?}/{:?} dev {}",
|
||||
address, netmask, name
|
||||
);
|
||||
let route_add_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(&route_add_str)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !route_add_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: cmd:{},out:{:?}", route_add_str, route_add_out)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn create_device(device_type: DeviceType,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
) -> io::Result<(DeviceWriter, DeviceReader)> {
|
||||
println!("========网卡配置========");
|
||||
let mut config = tun::Configuration::default();
|
||||
|
||||
config
|
||||
.destination(gateway)
|
||||
.address(address)
|
||||
.netmask(netmask)
|
||||
.mtu(1420)
|
||||
// .queues(2) 用多个队列有兼容性问题
|
||||
.up();
|
||||
match device_type {
|
||||
DeviceType::Tun => {}
|
||||
DeviceType::Tap => {
|
||||
config.layer(tun::Layer::L2);
|
||||
}
|
||||
}
|
||||
let dev = tun::create(&config).unwrap();
|
||||
let packet_information = dev.has_packet_information();
|
||||
let queue = dev.queue(0).unwrap();
|
||||
let reader = queue.reader();
|
||||
let writer = queue.writer();
|
||||
let name = dev.name();
|
||||
println!("name:{:?}", name);
|
||||
for (address, netmask) in &in_ips {
|
||||
add_route(name, *address, *netmask)?;
|
||||
}
|
||||
// 当前网段路由
|
||||
// add_route(name, address, netmask)?;
|
||||
// 广播和组播路由
|
||||
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||
let device_w = match device_type {
|
||||
DeviceType::Tun => {
|
||||
DeviceW::Tun(writer)
|
||||
}
|
||||
DeviceType::Tap => {
|
||||
let get_mac_cmd = format!("cat /sys/class/net/{}/address", name);
|
||||
let mac_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(get_mac_cmd)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !mac_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("获取mac地址错误: {:?}", mac_out)));
|
||||
}
|
||||
let mac_str = String::from_utf8(mac_out.stdout).unwrap();
|
||||
let mut mac = [0; 6];
|
||||
let mut split = mac_str.split(":");
|
||||
for i in 0..6 {
|
||||
mac[i] = u8::from_str_radix(&split.next().unwrap()[..2], 16).unwrap();
|
||||
}
|
||||
DeviceW::Tap((writer, mac))
|
||||
}
|
||||
};
|
||||
println!("========TUN网卡配置========");
|
||||
Ok((
|
||||
DeviceWriter::new(device_w, Arc::new(Mutex::new(dev)), in_ips, address, packet_information),
|
||||
DeviceReader::new(reader),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn delete_device(_device_type: DeviceType) {}
|
||||
@@ -0,0 +1,114 @@
|
||||
use std::io;
|
||||
use std::net::Ipv4Addr;
|
||||
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter};
|
||||
use tun::Device;
|
||||
use parking_lot::Mutex;
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
use crate::tun_tap_device::unix::DeviceW;
|
||||
|
||||
impl DeviceWriter {
|
||||
pub fn change_ip(&self, address: Ipv4Addr, netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr, _old_netmask: Ipv4Addr, _old_gateway: Ipv4Addr) -> io::Result<()> {
|
||||
let mut config = tun::Configuration::default();
|
||||
config
|
||||
.destination(gateway)
|
||||
.address(address)
|
||||
.netmask(netmask)
|
||||
.mtu(1420)
|
||||
.up();
|
||||
let mut dev = self.lock.lock();
|
||||
if let Err(e) = dev.configure(&config) {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("{:?}", e)));
|
||||
}
|
||||
if let Err(e) = config_ip(dev.name(), address, netmask, gateway) {
|
||||
log::error!("{}",e);
|
||||
}
|
||||
let name = dev.name();
|
||||
for (address, netmask) in &self.in_ips {
|
||||
add_route(name, *address, *netmask)?;
|
||||
}
|
||||
// 当前网段路由
|
||||
add_route(name, address, netmask)?;
|
||||
// 广播和组播路由
|
||||
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_device(device_type: DeviceType,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
) -> io::Result<(DeviceWriter, DeviceReader)> {
|
||||
match device_type {
|
||||
DeviceType::Tun => {}
|
||||
DeviceType::Tap => {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
println!("========TUN网卡配置========");
|
||||
let mut config = tun::Configuration::default();
|
||||
|
||||
config
|
||||
.destination(gateway)
|
||||
.address(address)
|
||||
.netmask(netmask)
|
||||
.mtu(1420)
|
||||
.up();
|
||||
|
||||
let dev = tun::create(&config).unwrap();
|
||||
let name = dev.name();
|
||||
config_ip(name, address, netmask, gateway)?;
|
||||
for (address, netmask) in &in_ips {
|
||||
add_route(name, *address, *netmask)?;
|
||||
}
|
||||
// 当前网段路由
|
||||
add_route(name, address, netmask)?;
|
||||
// 广播和组播路由
|
||||
add_route(name, Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST)?;
|
||||
add_route(name, Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]))?;
|
||||
let packet_information = dev.has_packet_information();
|
||||
let queue = dev.queue(0).unwrap();
|
||||
let reader = queue.reader();
|
||||
let writer = queue.writer();
|
||||
println!("name:{:?}", name);
|
||||
println!("========TUN网卡配置========");
|
||||
Ok((
|
||||
DeviceWriter::new(DeviceW::Tun(writer), Arc::new(Mutex::new(dev)), in_ips, address, packet_information),
|
||||
DeviceReader::new(reader),
|
||||
))
|
||||
}
|
||||
|
||||
fn add_route(name: &str, address: Ipv4Addr, netmask: Ipv4Addr) -> io::Result<()> {
|
||||
let route_add_str: String = format!(
|
||||
"sudo route -n add -net {:?}/{:?} -interface {}",
|
||||
address, netmask, name
|
||||
);
|
||||
let route_add_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(&route_add_str)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !route_add_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("添加路由失败: cmd:{},out:{:?}", route_add_str, route_add_out)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_ip(name: &str, address: Ipv4Addr, _netmask: Ipv4Addr, gateway: Ipv4Addr) -> io::Result<()> {
|
||||
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", name, address, gateway);
|
||||
let up_eth_out = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(&up_eth_str)
|
||||
.output()
|
||||
.expect("sh exec error!");
|
||||
if !up_eth_out.status.success() {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, format!("设置网络地址失败: cmd:{},out:{:?}", up_eth_str, up_eth_out)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete_device(_device_type: DeviceType) {}
|
||||
@@ -0,0 +1,32 @@
|
||||
#[cfg(target_os = "windows")]
|
||||
pub mod windows;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub mod linux;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod mac;
|
||||
#[cfg(any(unix))]
|
||||
pub mod unix;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub use linux::create_device;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub use linux::delete_device;
|
||||
#[cfg(any(unix))]
|
||||
pub use unix::{DeviceWriter, DeviceReader};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use mac::create_device;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use mac::delete_device;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::create_device;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::delete_device;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::{DeviceWriter, DeviceReader};
|
||||
|
||||
pub enum DeviceType {
|
||||
Tun,
|
||||
Tap,
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
|
||||
use bytes::BufMut;
|
||||
use tun::platform::posix::{Reader, Writer};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
use tun::platform::linux::Device;
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
use tun::platform::macos::Device;
|
||||
use parking_lot::Mutex;
|
||||
use packet::ethernet;
|
||||
|
||||
use packet::ethernet::packet::EthernetPacket;
|
||||
#[derive(Clone)]
|
||||
pub enum DeviceW {
|
||||
Tun(Writer),
|
||||
Tap((Writer, [u8; 6])),
|
||||
}
|
||||
|
||||
impl DeviceW {
|
||||
pub fn is_tun(&self) -> bool {
|
||||
match self {
|
||||
DeviceW::Tun(_) => {
|
||||
true
|
||||
}
|
||||
DeviceW::Tap(_) => {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DeviceWriter {
|
||||
writer: DeviceW,
|
||||
pub lock: Arc<Mutex<Device>>,
|
||||
pub in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
ip: Arc<AtomicCell<Ipv4Addr>>,
|
||||
packet_information: bool,
|
||||
}
|
||||
|
||||
impl DeviceWriter {
|
||||
pub fn new(writer: DeviceW,lock: Arc<Mutex<Device>>, in_ips: Vec<(Ipv4Addr, Ipv4Addr)>, ip: Ipv4Addr, packet_information: bool) -> Self {
|
||||
Self {
|
||||
writer,
|
||||
lock,
|
||||
in_ips,
|
||||
ip: Arc::new(AtomicCell::new(ip)),
|
||||
packet_information,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceWriter {
|
||||
pub fn write(packet_information: bool, writer: &Writer, packet: &[u8]) -> io::Result<()> {
|
||||
if packet_information {
|
||||
let mut buf = Vec::<u8>::with_capacity(4 + packet.len());
|
||||
buf.put_u16(0);
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
buf.put_u16(libc::PF_INET as u16);
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
buf.put_u16(libc::ETH_P_IP as u16);
|
||||
buf.extend_from_slice(packet);
|
||||
writer.write_all(&buf)
|
||||
} else {
|
||||
writer.write_all(packet)
|
||||
}
|
||||
}
|
||||
///tun网卡写入ipv4数据
|
||||
pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> {
|
||||
match &self.writer {
|
||||
DeviceW::Tun(writer) => {
|
||||
Self::write(self.packet_information, writer, buf)
|
||||
}
|
||||
DeviceW::Tap(_) => {
|
||||
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||
}
|
||||
}
|
||||
}
|
||||
/// tap网卡写入以太网帧
|
||||
pub fn write_ethernet_tap(&self, buf: &[u8]) -> io::Result<()> {
|
||||
match &self.writer {
|
||||
DeviceW::Tun(_) => {
|
||||
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||
}
|
||||
DeviceW::Tap((writer, _)) => {
|
||||
Self::write(self.packet_information, writer, buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
///写入ipv4数据,头部必须留14字节,给tap写入以太网帧头
|
||||
pub fn write_ipv4(&self, buf: &mut [u8]) -> io::Result<()> {
|
||||
match &self.writer {
|
||||
DeviceW::Tun(writer) => {
|
||||
Self::write(self.packet_information, writer, &buf[14..])
|
||||
}
|
||||
DeviceW::Tap((writer, mac)) => {
|
||||
let source_mac = [buf[14 + 12], buf[14 + 13], buf[14 + 14], buf[14 + 15], 123, 234];
|
||||
let mut ethernet_packet = EthernetPacket::unchecked(buf);
|
||||
ethernet_packet.set_source(&source_mac);
|
||||
ethernet_packet.set_destination(mac);
|
||||
ethernet_packet.set_protocol(ethernet::protocol::Protocol::Ipv4);
|
||||
Self::write(self.packet_information, writer, ðernet_packet.buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn ip(&self) -> Ipv4Addr {
|
||||
self.ip.load()
|
||||
}
|
||||
pub fn close(&self) -> io::Result<()> {
|
||||
unsafe {
|
||||
match &self.writer {
|
||||
DeviceW::Tun(writer) => {
|
||||
libc::close(writer.as_raw_fd());
|
||||
}
|
||||
DeviceW::Tap((writer, _)) => {
|
||||
libc::close(writer.as_raw_fd());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn is_tun(&self) -> bool {
|
||||
self.writer.is_tun()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DeviceReader(Reader);
|
||||
|
||||
impl DeviceReader {
|
||||
pub fn new(device: Reader) -> Self {
|
||||
DeviceReader(device)
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceReader {
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
use std::{io, thread};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use libloading::Library;
|
||||
use parking_lot::Mutex;
|
||||
use packet::ethernet;
|
||||
use packet::ethernet::packet::EthernetPacket;
|
||||
use win_tun_tap::{IFace, TapDevice, TunDevice};
|
||||
use crate::tun_tap_device::DeviceType;
|
||||
|
||||
pub const TUN_INTERFACE_NAME: &str = "Switch-Tun-V1";
|
||||
pub const TUN_POOL_NAME: &str = "Switch-Tun-V1";
|
||||
pub const TAP_INTERFACE_NAME: &str = "Switch-Tap-V1";
|
||||
|
||||
pub enum Device {
|
||||
Tun(TunDevice),
|
||||
Tap((TapDevice, [u8; 6])),
|
||||
}
|
||||
|
||||
impl Device {
|
||||
pub fn is_tun(&self) -> bool {
|
||||
match self {
|
||||
Device::Tun(_) => {
|
||||
true
|
||||
}
|
||||
Device::Tap(_) => {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DeviceWriter {
|
||||
device: Arc<Device>,
|
||||
lock: Arc<Mutex<()>>,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
ip: Arc<AtomicCell<Ipv4Addr>>,
|
||||
}
|
||||
|
||||
impl DeviceWriter {
|
||||
pub fn new(device: Arc<Device>, in_ips: Vec<(Ipv4Addr, Ipv4Addr)>, ip: Ipv4Addr) -> Self {
|
||||
Self {
|
||||
device,
|
||||
lock: Arc::new(Default::default()),
|
||||
in_ips,
|
||||
ip: Arc::new(AtomicCell::new(ip)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceWriter {
|
||||
///tun网卡写入ipv4数据
|
||||
pub fn write_ipv4_tun(&self, buf: &[u8]) -> io::Result<()> {
|
||||
match self.device.as_ref() {
|
||||
Device::Tun(dev) => {
|
||||
let mut packet = dev.allocate_send_packet(buf.len() as u16)?;
|
||||
packet.bytes_mut().copy_from_slice(buf);
|
||||
dev.send_packet(packet);
|
||||
Ok(())
|
||||
}
|
||||
Device::Tap(_) => {
|
||||
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||
}
|
||||
}
|
||||
}
|
||||
/// tap网卡写入以太网帧
|
||||
pub fn write_ethernet_tap(&self, buf: &[u8]) -> io::Result<()> {
|
||||
match self.device.as_ref() {
|
||||
Device::Tun(_) => {
|
||||
Err(io::Error::from(io::ErrorKind::Unsupported))
|
||||
}
|
||||
Device::Tap((dev, _)) => {
|
||||
dev.write(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
///写入ipv4数据,头部必须留14字节,给tap写入以太网帧头
|
||||
pub fn write_ipv4(&self, buf: &mut [u8]) -> io::Result<()> {
|
||||
match self.device.as_ref() {
|
||||
Device::Tun(dev) => {
|
||||
let mut packet = dev.allocate_send_packet((buf.len() - 14) as u16)?;
|
||||
packet.bytes_mut().copy_from_slice(&buf[14..]);
|
||||
dev.send_packet(packet);
|
||||
}
|
||||
Device::Tap((dev, mac)) => {
|
||||
let source_mac = [buf[14 + 12], buf[14 + 13], buf[14 + 14], buf[14 + 15], 123, 234];
|
||||
let mut ethernet_packet = EthernetPacket::unchecked(buf);
|
||||
ethernet_packet.set_source(&source_mac);
|
||||
ethernet_packet.set_destination(mac);
|
||||
ethernet_packet.set_protocol(ethernet::protocol::Protocol::Ipv4);
|
||||
dev.write(ðernet_packet.buffer)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn change_ip(
|
||||
&self,
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
old_netmask: Ipv4Addr,
|
||||
old_gateway: Ipv4Addr,
|
||||
) -> io::Result<()> {
|
||||
let _guard = self.lock.lock();
|
||||
let dev: &dyn IFace = match self.device.as_ref() {
|
||||
Device::Tun(dev) => {
|
||||
dev as &dyn IFace
|
||||
}
|
||||
Device::Tap((dev, _)) => {
|
||||
dev as &dyn IFace
|
||||
}
|
||||
};
|
||||
if let Err(e) =
|
||||
dev.delete_route(dest(old_gateway, old_gateway), old_netmask, old_gateway)
|
||||
{
|
||||
log::warn!("{:?}", e);
|
||||
}
|
||||
dev.set_ip(address, netmask)?;
|
||||
self.ip.store(address);
|
||||
for (address, netmask) in &self.in_ips {
|
||||
dev.add_route(*address, *netmask, gateway, 1)?;
|
||||
}
|
||||
// 当前网段路由
|
||||
dev.add_route(address, netmask, gateway, 1)?;
|
||||
// 广播和组播路由
|
||||
dev.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||
dev.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)
|
||||
}
|
||||
pub fn ip(&self) -> Ipv4Addr {
|
||||
self.ip.load()
|
||||
}
|
||||
pub fn close(&self) -> io::Result<()> {
|
||||
match self.device.as_ref() {
|
||||
Device::Tun(dev) => {
|
||||
dev.shutdown()
|
||||
}
|
||||
Device::Tap((dev, _)) => {
|
||||
dev.shutdown()
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn is_tun(&self) -> bool {
|
||||
self.device.is_tun()
|
||||
}
|
||||
}
|
||||
|
||||
fn dest(ip: Ipv4Addr, mask: Ipv4Addr) -> Ipv4Addr {
|
||||
let ip = ip.octets();
|
||||
let mask = mask.octets();
|
||||
Ipv4Addr::from([
|
||||
ip[0] & mask[0],
|
||||
ip[1] & mask[1],
|
||||
ip[2] & mask[2],
|
||||
ip[3] & mask[3],
|
||||
])
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DeviceReader {
|
||||
device: Arc<Device>,
|
||||
}
|
||||
|
||||
impl DeviceReader {
|
||||
pub fn new(device: Arc<Device>) -> Self {
|
||||
Self {
|
||||
device,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceReader {
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
match self.device.as_ref() {
|
||||
Device::Tun(dev) => {
|
||||
let packet = dev.receive_blocking()?;
|
||||
let packet = packet.bytes();
|
||||
let len = packet.len();
|
||||
if len > buf.len() {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "data too long"));
|
||||
}
|
||||
buf[..len].copy_from_slice(packet);
|
||||
Ok(len)
|
||||
}
|
||||
Device::Tap((dev, _)) => {
|
||||
dev.read(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_tun(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
) -> io::Result<(DeviceWriter, DeviceReader)> {
|
||||
unsafe {
|
||||
println!("========TUN网卡配置========");
|
||||
match Library::new("wintun.dll") {
|
||||
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
|
||||
Ok(_) => {
|
||||
thread::sleep(Duration::from_millis(5));
|
||||
}
|
||||
Err(_) => {}
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("wintun.dll not found");
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("wintun.dll not found {:?}", e),
|
||||
));
|
||||
}
|
||||
}
|
||||
let tun_device = match TunDevice::create(
|
||||
Library::new("wintun.dll").unwrap(),
|
||||
TUN_POOL_NAME,
|
||||
TUN_INTERFACE_NAME,
|
||||
) {
|
||||
Ok(tun_device) => tun_device,
|
||||
Err(_) => {
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
match TunDevice::create(
|
||||
Library::new("wintun.dll").unwrap(),
|
||||
TUN_POOL_NAME,
|
||||
TUN_INTERFACE_NAME,
|
||||
) {
|
||||
Ok(tun_device) => tun_device,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("{:?}", e),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
println!("name:{:?}", tun_device.get_name()?);
|
||||
println!("version:{:?}", tun_device.version()?);
|
||||
tun_device.set_ip(address, netmask)?;
|
||||
tun_device.set_metric(1)?;
|
||||
tun_device.set_mtu(1420)?;
|
||||
// ip代理路由
|
||||
for (address, netmask) in &in_ips {
|
||||
tun_device.add_route(*address, *netmask, gateway, 1)?;
|
||||
}
|
||||
// 当前网段路由
|
||||
tun_device.add_route(address, netmask, gateway, 1)?;
|
||||
// 广播和组播路由
|
||||
tun_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||
tun_device.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)?;
|
||||
let device = Arc::new(Device::Tun(tun_device));
|
||||
println!("========TUN网卡配置========");
|
||||
Ok((
|
||||
DeviceWriter::new(device.clone(), in_ips, address),
|
||||
DeviceReader::new(device),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn delete_tun() {
|
||||
unsafe {
|
||||
match Library::new("wintun.dll") {
|
||||
Ok(lib) => match TunDevice::delete_for_name(lib, TUN_INTERFACE_NAME) {
|
||||
Ok(_) => {}
|
||||
Err(_) => {}
|
||||
},
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_tap(
|
||||
address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>,
|
||||
) -> io::Result<(DeviceWriter, DeviceReader)> {
|
||||
println!("========TAP网卡配置========");
|
||||
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
|
||||
Ok(tap_device) => tap_device,
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e);
|
||||
let tap_device = TapDevice::create()?;
|
||||
tap_device.set_name(TAP_INTERFACE_NAME)?;
|
||||
tap_device
|
||||
}
|
||||
};
|
||||
let mac = tap_device.get_mac()?;
|
||||
println!("name:{:?}", tap_device.get_name()?);
|
||||
println!("version:{:x?}", tap_device.get_version()?);
|
||||
println!("mac:{:x?}", mac);
|
||||
tap_device.set_ip(address, netmask)?;
|
||||
tap_device.set_metric(1)?;
|
||||
tap_device.set_mtu(1420)?;
|
||||
tap_device.set_status(true)?;
|
||||
tap_device.add_route(address, netmask, gateway, 1)?;
|
||||
for (address, netmask) in &in_ips {
|
||||
tap_device.add_route(*address, *netmask, gateway, 1)?;
|
||||
}
|
||||
// 广播和组播路由
|
||||
tap_device.add_route(Ipv4Addr::BROADCAST, Ipv4Addr::BROADCAST, gateway, 1)?;
|
||||
tap_device.add_route(Ipv4Addr::from([224, 0, 0, 0]), Ipv4Addr::from([240, 0, 0, 0]), gateway, 1)?;
|
||||
let tap = Arc::new(Device::Tap((tap_device, mac)));
|
||||
println!("========TAP网卡配置========");
|
||||
Ok((
|
||||
DeviceWriter::new(tap.clone(), in_ips, address),
|
||||
DeviceReader::new(tap)
|
||||
))
|
||||
}
|
||||
|
||||
fn delete_tap() {
|
||||
let tap_device = match TapDevice::open(TAP_INTERFACE_NAME) {
|
||||
Ok(tap_device) => tap_device,
|
||||
Err(_) => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let _ = tap_device.delete();
|
||||
}
|
||||
|
||||
pub fn create_device(device_type: DeviceType, address: Ipv4Addr,
|
||||
netmask: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
in_ips: Vec<(Ipv4Addr, Ipv4Addr)>, ) -> io::Result<(DeviceWriter, DeviceReader)> {
|
||||
match device_type {
|
||||
DeviceType::Tun => {
|
||||
create_tun(address, netmask, gateway, in_ips)
|
||||
}
|
||||
DeviceType::Tap => {
|
||||
create_tap(address, netmask, gateway, in_ips)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_device(device_type: DeviceType) {
|
||||
match device_type {
|
||||
DeviceType::Tun => {
|
||||
delete_tun()
|
||||
}
|
||||
DeviceType::Tap => {
|
||||
delete_tap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user