Skip to content

Instantly share code, notes, and snippets.

@cmcconnell1
Created October 10, 2024 01:02

Revisions

  1. cmcconnell1 created this gist Oct 10, 2024.
    62 changes: 62 additions & 0 deletions main.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,62 @@
    use std::net::{SocketAddr, IpAddr, Ipv4Addr};

    /// Checks if a given `SocketAddr` is within the specified local IP ranges:
    /// - 127.0.0.1 (loopback address)
    /// - 10.0.0.0/8
    /// - 172.16.0.0/12
    /// - 192.168.0.0/16
    fn is_local(addr: &SocketAddr) -> bool {
    match addr.ip() {
    IpAddr::V4(ip) => {
    // Check if the IP is 127.0.0.1 (loopback address)
    ip == Ipv4Addr::LOCALHOST
    // Check if the IP is within the 10.0.0.0/8 range
    || (ip.octets()[0] == 10)
    // Check if the IP is within the 172.16.0.0/12 range (172.16.0.0 to 172.31.255.255)
    || (ip.octets()[0] == 172 && (16..=31).contains(&ip.octets()[1]))
    // Check if the IP is within the 192.168.0.0/16 range
    || (ip.octets()[0] == 192 && ip.octets()[1] == 168)
    }
    // Only IPv4 addresses are considered; IPv6 addresses are not local by these criteria.
    IpAddr::V6(_) => false,
    }
    }

    #[cfg(test)]
    mod tests {
    use super::*;
    use std::net::{SocketAddr, Ipv4Addr};

    #[test]
    fn test_is_local() {
    // Test cases for IPs that should be considered local
    let local_ips = [
    "127.0.0.1:8080", // Loopback address
    "10.0.0.1:8080", // Within 10.0.0.0/8 range
    "172.16.0.1:8080", // Within 172.16.0.0/12 range
    "192.168.0.1:8080", // Within 192.168.0.0/16 range
    ];

    for ip_str in &local_ips {
    // Parse the string into a `SocketAddr` type
    let addr: SocketAddr = ip_str.parse().expect("Failed to parse IP");
    // Assert that the IP is recognized as local
    assert!(is_local(&addr), "Expected {} to be local", ip_str);
    }

    // Test cases for IPs that should be considered non-local
    let non_local_ips = [
    "8.8.8.8:8080", // Google DNS, non-local
    "172.32.0.1:8080", // Outside 172.16.0.0/12 range
    "192.169.0.1:8080", // Outside 192.168.0.0/16 range
    "11.0.0.1:8080", // Outside 10.0.0.0/8 range
    ];

    for ip_str in &non_local_ips {
    // Parse the string into a `SocketAddr` type
    let addr: SocketAddr = ip_str.parse().expect("Failed to parse IP");
    // Assert that the IP is not recognized as local
    assert!(!is_local(&addr), "Expected {} to be non-local", ip_str);
    }
    }
    }