2012-05-09 75 views
7

私はIPアドレス範囲(CIDR表記)を持っていて、任意のIPアドレスがその範囲内にあるかどうかを知る必要があります - どちらも文字列として表示されます - C#でこれを行う最も簡単な方法は何ですか?C#のIPアドレス範囲を比較するには?

例:

  • IPv4の範囲:192.168.168.100/24、IPをチェックする:192.168.168.200
  • IPv6の範囲:fe80::202:b3ff:fe1e:8329/24、IPをチェックする:2001:db8::
+0

IPv4専用のソリューションを検討したいですか? – Tung

+0

いいえ、ipv4はかなり簡単です。それが挑戦的になるのは、ipv6、または2つのフォーマットが混在している場合です。ここに回答がないと判断して、多くの人がそれを気にしないようです... – ahmd0

答えて

10

ここでは単純なクラスです。このクラスは、変換する試みを行っていない、すべてのIPv4は、すべてのIPv6アドレスとは異なり対処扱い

Console.WriteLine(new IPSubnet("192.168.168.100/24").Contains("192.168.168.200")); // True 
Console.WriteLine(new IPSubnet("fe80::202:b3ff:fe1e:8329/24").Contains("2001:db8::")); // False 

public class IPSubnet 
{ 
    private readonly byte[] _address; 
    private readonly int _prefixLength; 

    public IPSubnet(string value) 
    { 
     if (value == null) 
      throw new ArgumentNullException("value"); 

     string[] parts = value.Split('/'); 
     if (parts.Length != 2) 
      throw new ArgumentException("Invalid CIDR notation.", "value"); 

     _address = IPAddress.Parse(parts[0]).GetAddressBytes(); 
     _prefixLength = Convert.ToInt32(parts[1], 10); 
    } 

    public bool Contains(string address) 
    { 
     return this.Contains(IPAddress.Parse(address).GetAddressBytes()); 
    } 

    public bool Contains(byte[] address) 
    { 
     if (address == null) 
      throw new ArgumentNullException("address"); 

     if (address.Length != _address.Length) 
      return false; // IPv4/IPv6 mismatch 

     int index = 0; 
     int bits = _prefixLength; 

     for (; bits >= 8; bits -= 8) 
     { 
      if (address[index] != _address[index]) 
       return false; 
      ++index; 
     } 

     if (bits > 0) 
     { 
      int mask = (byte)~(255 >> bits); 
      if ((address[index] & mask) != (_address[index] & mask)) 
       return false; 
     } 

     return true; 
    } 
} 

使用例IPv4とIPv6の間で

+0

ありがとうございます。たとえば、IPv4をIPv6に変換する必要がありますが、コードでIPv6として扱われる ":: 192.168.168.100"を使用できます。 – ahmd0

+1

"::"という接頭辞を付けるだけで、IPv4アドレスをIPv6に変換するのが正しいのですか? [IPv6アドレス](http://en.wikipedia.org/wiki/IPv6_address#Special_addresses)Wikipediaの記事では、これをIPv4変換メカニズムの1つとして挙げていません。 –

+0

この遅れて申し訳ありません。私はあなたが "Ipv4をIPv6に変換する"を検索すると、それをオンラインで見つけました。だから私は知らない... – ahmd0

2
+1

この比較を行う方法はあまり明確ではないので、あまりにも悪いです。たとえば、範囲がipv6の表記法であるが、アドレスがipv4で、その逆の場合はどうでしょうか?また、ipv6アドレスにサブネットマスクを適用するだけでは不明確です。そして、Web上にそれの例はあまりありません... – ahmd0

+0

あなたはどういう意味ですか? IPv4とIPv6は2つの全く異なるものです。 IPv4はIPv6表記になりません。私は扱いません:: 192.168.1。1は他のIPv6アドレスと同じです。 – LukeP

1

IPNetworkライブラリhttps://github.com/lduchosal/ipnetworkの使用をお勧めします。 バージョン2では、IPv4とIPv6もサポートしています。

のIPv6

IPNetwork ipnetwork = IPNetwork.Parse("fe80::202:b3ff:fe1e:8329/24"); 

    IPAddress ipaddress = IPAddress.Parse("2001:db8::"); 
    IPAddress ipaddress2 = IPAddress.Parse("fe80::202:b3ff:fe1e:1"); 

    bool contains1 = IPNetwork.Contains(ipnetwork, ipaddress); 
    bool contains2 = IPNetwork.Contains(ipnetwork, ipaddress2); 

    Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress,  contains1); 
    Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress2,  contains2); 

出力

fe80::/24 contains 2001:db8:: : False 
    fe80::/24 contains fe80::202:b3ff:fe1e:1 : True 

のIPv4

IPNetwork ipnetwork = IPNetwork.Parse("192.168.168.100/24"); 

    IPAddress ipaddress = IPAddress.Parse("192.168.168.200"); 
    IPAddress ipaddress2 = IPAddress.Parse("192.168.0.200"); 

    bool contains1 = IPNetwork.Contains(ipnetwork, ipaddress); 
    bool contains2 = IPNetwork.Contains(ipnetwork, ipaddress2); 

    Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress, contains1); 
    Console.WriteLine("{0} contains {1} : {2}", ipnetwork, ipaddress2, contains2); 

出力

192.168.168.0/24 contains 192.168.168.200 : True 
    192.168.168.0/24 contains 192.168.0.200 : False 

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

関連する問題