8

CIDR表記で提供されるIPv4アドレス(例:192.168.0.1 / 25)を関連する範囲(192.168.0.1〜192.168.0.126)に変換する方法を示す優れたC#の例をたくさん見てきました。私のプログラムはこれを実行できる必要があります(ローカルサブネット内のすべてのアドレスを計算するため)が、IPv6もサポートしたいと思います。

C#プログラムに一般的なipconfig情報(IPv4アドレス、サブネットマスク、IPv6アドレス、リンクローカルv6アドレス、デフォルトゲートウェイ)がすべて含まれている場合、ローカルサブネット内のすべてのIPv6アドレスのリストを生成するにはどうすればよいですか?それらをコンソールに出力しますか?

4

4 に答える 4

10

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を消耗するタスクになる可能性があることに注意してください。

于 2011-08-16T19:45:19.960 に答える
1

exNetworkLibraryは優れたツールですが、プロジェクトで使用できない場合は、次の記事を参照してください。

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

IPv4で使用するためのアドレスマスクの計算方法の概要を説明します。

あなたの質問は私が見るIPv6に関連していて、.Net4.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);
    }
于 2015-02-01T19:56:00.750 に答える
1

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

楽しむ !

于 2015-08-11T09:22:35.537 に答える
0

この投稿は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

ウェイリン

于 2016-10-25T15:03:47.253 に答える