2012-05-09 33 views
7

Jeśli mam zakres adresów IP (notacja CIDR) i muszę wiedzieć, czy jakiś arbitralny adres IP mieści się w tym zakresie - oba prezentowane jako łańcuchy - jaki jest najprostszy sposób na zrobienie tego za pomocą C#?Jak porównać zakres adresów IP w języku C#?

Przykłady:

  • IPv4 Rząd: 192.168.168.100/24, IP do sprawdzenia: 192.168.168.200
  • IPv6 Zakres: fe80::202:b3ff:fe1e:8329/24, IP do sprawdzenia: 2001:db8::
+0

Czy byłby (a) zainteresowany (a) rozwiązaniem tylko rozwiązanie IPv4? – Tung

+0

Nie. Ipv4 jest całkiem łatwe. Wyzwaniem jest ipv6 lub mieszanie dwóch formatów. Sądząc po braku odpowiedzi, wydaje się, że niewiele osób to obchodzi ... – ahmd0

Odpowiedz

10

Oto proste klasy: Wykorzystanie

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

Próbka:

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 

Ta klasa traktuje wszystkich adresów IPv4, w odróżnieniu od wszystkich adresów IPv6, nie próbując tłumaczyć między IPv4 i IPv6.

+0

Dzięki. Chociaż na przykład IPv4 powinno być konwertowane na IPv6, można użyć ":: 192.168.168.100", który będzie traktowany przez twój kod jako IPv6. – ahmd0

+1

Czy jesteś pewien, że konwersja adresu IPv4 na IPv6 jest poprawna, po prostu poprzedzając go "::"? Adres [adres IPv6] (http://en.wikipedia.org/wiki/IPv6_address#Special_addresses) w Wikipedii nie wymienia tego jako jednego z mechanizmów tłumaczenia IPv4. –

+0

Przepraszamy za opóźnienie. Znalazłem go online, jeśli wyszukasz "przekonwertuj IPv4 na IPv6". Więc nie wiem ... – ahmd0

2
+1

Cóż, szkoda, ponieważ nie jest jasne, jak to zrobić. Na przykład, jeśli zakres jest zapisany w formacie ipv6, ale adres to ipv4 i vice verse? Również samo zastosowanie maski podsieci do adresów IPv6 również nie jest jasne. I nie ma wielu przykładów tego w Internecie ... – ahmd0

+0

Nie jestem pewien co masz na myśli? IPv4 i IPv6 to dwie zupełnie różne rzeczy. Żadne IPv4 nie będzie zapisywane w IPv6. Nie traktowałbym: 192.168.1.1 taki sam jak inne adresy IPv6. – LukeP

1

Polecam korzystanie z biblioteki IPNetwork https://github.com/lduchosal/ipnetwork. Od wersji 2 obsługuje również protokoły IPv4 i 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); 

Wyjście

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

Wyjście

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

Miłej zabawy!

Powiązane problemy