network: begin work on ICMP

This commit is contained in:
Alex Zenla
2024-02-10 15:18:12 +00:00
parent a7f4e0a549
commit 4f0e505e2b
6 changed files with 234 additions and 15 deletions

View File

@ -1,6 +1,8 @@
use anyhow::Result;
use async_trait::async_trait;
use etherparse::Ethernet2Slice;
use etherparse::Icmpv4Header;
use etherparse::Icmpv4Type;
use etherparse::IpNumber;
use etherparse::IpPayloadSlice;
use etherparse::Ipv4Slice;
@ -26,6 +28,7 @@ use tokio::sync::mpsc::Sender;
pub enum NatKeyProtocol {
Tcp,
Udp,
Icmp,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
@ -164,6 +167,11 @@ impl NatRouter {
.await?;
}
IpNumber::ICMP => {
self.process_icmpv4(data, ether, source_addr, dest_addr, ipv4.payload())
.await?;
}
_ => {}
}
@ -239,6 +247,31 @@ impl NatRouter {
Ok(())
}
pub async fn process_icmpv4<'a>(
&mut self,
data: &'a [u8],
ether: &Ethernet2Slice<'a>,
source_addr: IpAddress,
dest_addr: IpAddress,
payload: &IpPayloadSlice<'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_nat(&mut self, data: &[u8], key: NatKey) -> Result<()> {
for cidr in &self.local_cidrs {
if cidr.contains_addr(&key.external_ip.addr) {