use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use crate::address::ip::ipnet::IpNet;
use rama_core::extensions::Extensions;
#[derive(Debug, Clone)]
pub struct PrivateIpNetMatcher {
matchers: [IpNet; 11],
optional: bool,
}
impl PrivateIpNetMatcher {
#[must_use]
pub const fn new() -> Self {
Self::inner_new(false)
}
#[must_use]
pub const fn optional() -> Self {
Self::inner_new(true)
}
const fn inner_new(optional: bool) -> Self {
const MATCHERS: [IpNet; 11] = [
IpNet::new_assert(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 8), IpNet::new_assert(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 0)), 8), IpNet::new_assert(IpAddr::V4(Ipv4Addr::new(100, 64, 0, 0)), 10), IpNet::new_assert(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 0)), 8), IpNet::new_assert(IpAddr::V4(Ipv4Addr::new(169, 254, 0, 0)), 16), IpNet::new_assert(IpAddr::V4(Ipv4Addr::new(172, 16, 0, 0)), 12), IpNet::new_assert(IpAddr::V4(Ipv4Addr::new(192, 168, 0, 0)), 16), IpNet::new_assert(IpAddr::V6(Ipv6Addr::new(0xfc00, 0, 0, 0, 0, 0, 0, 0)), 7), IpNet::new_assert(IpAddr::V6(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0)), 10), IpNet::new_assert(IpAddr::V6(Ipv6Addr::LOCALHOST), 128), IpNet::new_assert(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 128), ];
Self {
matchers: MATCHERS,
optional,
}
}
}
impl Default for PrivateIpNetMatcher {
#[inline(always)]
fn default() -> Self {
Self::new()
}
}
impl<Socket> rama_core::matcher::Matcher<Socket> for PrivateIpNetMatcher
where
Socket: crate::stream::Socket,
{
fn matches(&self, _ext: Option<&Extensions>, stream: &Socket) -> bool {
stream
.peer_addr()
.map(|addr| {
let peer_ip = IpNet::from(addr.ip_addr);
self.matchers.iter().any(|ip_net| ip_net.contains(&peer_ip))
})
.unwrap_or(self.optional)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::address::SocketAddress;
use rama_core::matcher::Matcher;
#[test]
fn test_local_ip_net_matcher_socket_trait() {
let matcher = PrivateIpNetMatcher::new();
struct FakeSocket {
local_addr: Option<SocketAddress>,
peer_addr: Option<SocketAddress>,
}
impl crate::stream::Socket for FakeSocket {
fn local_addr(&self) -> std::io::Result<SocketAddress> {
match &self.local_addr {
Some(addr) => Ok(*addr),
None => Err(std::io::Error::from(std::io::ErrorKind::AddrNotAvailable)),
}
}
fn peer_addr(&self) -> std::io::Result<SocketAddress> {
match &self.peer_addr {
Some(addr) => Ok(*addr),
None => Err(std::io::Error::from(std::io::ErrorKind::AddrNotAvailable)),
}
}
}
let mut socket = FakeSocket {
local_addr: None,
peer_addr: None,
};
assert!(!matcher.matches(None, &socket));
socket.peer_addr = Some(([1, 1, 1, 1], 8080).into());
assert!(!matcher.matches(None, &socket));
socket.peer_addr = Some(([1, 1, 1, 1, 1, 1, 1, 1], 8080).into());
assert!(!matcher.matches(None, &socket));
socket.peer_addr = Some(([192, 168, 0, 0], 8080).into());
assert!(matcher.matches(None, &socket));
socket.peer_addr = Some(([127, 3, 2, 1], 8080).into());
assert!(matcher.matches(None, &socket));
socket.peer_addr = Some(([0, 0, 0, 0, 0, 0, 0, 1], 8080).into());
assert!(matcher.matches(None, &socket));
let matcher = PrivateIpNetMatcher::optional();
socket.peer_addr = None;
assert!(matcher.matches(None, &socket));
}
}