2011-08-16 12 views
6

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

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

+2

。設計上、IPv6で見られるほとんどすべてのサブネットは/ 64、または(2^64)-1のホストが大きくなります。 – Joe

+2

それは正しいです、私はすべての18,446,744,073,709,551,616のIPアドレスが必要です;) – DaveUK

+8

そしてあなたはそれらで何をしますか? 1秒間に1000万回でさえ、それらをすべて通過するには58,000年が必要です。 – Joe

答えて

9

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

私は、サブネットマスクの権利を含むバイト配列にプレフィックス長からの変換を行っている場合は、完全にわからないんだけど、このコードはあなたに良い出発点を与える必要があります。

:コードのビット曲げ部分が更新されました。醜いかもしれませんが、この例では機能します。あなたが必要な場合は、より良いソリューションを見つけることができると思います。それらのBitArraysは首の痛みです。

IPv6ネットワークの範囲を生成することは、ネットワークが大規模である場合、非常にメモリ/ CPUを使い果たすタスクになる可能性があることに注意してください。

+0

これはほとんど私のために働いた。 iIndexを(iMaskLength - iC1 - 1)に変更する必要がありました。これは編集前のコードなので、なぜ変更されたのか分かりません。 –

1

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

私は、IPネットワークライブラリ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 

楽しくお楽しみください!

+0

最初と最後の使用可能なアドレスの出力が正しくありません。 IPv6は、IPv4と異なり、サブネット内のすべてのアドレスを使用できます。標準のIPv6サブネットは/ 64です(いくつかの特別なケースでは他のマスク長を使用します)。使用可能なアドレスは ' ::'から ':ffff:ffff:ffff:ffff'です。サブネット( ' :: ')の予約はなく、IPv6にはブロードキャストの概念がないため、ブロードキャストアドレスは' :ffff:ffff:ffff:ffff'に存在しません。 –

+1

これを指摘してくれてありがとう。修正例 – LukeSkywalker

0

私はこの記事が5歳であることを知っていますが、Googleの能力を考慮すると、今朝更新されている可能性があります。そこで、ネットワークエンジニアリングの観点から少し説明を追加します。

どのような種類のアドレスに依存しますか。範囲内のすべてのアドレスを意味する場合、上記の説明は正しいです。サブネット内のノード(ユニキャストアドレス)に一意的に割り当てられるアドレスを意味する場合は、IPv6(a)ではブロードキャストがなく、(b)実質的なマルチキャスト範囲があることに注意してください。

基本的に[サブネット]:ff ::はマルチキャスト用に予約されています。サブネットマスクに/ 64を使用していない場合は、IPv6関連の多くのRFCが基本的な前提に反しているので、注意が必要です。オールゼロのホストアドレスの使用には注意が必要です(しかし、私は特定のの必要性を意識していません)。その効果はです。

したがって、/ 64サブネットの場合、ユニキャストアドレスの範囲は:: 0:0:0:1から:: feff:ffff:ffff:ffffであることを意味します。

は、議論のためにここを参照してください:あなたはおそらく、あなたの機能を再考する必要が http://www.tcpipguide.com/free/t_IPv6MulticastandAnycastAddressing.htm

weylin

+0

すべてゼロのホストアドレスは、このアドレスで応答しなければならないサブネットルーター用に予約されています。 [RFC 4291 section 2.6.1](https://tools.ietf.org/html/rfc4291#section-2.6.1)を参照してください。この要件にもかかわらず、多くのネットワーク上のルータはこのアドレスに応答しませんが、ルータが正常に動作するネットワーク上でこのアドレスを使用しようとすると、悪い一日を過ごすことになります。 –

関連する問題