Calculating all addresses within a subnet...for IPv6

DaveUK picture DaveUK · Aug 16, 2011 · Viewed 8.3k times · Source

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?

Answer

Emiswelt picture Emiswelt · Aug 16, 2011

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.