Search code examples
c#ipv6subnet

Calculating all addresses within a subnet...for IPv6


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?


Solution

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