2024-02-06 10:28:39 +00:00
|
|
|
use std::sync::{Arc, Mutex};
|
2024-02-05 19:10:02 +00:00
|
|
|
use std::time::Duration;
|
2024-02-05 12:45:45 +00:00
|
|
|
|
|
|
|
use anyhow::{anyhow, Result};
|
2024-02-05 19:10:02 +00:00
|
|
|
use futures::TryStreamExt;
|
2024-02-06 14:35:55 +00:00
|
|
|
use ipstack::stream::IpStackStream;
|
|
|
|
use log::{debug, error, info, warn};
|
2024-02-05 19:10:02 +00:00
|
|
|
use netlink_packet_route::link::LinkAttribute;
|
2024-02-06 14:35:55 +00:00
|
|
|
use raw_socket::{AsyncRawSocket, RawSocket};
|
|
|
|
use tokio::net::TcpStream;
|
2024-02-05 19:10:02 +00:00
|
|
|
use tokio::time::sleep;
|
2024-02-06 14:35:55 +00:00
|
|
|
use udp_stream::UdpStream;
|
|
|
|
|
|
|
|
mod raw_socket;
|
2024-02-05 12:45:45 +00:00
|
|
|
|
2024-02-05 19:10:02 +00:00
|
|
|
pub struct NetworkBackend {
|
|
|
|
pub interface: String,
|
2024-02-05 12:45:45 +00:00
|
|
|
}
|
2024-02-05 19:10:02 +00:00
|
|
|
pub struct NetworkService {
|
|
|
|
pub network: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl NetworkService {
|
|
|
|
pub fn new(network: String) -> Result<NetworkService> {
|
|
|
|
Ok(NetworkService { network })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl NetworkBackend {
|
2024-02-06 14:35:55 +00:00
|
|
|
pub fn new(iface: &str) -> Result<NetworkBackend> {
|
2024-02-05 19:10:02 +00:00
|
|
|
Ok(NetworkBackend {
|
|
|
|
interface: iface.to_string(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn init(&mut self) -> Result<()> {
|
|
|
|
let (connection, handle, _) = rtnetlink::new_connection()?;
|
|
|
|
tokio::spawn(connection);
|
|
|
|
|
|
|
|
let mut links = handle
|
|
|
|
.link()
|
|
|
|
.get()
|
|
|
|
.match_name(self.interface.clone())
|
|
|
|
.execute();
|
|
|
|
let link = links.try_next().await?;
|
|
|
|
if link.is_none() {
|
|
|
|
return Err(anyhow!(
|
|
|
|
"unable to find network interface named {}",
|
|
|
|
self.interface
|
|
|
|
));
|
|
|
|
}
|
|
|
|
let link = link.unwrap();
|
|
|
|
handle.link().set(link.header.index).up().execute().await?;
|
2024-02-06 06:19:36 +00:00
|
|
|
tokio::time::sleep(Duration::from_secs(3)).await;
|
2024-02-05 19:10:02 +00:00
|
|
|
Ok(())
|
2024-02-05 12:45:45 +00:00
|
|
|
}
|
|
|
|
|
2024-02-06 14:35:55 +00:00
|
|
|
pub async fn run(&mut self) -> Result<()> {
|
|
|
|
let mut config = ipstack::IpStackConfig::default();
|
|
|
|
config.mtu(1500);
|
|
|
|
config.tcp_timeout(std::time::Duration::from_secs(600)); // 10 minutes
|
|
|
|
config.udp_timeout(std::time::Duration::from_secs(10)); // 10 seconds
|
2024-02-06 06:19:36 +00:00
|
|
|
|
2024-02-06 14:35:55 +00:00
|
|
|
let mut socket = RawSocket::new(&self.interface)?;
|
|
|
|
socket.bind_interface()?;
|
|
|
|
let socket = AsyncRawSocket::new(socket)?;
|
|
|
|
let mut stack = ipstack::IpStack::new(config, socket);
|
2024-02-06 06:19:36 +00:00
|
|
|
|
2024-02-06 14:35:55 +00:00
|
|
|
while let Ok(stream) = stack.accept().await {
|
|
|
|
self.process_stream(stream).await?
|
|
|
|
}
|
|
|
|
Ok(())
|
2024-02-06 06:19:36 +00:00
|
|
|
}
|
|
|
|
|
2024-02-06 14:35:55 +00:00
|
|
|
async fn process_stream(&mut self, stream: IpStackStream) -> Result<()> {
|
|
|
|
match stream {
|
|
|
|
IpStackStream::Tcp(mut tcp) => {
|
|
|
|
debug!("tcp: {}", tcp.peer_addr());
|
|
|
|
tokio::spawn(async move {
|
|
|
|
if let Ok(mut stream) = TcpStream::connect(tcp.peer_addr()).await {
|
|
|
|
let _ = tokio::io::copy_bidirectional(&mut stream, &mut tcp).await;
|
|
|
|
} else {
|
|
|
|
warn!("failed to connect to tcp address: {}", tcp.peer_addr());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2024-02-05 12:45:45 +00:00
|
|
|
|
2024-02-06 14:35:55 +00:00
|
|
|
IpStackStream::Udp(mut udp) => {
|
|
|
|
debug!("udp: {}", udp.peer_addr());
|
|
|
|
tokio::spawn(async move {
|
|
|
|
if let Ok(mut stream) = UdpStream::connect(udp.peer_addr()).await {
|
|
|
|
let _ = tokio::io::copy_bidirectional(&mut stream, &mut udp).await;
|
|
|
|
} else {
|
|
|
|
warn!("failed to connect to udp address: {}", udp.peer_addr());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
IpStackStream::UnknownTransport(u) => {
|
|
|
|
debug!("unknown transport: {}", u.dst_addr());
|
|
|
|
}
|
|
|
|
|
|
|
|
IpStackStream::UnknownNetwork(packet) => {
|
|
|
|
debug!("unknown network: {:?}", packet);
|
|
|
|
}
|
2024-02-05 12:45:45 +00:00
|
|
|
}
|
2024-02-06 14:35:55 +00:00
|
|
|
Ok(())
|
2024-02-05 12:45:45 +00:00
|
|
|
}
|
|
|
|
}
|
2024-02-05 19:10:02 +00:00
|
|
|
|
|
|
|
impl NetworkService {
|
|
|
|
pub async fn watch(&mut self) -> Result<()> {
|
2024-02-06 10:28:39 +00:00
|
|
|
let spawned: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(Vec::new()));
|
2024-02-05 19:10:02 +00:00
|
|
|
let (connection, handle, _) = rtnetlink::new_connection()?;
|
|
|
|
tokio::spawn(connection);
|
|
|
|
loop {
|
|
|
|
let mut stream = handle.link().get().execute();
|
|
|
|
while let Some(message) = stream.try_next().await? {
|
|
|
|
let mut name: Option<String> = None;
|
|
|
|
for attribute in &message.attributes {
|
|
|
|
if let LinkAttribute::IfName(if_name) = attribute {
|
|
|
|
name = Some(if_name.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if name.is_none() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let name = name.unwrap();
|
|
|
|
if !name.starts_with("vif") {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-02-06 10:28:39 +00:00
|
|
|
if let Ok(spawns) = spawned.lock() {
|
|
|
|
if spawns.contains(&name) {
|
|
|
|
continue;
|
|
|
|
}
|
2024-02-05 19:10:02 +00:00
|
|
|
}
|
|
|
|
|
2024-02-06 10:28:39 +00:00
|
|
|
if let Err(error) = self.add_network_backend(&name, spawned.clone()).await {
|
2024-02-05 19:10:02 +00:00
|
|
|
warn!(
|
|
|
|
"failed to initialize network backend for interface {}: {}",
|
|
|
|
name, error
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-02-06 10:28:39 +00:00
|
|
|
if let Ok(mut spawns) = spawned.lock() {
|
|
|
|
spawns.push(name.clone());
|
|
|
|
}
|
2024-02-05 19:10:02 +00:00
|
|
|
}
|
|
|
|
|
2024-02-06 06:19:36 +00:00
|
|
|
sleep(Duration::from_secs(2)).await;
|
2024-02-05 19:10:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-06 10:28:39 +00:00
|
|
|
async fn add_network_backend(
|
|
|
|
&mut self,
|
|
|
|
interface: &str,
|
|
|
|
spawned: Arc<Mutex<Vec<String>>>,
|
|
|
|
) -> Result<()> {
|
2024-02-05 19:10:02 +00:00
|
|
|
let interface = interface.to_string();
|
2024-02-06 14:35:55 +00:00
|
|
|
let mut network = NetworkBackend::new(&interface)?;
|
2024-02-06 06:19:36 +00:00
|
|
|
info!("initializing network backend for interface {}", interface);
|
2024-02-05 19:10:02 +00:00
|
|
|
network.init().await?;
|
2024-02-06 06:19:36 +00:00
|
|
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
2024-02-05 19:10:02 +00:00
|
|
|
info!("spawning network backend for interface {}", interface);
|
2024-02-06 14:35:55 +00:00
|
|
|
tokio::spawn(async move {
|
|
|
|
if let Err(error) = network.run().await {
|
2024-02-05 19:10:02 +00:00
|
|
|
error!(
|
2024-02-06 14:35:55 +00:00
|
|
|
"network backend for interface {} has been stopped: {}",
|
2024-02-05 19:10:02 +00:00
|
|
|
interface, error
|
|
|
|
);
|
|
|
|
}
|
2024-02-06 10:28:39 +00:00
|
|
|
|
|
|
|
if let Ok(mut spawns) = spawned.lock() {
|
|
|
|
if let Some(position) = spawns.iter().position(|x| *x == interface) {
|
|
|
|
spawns.remove(position);
|
|
|
|
}
|
|
|
|
}
|
2024-02-05 19:10:02 +00:00
|
|
|
});
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|