125 lines
4.3 KiB
Rust
125 lines
4.3 KiB
Rust
use std::io;
|
|
use std::net::Ipv4Addr;
|
|
use crate::tun_tap_device::{DeviceReader, DeviceType, DeviceWriter, DriverInfo};
|
|
use tun::Device;
|
|
use parking_lot::Mutex;
|
|
use std::process::Command;
|
|
use std::sync::Arc;
|
|
use crate::tun_tap_device::linux_mac::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)
|
|
// .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)>,
|
|
mtu: u16,
|
|
) -> io::Result<(DeviceWriter, DeviceReader,DriverInfo)> {
|
|
let mut config = tun::Configuration::default();
|
|
|
|
config
|
|
.destination(gateway)
|
|
.address(address)
|
|
.netmask(netmask)
|
|
.mtu(mtu.into())
|
|
// .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();
|
|
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))
|
|
}
|
|
};
|
|
let driver_info = DriverInfo {
|
|
device_type,
|
|
name:name.to_string(),
|
|
version:String::new(),
|
|
mac: None,
|
|
};
|
|
Ok((
|
|
DeviceWriter::new(device_w, Arc::new(Mutex::new(dev)), in_ips, address, packet_information),
|
|
DeviceReader::new(reader),
|
|
driver_info,
|
|
))
|
|
}
|
|
|
|
pub fn delete_device(_device_type: DeviceType) {} |