Calculating all addresses within a subnet…for IPv6

前端 未结 4 1258
失恋的感觉
失恋的感觉 2021-01-02 17:26

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

相关标签:
4条回答
  • 2021-01-02 17:41

    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.

    0 讨论(0)
  • 2021-01-02 17:44

    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 !

    0 讨论(0)
  • 2021-01-02 18:05

    I know this post is 5yr old, but given the Google capabilities it may as well have been updated this morning. So, I'll add a bit of clarification from the network engineering perspective.

    It depends on what kind of addresses. If you mean every address in the range, then the above discussion is correct. If you mean addresses that can be uniquely assigned to a node in the subnet ("unicast" addresses), be aware that in IPv6 (a) there is no broadcast, and (b) there is a substantial multicast range.

    Basically: [subnet]:ff:: is reserved for multicast. If you're not using a /64 for a subnet mask, you REALLY want to be careful because it goes against a fundamental assumption is many IPv6-related RFCs. There's other RFCs out that caution against using the all-zeros host address (but I'm not aware of a specific requirement to that effect).

    So, for a /64 subnet, that means the range of unicast addresses is ::0:0:0:1 through ::feff:ffff:ffff:ffff.

    See here for discussion: http://www.tcpipguide.com/free/t_IPv6MulticastandAnycastAddressing.htm

    weylin

    0 讨论(0)
  • 2021-01-02 18:08

    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);
        }
    
    0 讨论(0)
提交回复
热议问题