How to compare IP address range in C#?
Question
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.
OTHER TIPS
I'm not going to write code for you but:
- http://msdn.microsoft.com/en-us/library/system.net.ipaddress.aspx
- http://blogs.msdn.com/b/knom/archive/2008/12/31/ip-address-calculations-with-c-subnetmasks-networks.aspx
- Is IP address on the same subnet as the local machine (with IPv6 support)
- Calculating all addresses within a subnet...for IPv6
should be enough to get you started.
Good luck
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 !
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow