Search code examples
c#ipv6ipv4cidr

How to compare IP address range in C#?


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::

Solution

  • 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.