I have seen plenty of great C# examples which demonstrate how to convert IPv4 addresses provided in CIDR notation (e.g. 192.168.0.1/25) into their relevant ranges (192.168.0.1 - 192.168.0.126). My program needs to be able to do this (to compute all the addresses within my local subnet) but I want to also support IPv6.
If my C# program has all of my typical ipconfig information (IPv4 address, subnet mask, IPv6 address, link-local v6 address, default gateway) - how would I go about generating a list of all of the IPv6 addresses in my local subnet and outputting them to the console?
You can use the eExNetworkLibrary.IP.IPAddressAnalysis class from the eExNetworkLibrary.
The following code works with IPv4 and IPv6 (just tested).
string strIn = "2001:DB8::/120";
//Split the string in parts for address and prefix
string strAddress = strIn.Substring(0, strIn.IndexOf('/'));
string strPrefix = strIn.Substring(strIn.IndexOf('/') + 1);
int iPrefix = Int32.Parse(strPrefix);
IPAddress ipAddress = IPAddress.Parse(strAddress);
//Convert the prefix length to a valid SubnetMask
int iMaskLength = 32;
if(ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
{
iMaskLength = 128;
}
BitArray btArray = new BitArray(iMaskLength);
for (int iC1 = 0; iC1 < iMaskLength; iC1++)
{
//Index calculation is a bit strange, since you have to make your mind about byte order.
int iIndex = (int)((iMaskLength - iC1 - 1) / 8) * 8 + (iC1 % 8);
if (iC1 < (iMaskLength - iPrefix))
{
btArray.Set(iIndex, false);
}
else
{
btArray.Set(iIndex, true);
}
}
byte[] bMaskData = new byte[iMaskLength / 8];
btArray.CopyTo(bMaskData, 0);
//Create subnetmask
Subnetmask smMask = new Subnetmask(bMaskData);
//Get the IP range
IPAddress ipaStart = IPAddressAnalysis.GetClasslessNetworkAddress(ipAddress, smMask);
IPAddress ipaEnd = IPAddressAnalysis.GetClasslessBroadcastAddress(ipAddress, smMask);
//Omit the following lines if your network range is large
IPAddress[] ipaRange = IPAddressAnalysis.GetIPRange(ipaStart, ipaEnd);
//Debug output
foreach (IPAddress ipa in ipaRange)
{
Console.WriteLine(ipa.ToString());
}
Console.ReadLine();
I'm not completely sure if I have done the conversion from the prefix length to a byte array containing the subnet mask right, but this code should give you a good starting point.
Edit: Updated the bit-bending part of the code. May be ugly, but works for this example. I think you will be capable of finding a better solution, if you need to. Those BitArrays are a pain in the neck.
Be aware that generating an IPv6 network range can be a very memory/cpu exhausting task if the network is large.
exNetworkLibrary is a great tool but if you can't use it in your project then you may just want to see this article:
http://www.codeproject.com/Articles/112020/IP-Address-Extension
It outlines how address masks are calculated for use in IPv4.
Your question is related to IPv6 I see and Since .Net 4.5 there is a IPAddress.MapToIPv6
method.
https://msdn.microsoft.com/en-us/library/system.net.ipaddress.maptoipv6(v=vs.110).aspx
You can utilize that with the checks in the article to produce this code:
private static IPAddress empty = IPAddress.Parse("0.0.0.0");
private static IPAddress intranetMask1 = IPAddress.Parse("10.255.255.255");
private static IPAddress intranetMask2 = IPAddress.Parse("172.16.0.0");
private static IPAddress intranetMask3 = IPAddress.Parse("172.31.255.255");
private static IPAddress intranetMask4 = IPAddress.Parse("192.168.255.255");
/// <summary>
/// Retuns true if the ip address is one of the following
/// IANA-reserved private IPv4 network ranges (from http://en.wikipedia.org/wiki/IP_address)
/// Start End
/// 10.0.0.0 10.255.255.255
/// 172.16.0.0 172.31.255.255
/// 192.168.0.0 192.168.255.255
/// </summary>
/// <returns></returns>
public static bool IsOnIntranet(this IPAddress ipAddress)
{
if (empty.Equals(ipAddress))
{
return false;
}
bool onIntranet = IPAddress.IsLoopback(ipAddress);
if (false == onIntranet)
{
//Handle IPv6 by getting the IPv4 Mapped Address.
if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
{
onIntranet = ipAddress.Equals(ipAddress.And(intranetMask1.MapToIPv6())); //10.255.255.255
onIntranet = onIntranet || ipAddress.Equals(ipAddress.And(intranetMask4.MapToIPv6())); ////192.168.255.255
onIntranet = onIntranet || (intranetMask2.Equals(ipAddress.And(intranetMask2.MapToIPv6()))
&& ipAddress.Equals(ipAddress.And(intranetMask3.MapToIPv6())));
}
else
{
onIntranet = ipAddress.Equals(ipAddress.And(intranetMask1)); //10.255.255.255
onIntranet = onIntranet || ipAddress.Equals(ipAddress.And(intranetMask4)); ////192.168.255.255
onIntranet = onIntranet || (intranetMask2.Equals(ipAddress.And(intranetMask2))
&& ipAddress.Equals(ipAddress.And(intranetMask3)));
}
}
return onIntranet;
}
private static void CheckIPVersion(IPAddress ipAddress, IPAddress mask, out byte[] addressBytes, out byte[] maskBytes)
{
if (mask == null)
{
throw new ArgumentException();
}
addressBytes = ipAddress.GetAddressBytes();
maskBytes = mask.GetAddressBytes();
if (addressBytes.Length != maskBytes.Length)
{
throw new ArgumentException("The address and mask don't use the same IP standard");
}
}
public static IPAddress And(this IPAddress ipAddress, IPAddress mask)
{
byte[] addressBytes;
byte[] maskBytes;
CheckIPVersion(ipAddress, mask, out addressBytes, out maskBytes);
byte[] resultBytes = new byte[addressBytes.Length];
for (int i = 0, e = addressBytes.Length; i < e; ++i)
{
resultBytes[i] = (byte)(addressBytes[i] & maskBytes[i]);
}
return new IPAddress(resultBytes);
}
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("2001:0db8::/64");
Console.WriteLine("Network : {0}", ipnetwork.Network);
Console.WriteLine("Netmask : {0}", ipnetwork.Netmask);
Console.WriteLine("Broadcast : {0}", ipnetwork.Broadcast);
Console.WriteLine("FirstUsable : {0}", ipnetwork.FirstUsable);
Console.WriteLine("LastUsable : {0}", ipnetwork.LastUsable);
Console.WriteLine("Usable : {0}", ipnetwork.Usable);
Console.WriteLine("Cidr : {0}", ipnetwork.Cidr);
Output
Network : 2001:db8::
Netmask : ffff:ffff:ffff:ffff::
Broadcast :
FirstUsable : 2001:db8::
LastUsable : 2001:db8::ffff:ffff:ffff:ffff
Usable : 18446744073709551616
Cidr : 64
Enumeration
IPNetwork network = IPNetwork.Parse("::/124");
IPNetworkCollection ips = IPNetwork.Subnet(network, 128);
foreach (IPNetwork ip in ips) {
Console.WriteLine("{0}", ip);
}
Output
::/128
::1/128
::2/128
::3/128
::4/128
::5/128
::6/128
::7/128
::8/128
::9/128
::a/128
::b/128
::c/128
::d/128
::e/128
::f/128
Have fun !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With