use std::net::{Ipv4Addr, Ipv6Addr};
pub fn is_private_ipv4(ip: &Ipv4Addr) -> bool {
ip.is_loopback()
|| ip.is_private()
|| ip.is_link_local()
|| ip.is_broadcast()
|| ip.is_unspecified()
|| (ip.octets()[0] == 100 && (ip.octets()[1] & 0xC0) == 64)
}
pub fn is_private_ipv6(ip: &Ipv6Addr) -> bool {
ip.is_loopback() || ip.is_unspecified() || {
let segments = ip.segments();
(segments[0] & 0xFE00) == 0xFC00
|| (segments[0] & 0xFFC0) == 0xFE80
|| match ip.to_ipv4_mapped() {
Some(v4) => is_private_ipv4(&v4),
None => false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_private_ipv4() {
assert!(is_private_ipv4(&"127.0.0.1".parse().unwrap()));
assert!(is_private_ipv4(&"10.0.0.1".parse().unwrap()));
assert!(is_private_ipv4(&"192.168.1.1".parse().unwrap()));
assert!(is_private_ipv4(&"172.16.0.1".parse().unwrap()));
assert!(is_private_ipv4(&"0.0.0.0".parse().unwrap()));
assert!(is_private_ipv4(&"100.64.0.1".parse().unwrap()));
assert!(!is_private_ipv4(&"8.8.8.8".parse().unwrap()));
}
#[test]
fn test_private_ipv6() {
assert!(is_private_ipv6(&"::1".parse().unwrap()));
assert!(is_private_ipv6(&"::".parse().unwrap()));
assert!(is_private_ipv6(&"fc00::1".parse().unwrap()));
assert!(is_private_ipv6(&"fe80::1".parse().unwrap()));
assert!(!is_private_ipv6(&"2001:db8::1".parse().unwrap()));
}
}