문제

If I have an IP address range (CIDR notation) and I need to know if some arbitrary IP address is within that range -- both presented as strings -- what is the easiest way to do this with C#?

Examples:

  • IPv4 Range: 192.168.168.100/24, IP to check: 192.168.168.200
  • IPv6 Range: fe80::202:b3ff:fe1e:8329/24, IP to check: 2001:db8::
도움이 되었습니까?

해결책

Here's a simple class:

public class IPSubnet
{
    private readonly byte[] _address;
    private readonly int _prefixLength;

    public IPSubnet(string value)
    {
        if (value == null)
            throw new ArgumentNullException("value");

        string[] parts = value.Split('/');
        if (parts.Length != 2)
            throw new ArgumentException("Invalid CIDR notation.", "value");

        _address = IPAddress.Parse(parts[0]).GetAddressBytes();
        _prefixLength = Convert.ToInt32(parts[1], 10);
    }

    public bool Contains(string address)
    {
        return this.Contains(IPAddress.Parse(address).GetAddressBytes());
    }

    public bool Contains(byte[] address)
    {
        if (address == null)
            throw new ArgumentNullException("address");

        if (address.Length != _address.Length)
            return false; // IPv4/IPv6 mismatch

        int index = 0;
        int bits = _prefixLength;

        for (; bits >= 8; bits -= 8)
        {
            if (address[index] != _address[index])
                return false;
            ++index;
        }

        if (bits > 0)
        {
            int mask = (byte)~(255 >> bits);
            if ((address[index] & mask) != (_address[index] & mask))
                return false;
        }

        return true;
    }
}

Sample usage:

Console.WriteLine(new IPSubnet("192.168.168.100/24").Contains("192.168.168.200")); // True
Console.WriteLine(new IPSubnet("fe80::202:b3ff:fe1e:8329/24").Contains("2001:db8::")); // False

This class treats all IPv4 addresses as distinct from all IPv6 addresses, making no attempt to translate between IPv4 and IPv6.

다른 팁

I would recommend the use of IPNetwork Library https://github.com/lduchosal/ipnetwork. As of version 2, it supports IPv4 and IPv6 as well.

IPv6

  IPNetwork ipnetwork = IPNetwork.Parse("fe80::202:b3ff:fe1e:8329/24");

  IPAddress ipaddress = IPAddress.Parse("2001:db8::");
  IPAddress ipaddress2 = IPAddress.Parse("fe80::202:b3ff:fe1e:1");

  bool contains1 = IPNetwork.Contains(ipnetwork, ipaddress);
  bool contains2 = IPNetwork.Contains(ipnetwork, ipaddress2);

  Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress,     contains1);
  Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress2,     contains2);

Output

   fe80::/24 contains 2001:db8:: : False
   fe80::/24 contains fe80::202:b3ff:fe1e:1 : True

IPv4

  IPNetwork ipnetwork = IPNetwork.Parse("192.168.168.100/24");

  IPAddress ipaddress = IPAddress.Parse("192.168.168.200");
  IPAddress ipaddress2 = IPAddress.Parse("192.168.0.200");

  bool contains1 = IPNetwork.Contains(ipnetwork, ipaddress);
  bool contains2 = IPNetwork.Contains(ipnetwork, ipaddress2);

  Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress, contains1);
  Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress2, contains2);

Output

  192.168.168.0/24 contains 192.168.168.200 : True
  192.168.168.0/24 contains 192.168.0.200 : False

Have fun !

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top