Add UDP Packet Filtering to netstack
This commit is contained in:
committed by
Jeremy Soller
parent
72d842ffd8
commit
af908029f8
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user