Files
sbox-public/engine/Sandbox.System/Extend/UriExtension.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

63 lines
2.1 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Net.Sockets;
using System.Net;
namespace Sandbox;
public static partial class SandboxSystemExtensions
{
/// <summary>
/// Does this Uri resolve to a private range IP address?
/// </summary>
internal static bool IsPrivate( this Uri uri )
{
// don't allow any domains that resolve to private or loopback ip addresses
if ( Dns.GetHostEntry( uri.DnsSafeHost ).AddressList.Any( x => x.IsPrivate() ) )
return true;
return false;
}
/// <summary>
/// Returns true if the IP address is in a private range.<br/>
/// IPv4: Loopback, link local ("169.254.x.x"), class A ("10.x.x.x"), class B ("172.16.x.x" to "172.31.x.x") and class C ("192.168.x.x").<br/>
/// IPv6: Loopback, link local, site local, unique local and private IPv4 mapped to IPv6.<br/>
/// </summary>
internal static bool IsPrivate( this IPAddress ip )
{
// Map back to IPv4 if mapped to IPv6, for example "::ffff:1.2.3.4" to "1.2.3.4".
if ( ip.IsIPv4MappedToIPv6 )
ip = ip.MapToIPv4();
// Checks loopback ranges for both IPv4 and IPv6.
if ( IPAddress.IsLoopback( ip ) ) return true;
// IPv4
if ( ip.AddressFamily == AddressFamily.InterNetwork )
{
var ipv4Bytes = ip.GetAddressBytes();
// Link local (no IP assigned by DHCP): 169.254.0.0 to 169.254.255.255 (169.254.0.0/16)
bool IsLinkLocal() => ipv4Bytes[0] == 169 && ipv4Bytes[1] == 254;
// Class A private range: 10.0.0.0 10.255.255.255 (10.0.0.0/8)
bool IsClassA() => ipv4Bytes[0] == 10;
// Class B private range: 172.16.0.0 172.31.255.255 (172.16.0.0/12)
bool IsClassB() => ipv4Bytes[0] == 172 && ipv4Bytes[1] >= 16 && ipv4Bytes[1] <= 31;
// Class C private range: 192.168.0.0 192.168.255.255 (192.168.0.0/16)
bool IsClassC() => ipv4Bytes[0] == 192 && ipv4Bytes[1] == 168;
return IsLinkLocal() || IsClassA() || IsClassC() || IsClassB();
}
// IPv6
if ( ip.AddressFamily == AddressFamily.InterNetworkV6 )
{
return ip.IsIPv6LinkLocal || ip.IsIPv6UniqueLocal || ip.IsIPv6SiteLocal;
}
throw new NotSupportedException( $"IP address family {ip.AddressFamily} is not supported, expected only IPv4 (InterNetwork) or IPv6 (InterNetworkV6)" );
}
}