Add UDP Packet Filtering to netstack

This commit is contained in:
Akshit Gaur
2026-01-19 17:06:45 +00:00
committed by Jeremy Soller
parent 72d842ffd8
commit af908029f8
5 changed files with 53 additions and 14 deletions
+3 -3
View File
@@ -40,8 +40,8 @@ impl<'a> SchemeSocket for IcmpSocket<'a> {
self.can_send()
}
fn can_recv(&self) -> bool {
self.can_recv()
fn can_recv(&mut self, _data: &Self::DataT) -> bool {
smoltcp::socket::icmp::Socket::can_recv(self)
}
fn may_recv(&self) -> bool {
@@ -212,7 +212,7 @@ impl<'a> SchemeSocket for IcmpSocket<'a> {
if !file.read_enabled {
return Ok(0);
}
while self.can_recv() {
while self.can_recv(&file.data) {
let (payload, _) = self.recv().expect("Can't recv icmp packet");
let icmp_packet = Icmpv4Packet::new_unchecked(&payload);
//TODO: replace default with actual caps
+3 -3
View File
@@ -27,8 +27,8 @@ impl<'a> SchemeSocket for RawSocket<'a> {
self.can_send()
}
fn can_recv(&self) -> bool {
self.can_recv()
fn can_recv(&mut self, _data: &Self::DataT) -> bool {
smoltcp::socket::raw::Socket::can_recv(self)
}
fn may_recv(&self) -> bool {
@@ -117,7 +117,7 @@ impl<'a> SchemeSocket for RawSocket<'a> {
) -> SyscallResult<usize> {
if !file.read_enabled {
Ok(0)
} else if self.can_recv() {
} else if self.can_recv(&file.data) {
let length = self.recv_slice(buf).expect("Can't receive slice");
Ok(length)
} else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
+4 -3
View File
@@ -133,13 +133,14 @@ where
events,
ref mut read_notified,
ref mut write_notified,
ref data,
..
}) = self
{
let socket = socket_set.get::<SocketT>(socket_handle);
let socket = socket_set.get_mut::<SocketT>(socket_handle);
if events & syscall::EVENT_READ.bits() == syscall::EVENT_READ.bits()
&& (socket.can_recv() || !socket.may_recv())
&& (socket.can_recv(data) || !socket.may_recv())
{
if !*read_notified {
*read_notified = true;
@@ -180,7 +181,7 @@ where
fn new_scheme_data() -> Self::SchemeDataT;
fn can_send(&self) -> bool;
fn can_recv(&self) -> bool;
fn can_recv(&mut self, data: &Self::DataT) -> bool;
fn may_recv(&self) -> bool;
fn hop_limit(&self) -> u8;
+3 -3
View File
@@ -25,8 +25,8 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
self.can_send()
}
fn can_recv(&self) -> bool {
self.can_recv()
fn can_recv(&mut self, _data: &Self::DataT) -> bool {
smoltcp::socket::tcp::Socket::can_recv(self)
}
fn may_recv(&self) -> bool {
@@ -176,7 +176,7 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
Ok(0)
} else if !self.is_active() {
Err(SyscallError::new(syscall::ENOTCONN))
} else if self.can_recv() {
} else if self.can_recv(&file.data) {
let length = self.recv_slice(buf).expect("Can't receive slice");
Ok(length)
} else if !self.may_recv() {
+40 -2
View File
@@ -28,8 +28,46 @@ impl<'a> SchemeSocket for UdpSocket<'a> {
self.can_send()
}
fn can_recv(&self) -> bool {
self.can_recv()
fn can_recv(&mut self, data: &IpListenEndpoint) -> bool {
loop {
// If buffer is empty, we definitely can't recv
if !UdpSocket::can_recv(self) {
return false;
}
// If we are not connected to a specific remote, any packet is valid
if !data.is_specified() {
return true;
}
// If we are connected, peek at the packet.
match self.peek() {
Ok((_, meta)) => {
let source = meta.endpoint;
let connected_addr = data.addr.unwrap(); // Safe because is_specified() checked it
// Allow Broadcast special case (DHCP)
let is_broadcast = match connected_addr {
smoltcp::wire::IpAddress::Ipv4(ip) => {
ip == smoltcp::wire::Ipv4Address::BROADCAST
}
_ => false,
};
if !is_broadcast && !connected_addr.is_unspecified() {
if source.addr != connected_addr || source.port != data.port {
// Bad packet detetced
// Remove it from the buffer immediately so poll() doesn't trigger
let _ = self.recv();
continue; // Loop again to check the next packet
}
}
// Packet is valid
return true;
}
Err(_) => return false,
}
}
}
fn may_recv(&self) -> bool {