2012-05-09 27 views
7

Si tengo un rango de direcciones IP (notación CIDR) y necesito saber si alguna dirección IP arbitraria está dentro de ese rango, ambas presentadas como cadenas, ¿cuál es la forma más fácil de hacerlo con C#?¿Cómo comparar el rango de direcciones IP en C#?

Ejemplos:

  • IPv4 Rango: 192.168.168.100/24, IP para comprobar: 192.168.168.200
  • IPv6 Rango: fe80::202:b3ff:fe1e:8329/24, IP para comprobar: 2001:db8::
+0

¿Le interesaría ver una solución solo IPv4? – Tung

+0

No. ipv4 es bastante fácil. Lo que lo hace desafiante es ipv6, o cuando los dos formatos están mezclados. A juzgar por la falta de respuestas aquí, parece que a mucha gente no le importa ... – ahmd0

Respuesta

10

Aquí está una clase simple: el uso

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

muestra:

trata
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 

Esta clase todos direcciones IPv4 a diferencia de todas las direcciones IPv6, sin hacer ningún intento de traducir entre IPv4 e IPv6.

+0

Gracias. Aunque IPv4 se debe convertir a IPv6, por ejemplo, se puede usar ":: 192.168.168.100" que su código tratará como IPv6. – ahmd0

+1

¿Está seguro de que es correcto convertir una dirección IPv4 a IPv6 simplemente con el prefijo "::"? El artículo de Wikipedia [dirección IPv6] (http://en.wikipedia.org/wiki/IPv6_address#Special_addresses) no lo incluye como uno de los mecanismos de traducción de IPv4. –

+0

Perdón por este retraso. Lo encontré en línea, si buscas "convertir Ipv4 a IPv6". Entonces no sé ... – ahmd0

2
+1

Bueno, lástima, porque no está muy claro cómo hacer esta comparación. Por ejemplo, ¿qué pasa si el rango está en notación ipv6 pero la dirección es ipv4 y viceversa? Además, tampoco está claro aplicar simplemente la máscara de subred a direcciones IPv6. Y no hay muchos ejemplos de esto en la web ... – ahmd0

+0

No estoy seguro de lo que quieres decir? IPv4 e IPv6 son 2 cosas completamente diferentes. Ningún IPv4 estará en notación IPv6. No trataría :: 192.168.1.1 igual que otras direcciones IPv6. – LukeP

1

Recomendaría el uso de la biblioteca de IPNetwork https://github.com/lduchosal/ipnetwork. A partir de la versión 2, también es compatible con IPv4 e 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); 

salida

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

salida

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

¡Diviértete!

Cuestiones relacionadas