Files
vnt/switch/src/tun_tap_device/linux.rs
T

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) {}