计算子网内的所有地址...对于 IPv6

发布于 2024-11-30 04:03:48 字数 392 浏览 0 评论 0原文

我见过很多很棒的 C# 示例,演示如何将以 CIDR 表示法提供的 IPv4 地址(例如 192.168.0.1/25)转换为其相关范围(192.168.0.1 - 192.168.0.126)。我的程序需要能够执行此操作(计算本地子网内的所有地址),但我还想支持 IPv6。

如果我的 C# 程序具有所有典型的 ipconfig 信息(IPv4 地址、子网掩码、IPv6 地址、链路本地 v6 地址、默认网关),我将如何生成本地子网中所有 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小傻瓜 2024-12-07 04:03:48

您可以使用 eExNetworkLibrary 中的 eExNetworkLibrary.IP.IPAddressAnalysis 类。

以下代码适用于 IPv4 和 IPv6(刚刚测试)。

        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();

我不完全确定我是否已完成从前缀长度到包含子网掩码的字节数组的转换,但这段代码应该为您提供一个很好的起点。

编辑:更新了代码的位弯曲部分。可能很难看,但适用于这个例子。我认为如果需要的话,您将有能力找到更好的解决方案。这些 BitArray 让人头疼。

请注意,如果网络很大,生成 IPv6 网络范围可能是一项非常消耗内存/CPU 的任务。

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.

苏辞 2024-12-07 04:03:48

我建议使用 IPNetwork 库 https://github.com/lduchosal/ipnetwork
从版本 2 开始,它还支持 IPv4 和 IPv6。

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);

输出

Network : 2001:db8::
Netmask : ffff:ffff:ffff:ffff::
Broadcast : 
FirstUsable : 2001:db8::
LastUsable : 2001:db8::ffff:ffff:ffff:ffff
Usable : 18446744073709551616
Cidr : 64

枚举

  IPNetwork network = IPNetwork.Parse("::/124");
  IPNetworkCollection ips = IPNetwork.Subnet(network, 128);

  foreach (IPNetwork ip in ips) {
      Console.WriteLine("{0}", ip);
  }

输出

::/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

玩得开心!

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 !

☆獨立☆ 2024-12-07 04:03:48

exNetworkLibrary 是一个很棒的工具,但如果你不能在你的项目中使用它,那么你可能只想看看这个文章:

http://www.codeproject.com/Articles/112020/IP-Address-Extension

它概述了如何计算在 IPv4 中使用的地址掩码。

我看到你的问题与 IPv6 有关,从 .Net 4.5 开始,有一个 IPAddress.MapToIPv6 方法。

https://msdn。 microsoft.com/en-us/library/system.net.ipaddress.maptoipv6(v=vs.110).aspx

您可以将其与本文中的检查一起使用来生成以下代码:

    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);
    }

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);
    }
马蹄踏│碎落叶 2024-12-07 04:03:48

我知道这篇文章已经有 5 年历史了,但考虑到 Google 的功能,它可能已经在今天早上更新了。因此,我将从网络工程的角度进行一些澄清。

这取决于什么样的地址。如果您指的是范围内的每个地址,那么上述讨论是正确的。如果您指的是可以唯一分配给子网中的节点的地址(“单播”地址),请注意在 IPv6 中 (a) 没有广播,并且 (b) 存在很大的多播范围。

基本上: [subnet]:ff:: 是为多播保留的。如果您不使用 /64 作为子网掩码,那么您一定要小心,因为它违背了许多 IPv6 相关 RFC 的基本假设。还有其他 RFC 警告不要使用全零主机地址(但我不知道对此有具体要求)。

因此,对于 /64 子网,这意味着单播地址范围为 ::0:0:0:1 到 ::feff:ffff:ffff:ffff。

请参阅此处进行讨论:
http://www.tcpipguide.com/free/t_IPv6MulticastandAnycastAddressing.htm

韦林

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文