diff --git a/network/src/backend.rs b/network/src/backend.rs
index e1239bc..f849d96 100644
--- a/network/src/backend.rs
+++ b/network/src/backend.rs
@@ -1,9 +1,11 @@
use crate::chandev::ChannelDevice;
use crate::nat::NatRouter;
+use crate::pkt::RecvPacket;
use crate::proxynat::ProxyNatHandlerFactory;
use crate::raw_socket::{AsyncRawSocket, RawSocketProtocol};
use advmac::MacAddr6;
use anyhow::{anyhow, Result};
+use etherparse::SlicedPacket;
use futures::TryStreamExt;
use log::debug;
use smoltcp::iface::{Config, Interface, SocketSet};
@@ -41,30 +43,32 @@ struct NetworkStack<'a> {
}
impl NetworkStack<'_> {
- async fn poll(&mut self, receive_buffer: &mut [u8]) -> Result<()> {
+ async fn poll(&mut self, buffer: &mut [u8]) -> Result<()> {
let what = select! {
+ x = self.kdev.read(buffer) => NetworkStackSelect::Receive(&buffer[0..x?]),
x = self.tx.recv() => NetworkStackSelect::Send(x),
- x = self.kdev.read(receive_buffer) => NetworkStackSelect::Receive(&receive_buffer[0..x?]),
_ = self.router.process_reclaim() => NetworkStackSelect::Reclaim,
};
match what {
+ NetworkStackSelect::Receive(packet) => {
+ let slice = SlicedPacket::from_ethernet(packet)?;
+ let packet = RecvPacket::new(packet, &slice)?;
+ if let Err(error) = self.router.process(&packet).await {
+ debug!("router failed to process packet: {}", error);
+ }
+
+ self.udev.rx = Some(packet.raw.to_vec());
+ self.interface
+ .poll(Instant::now(), &mut self.udev, &mut self.sockets);
+ }
+
NetworkStackSelect::Send(packet) => {
if let Some(packet) = packet {
self.kdev.write_all(&packet).await?
}
}
- NetworkStackSelect::Receive(packet) => {
- if let Err(error) = self.router.process(packet).await {
- debug!("router failed to process packet: {}", error);
- }
-
- self.udev.rx = Some(packet.to_vec());
- self.interface
- .poll(Instant::now(), &mut self.udev, &mut self.sockets);
- }
-
NetworkStackSelect::Reclaim => {}
}
diff --git a/network/src/lib.rs b/network/src/lib.rs
index e30caa3..c346758 100644
--- a/network/src/lib.rs
+++ b/network/src/lib.rs
@@ -13,6 +13,7 @@ pub mod backend;
pub mod chandev;
pub mod icmp;
pub mod nat;
+pub mod pkt;
pub mod proxynat;
pub mod raw_socket;
diff --git a/network/src/nat.rs b/network/src/nat.rs
index fb39ca4..ebc8aa3 100644
--- a/network/src/nat.rs
+++ b/network/src/nat.rs
@@ -1,17 +1,15 @@
+use crate::pkt::RecvPacket;
+use crate::pkt::RecvPacketIp;
use anyhow::Result;
use async_trait::async_trait;
-use etherparse::Ethernet2Slice;
use etherparse::Icmpv4Header;
use etherparse::Icmpv4Type;
use etherparse::Icmpv6Header;
use etherparse::Icmpv6Type;
use etherparse::IpNumber;
-use etherparse::LaxIpPayloadSlice;
-use etherparse::LaxIpv4Slice;
-use etherparse::LaxIpv6Slice;
-use etherparse::LaxNetSlice;
-use etherparse::LaxSlicedPacket;
-use etherparse::LinkSlice;
+use etherparse::IpPayloadSlice;
+use etherparse::Ipv4Slice;
+use etherparse::Ipv6Slice;
use etherparse::TcpHeaderSlice;
use etherparse::UdpHeaderSlice;
use log::{debug, trace};
@@ -145,13 +143,8 @@ impl NatRouter {
})
}
- pub async fn process(&mut self, data: &[u8]) -> Result<()> {
- let packet = LaxSlicedPacket::from_ethernet(data)?;
- let Some(ref link) = packet.link else {
- return Ok(());
- };
-
- let LinkSlice::Ethernet2(ref ether) = link else {
+ pub async fn process<'a>(&mut self, packet: &RecvPacket<'a>) -> Result<()> {
+ let Some(ether) = packet.ether else {
return Ok(());
};
@@ -165,173 +158,16 @@ impl NatRouter {
return Ok(());
}
- let Some(ref net) = packet.net else {
+ let key = match packet.ip {
+ Some(RecvPacketIp::Ipv4(ipv4)) => self.extract_key_ipv4(packet, ipv4)?,
+ Some(RecvPacketIp::Ipv6(ipv6)) => self.extract_key_ipv6(packet, ipv6)?,
+ _ => None,
+ };
+
+ let Some(key) = key else {
return Ok(());
};
- match net {
- LaxNetSlice::Ipv4(ipv4) => self.process_ipv4(data, ether, ipv4).await?,
- LaxNetSlice::Ipv6(ipv6) => self.process_ipv6(data, ether, ipv6).await?,
- }
-
- Ok(())
- }
-
- pub async fn process_ipv4<'a>(
- &mut self,
- data: &[u8],
- ether: &Ethernet2Slice<'a>,
- ipv4: &LaxIpv4Slice<'a>,
- ) -> Result<()> {
- let source_addr = IpAddress::Ipv4(ipv4.header().source_addr().into());
- let dest_addr = IpAddress::Ipv4(ipv4.header().destination_addr().into());
- match ipv4.header().protocol() {
- IpNumber::TCP => {
- self.process_tcp(data, ether, source_addr, dest_addr, ipv4.payload())
- .await?;
- }
-
- IpNumber::UDP => {
- self.process_udp(data, ether, source_addr, dest_addr, ipv4.payload())
- .await?;
- }
-
- IpNumber::ICMP => {
- self.process_icmpv4(data, ether, source_addr, dest_addr, ipv4.payload())
- .await?;
- }
-
- _ => {}
- }
-
- Ok(())
- }
-
- pub async fn process_ipv6<'a>(
- &mut self,
- data: &[u8],
- ether: &Ethernet2Slice<'a>,
- ipv6: &LaxIpv6Slice<'a>,
- ) -> Result<()> {
- let source_addr = IpAddress::Ipv6(ipv6.header().source_addr().into());
- let dest_addr = IpAddress::Ipv6(ipv6.header().destination_addr().into());
- match ipv6.header().next_header() {
- IpNumber::TCP => {
- self.process_tcp(data, ether, source_addr, dest_addr, ipv6.payload())
- .await?;
- }
-
- IpNumber::UDP => {
- self.process_udp(data, ether, source_addr, dest_addr, ipv6.payload())
- .await?;
- }
-
- IpNumber::IPV6_ICMP => {
- self.process_icmpv6(data, ether, source_addr, dest_addr, ipv6.payload())
- .await?;
- }
-
- _ => {}
- }
-
- Ok(())
- }
-
- pub async fn process_tcp<'a>(
- &mut self,
- data: &'a [u8],
- ether: &Ethernet2Slice<'a>,
- source_addr: IpAddress,
- dest_addr: IpAddress,
- payload: &LaxIpPayloadSlice<'a>,
- ) -> Result<()> {
- let header = TcpHeaderSlice::from_slice(payload.payload)?;
- let source = IpEndpoint::new(source_addr, header.source_port());
- let dest = IpEndpoint::new(dest_addr, header.destination_port());
- let key = NatKey {
- protocol: NatKeyProtocol::Tcp,
- client_mac: EthernetAddress(ether.source()),
- local_mac: EthernetAddress(ether.destination()),
- client_ip: source,
- external_ip: dest,
- };
- self.process_nat(data, key).await?;
- Ok(())
- }
-
- pub async fn process_udp<'a>(
- &mut self,
- data: &'a [u8],
- ether: &Ethernet2Slice<'a>,
- source_addr: IpAddress,
- dest_addr: IpAddress,
- payload: &LaxIpPayloadSlice<'a>,
- ) -> Result<()> {
- let header = UdpHeaderSlice::from_slice(payload.payload)?;
- let source = IpEndpoint::new(source_addr, header.source_port());
- let dest = IpEndpoint::new(dest_addr, header.destination_port());
- let key = NatKey {
- protocol: NatKeyProtocol::Udp,
- client_mac: EthernetAddress(ether.source()),
- local_mac: EthernetAddress(ether.destination()),
- client_ip: source,
- external_ip: dest,
- };
- self.process_nat(data, key).await?;
- Ok(())
- }
-
- pub async fn process_icmpv4<'a>(
- &mut self,
- data: &'a [u8],
- ether: &Ethernet2Slice<'a>,
- source_addr: IpAddress,
- dest_addr: IpAddress,
- payload: &LaxIpPayloadSlice<'a>,
- ) -> Result<()> {
- let (header, _) = Icmpv4Header::from_slice(payload.payload)?;
- let Icmpv4Type::EchoRequest(_) = header.icmp_type else {
- return Ok(());
- };
- let source = IpEndpoint::new(source_addr, 0);
- let dest = IpEndpoint::new(dest_addr, 0);
- let key = NatKey {
- protocol: NatKeyProtocol::Icmp,
- client_mac: EthernetAddress(ether.source()),
- local_mac: EthernetAddress(ether.destination()),
- client_ip: source,
- external_ip: dest,
- };
- self.process_nat(data, key).await?;
- Ok(())
- }
-
- pub async fn process_icmpv6<'a>(
- &mut self,
- data: &'a [u8],
- ether: &Ethernet2Slice<'a>,
- source_addr: IpAddress,
- dest_addr: IpAddress,
- payload: &LaxIpPayloadSlice<'a>,
- ) -> Result<()> {
- let (header, _) = Icmpv6Header::from_slice(payload.payload)?;
- let Icmpv6Type::EchoRequest(_) = header.icmp_type else {
- return Ok(());
- };
- let source = IpEndpoint::new(source_addr, 0);
- let dest = IpEndpoint::new(dest_addr, 0);
- let key = NatKey {
- protocol: NatKeyProtocol::Icmp,
- client_mac: EthernetAddress(ether.source()),
- local_mac: EthernetAddress(ether.destination()),
- client_ip: source,
- external_ip: dest,
- };
- self.process_nat(data, key).await?;
- Ok(())
- }
-
- pub async fn process_nat(&mut self, data: &[u8], key: NatKey) -> Result<()> {
for cidr in &self.local_cidrs {
if cidr.contains_addr(&key.external_ip.addr) {
return Ok(());
@@ -357,10 +193,152 @@ impl NatRouter {
};
if let Some(handler) = handler {
- if !handler.receive(data).await? {
+ if !handler.receive(packet.raw).await? {
self.reclaim_sender.try_send(key)?;
}
}
Ok(())
}
+
+ pub fn extract_key_ipv4<'a>(
+ &mut self,
+ packet: &RecvPacket<'a>,
+ ipv4: &Ipv4Slice<'a>,
+ ) -> Result