cuprate_helper/
net.rs

1//! Networking utilities.
2//!
3//! `#[no_std]` compatible.
4
5use core::net::IpAddr;
6
7/// Returns [`true`] if the address is a local address
8/// (non-reachable via the broader internet).
9///
10/// # FIXME
11/// This is only mostly accurate.
12///
13/// It should be replaced when `std` stabilizes things:
14/// <https://github.com/rust-lang/rust/issues/27709>
15pub const fn ip_is_local(ip: IpAddr) -> bool {
16    match ip {
17        IpAddr::V4(ip) => ip.is_loopback() || ip.is_private(),
18        IpAddr::V6(ip) => ip.is_loopback() || ip.is_unique_local() || ip.is_unicast_link_local(),
19    }
20}
21
22#[cfg(test)]
23mod test {
24    use core::net::{Ipv4Addr, Ipv6Addr};
25
26    use super::*;
27
28    #[test]
29    fn ip_local() {
30        for ipv4 in [
31            Ipv4Addr::LOCALHOST,
32            Ipv4Addr::new(10, 0, 0, 0),
33            Ipv4Addr::new(10, 0, 255, 255),
34            Ipv4Addr::new(172, 16, 0, 0),
35            Ipv4Addr::new(172, 16, 255, 255),
36            Ipv4Addr::new(192, 168, 0, 0),
37            Ipv4Addr::new(192, 168, 255, 255),
38        ] {
39            assert!(ip_is_local(ipv4.into()));
40        }
41
42        for ipv4 in [
43            Ipv4Addr::UNSPECIFIED,
44            Ipv4Addr::new(1, 1, 1, 1),
45            Ipv4Addr::new(176, 9, 0, 187),
46            Ipv4Addr::new(88, 198, 163, 90),
47            Ipv4Addr::new(66, 85, 74, 134),
48            Ipv4Addr::new(51, 79, 173, 165),
49            Ipv4Addr::new(192, 99, 8, 110),
50            Ipv4Addr::new(37, 187, 74, 171),
51            Ipv4Addr::new(77, 172, 183, 193),
52        ] {
53            assert!(!ip_is_local(ipv4.into()));
54        }
55
56        for ipv6 in [
57            Ipv6Addr::LOCALHOST,
58            Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0),
59            Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0),
60            Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0),
61            Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0),
62        ] {
63            assert!(ip_is_local(ipv6.into()));
64        }
65
66        for ipv6 in [
67            Ipv6Addr::UNSPECIFIED,
68            Ipv6Addr::new(1, 1, 1, 1, 1, 1, 1, 1),
69            Ipv6Addr::new(
70                0x1020, 0x3040, 0x5060, 0x7080, 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
71            ),
72        ] {
73            assert!(!ip_is_local(ipv6.into()));
74        }
75    }
76}