2009-09-30 13 views

Antwort

23

Werfen Sie einen Blick auf IP Address Calculations with C# auf MSDN Blogs. Es enthält eine Erweiterungsmethode (IsInSameSubnet), die Ihre Bedürfnisse sowie einige andere Leckereien erfüllen sollte.

public static class IPAddressExtensions 
{ 
    public static IPAddress GetBroadcastAddress(this IPAddress address, IPAddress subnetMask) 
    { 
     byte[] ipAdressBytes = address.GetAddressBytes(); 
     byte[] subnetMaskBytes = subnetMask.GetAddressBytes(); 

     if (ipAdressBytes.Length != subnetMaskBytes.Length) 
      throw new ArgumentException("Lengths of IP address and subnet mask do not match."); 

     byte[] broadcastAddress = new byte[ipAdressBytes.Length]; 
     for (int i = 0; i < broadcastAddress.Length; i++) 
     { 
      broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i]^255)); 
     } 
     return new IPAddress(broadcastAddress); 
    } 

    public static IPAddress GetNetworkAddress(this IPAddress address, IPAddress subnetMask) 
    { 
     byte[] ipAdressBytes = address.GetAddressBytes(); 
     byte[] subnetMaskBytes = subnetMask.GetAddressBytes(); 

     if (ipAdressBytes.Length != subnetMaskBytes.Length) 
      throw new ArgumentException("Lengths of IP address and subnet mask do not match."); 

     byte[] broadcastAddress = new byte[ipAdressBytes.Length]; 
     for (int i = 0; i < broadcastAddress.Length; i++) 
     { 
      broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i])); 
     } 
     return new IPAddress(broadcastAddress); 
    } 

    public static bool IsInSameSubnet(this IPAddress address2, IPAddress address, IPAddress subnetMask) 
    { 
     IPAddress network1 = address.GetNetworkAddress(subnetMask); 
     IPAddress network2 = address2.GetNetworkAddress(subnetMask); 

     return network1.Equals(network2); 
    } 
} 
+0

Was ist mit IPv6-Adressen? – ageroh

+0

@ageroh GitHub scheint einige C# -Bibliotheken zu haben, die mit IPv6-Adressen umgehen können. IPNetwork, zum Beispiel https://github.com/lduchosal/ipnetwork –

10

Bit-Manipulation funktioniert. Stuff die IP in eine 32-Bit Integer ohne Vorzeichen, das gleiche mit der Adresse des Subnetz, & -mask sowohl mit 0xFFFFFFFF << (32-20) und vergleichen:

unsigned int net = ..., ip = ...; 
int network_bits = 20; 
unsigned int mask = 0xFFFFFFFF << (32 - network_bits); 
if ((net & mask) == (ip & mask)) { 
    // ... 
} 
+0

Oder, wenn wie üblich, das Subnetz als Zahl wie 255.255.240.0 gegeben, nur Sachen die Maske in eine 32-Bit-Ganzzahl anstelle der Verschiebung. – erikkallen

+3

Ich fand die System.Net.IPAddress Klasse hilfreich für das Parsen und Zerlegen von IP-Adressen in Bytes –

0

Die Lösung ist die IP-Adresse in Bytes auf die Adresse, Subnet und Maske Oktetts mit System.Net.IPAddress und führen bitweise Vergleiche zu konvertieren.

Der binäre UND-Operator & kopiert ein Bit in das Ergebnis, wenn es in beiden Operanden existiert.

Der Code:

using System.Net; // Used to access IPAddress 

bool IsAddressOnSubnet(string address, string subnet, string mask) 
{ 
    try 
    { 
     IPAddress Address = IPAddress.Parse(address); 
     IPAddress Subnet = IPAddress.Parse(subnet); 
     IPAddress Mask = IPAddress.Parse(mask);    

     Byte[] addressOctets = Address.GetAddressBytes(); 
     Byte[] subnetOctets = Mask.GetAddressBytes(); 
     Byte[] networkOctets = Subnet.GetAddressBytes(); 

     return 
      ((networkOctets[0] & subnetOctets[0]) == (addressOctets[0] & subnetOctets[0])) && 
      ((networkOctets[1] & subnetOctets[1]) == (addressOctets[1] & subnetOctets[1])) && 
      ((networkOctets[2] & subnetOctets[2]) == (addressOctets[2] & subnetOctets[2])) && 
      ((networkOctets[3] & subnetOctets[3]) == (addressOctets[3] & subnetOctets[3])); 
    } 
    catch (System.Exception ex) 
    { 
     return false;     
    } 
} 

Besonderer Dank geht an Спасибо! Прекрасное решение! Reference

+1

nur beachten Sie, das wird brechen, wenn mit IPv6-Adressen präsentiert – Fowl

2

Da der MSDN-Blog-Code auf einem Broadcast beruht und IPv6 keinen hat, weiß ich nicht, ob es mit IPv6 funktioniert.

Ich endete mit diesen Methoden (dank Nu Everest). Sie können das Subnetz und die Maske aus einer CIDR-Notation ("1.2.3.4/5") abrufen und prüfen, ob sich eine Adresse in diesem Netzwerk befindet oder nicht.

Diese für IPv4 und IPv6 funktioniert:

public static class IpAddresses 
{ 
    public static Tuple<IPAddress, IPAddress> GetSubnetAndMaskFromCidr(string cidr) 
    { 
     var delimiterIndex = cidr.IndexOf('/'); 
     string ipSubnet = cidr.Substring(0, delimiterIndex); 
     string mask = cidr.Substring(delimiterIndex + 1); 

     var subnetAddress = IPAddress.Parse(ipSubnet); 

     if (subnetAddress.AddressFamily == AddressFamily.InterNetworkV6) 
     { 
      // ipv6 
      var ip = BigInteger.Parse("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber) << (128 - int.Parse(mask)); 

      var maskBytes = new[] 
      { 
       (byte)((ip & BigInteger.Parse("00FF000000000000000000000000000000", NumberStyles.HexNumber)) >> 120), 
       (byte)((ip & BigInteger.Parse("0000FF0000000000000000000000000000", NumberStyles.HexNumber)) >> 112), 
       (byte)((ip & BigInteger.Parse("000000FF00000000000000000000000000", NumberStyles.HexNumber)) >> 104), 
       (byte)((ip & BigInteger.Parse("00000000FF000000000000000000000000", NumberStyles.HexNumber)) >> 96), 
       (byte)((ip & BigInteger.Parse("0000000000FF0000000000000000000000", NumberStyles.HexNumber)) >> 88), 
       (byte)((ip & BigInteger.Parse("000000000000FF00000000000000000000", NumberStyles.HexNumber)) >> 80), 
       (byte)((ip & BigInteger.Parse("00000000000000FF000000000000000000", NumberStyles.HexNumber)) >> 72), 
       (byte)((ip & BigInteger.Parse("0000000000000000FF0000000000000000", NumberStyles.HexNumber)) >> 64), 
       (byte)((ip & BigInteger.Parse("000000000000000000FF00000000000000", NumberStyles.HexNumber)) >> 56), 
       (byte)((ip & BigInteger.Parse("00000000000000000000FF000000000000", NumberStyles.HexNumber)) >> 48), 
       (byte)((ip & BigInteger.Parse("0000000000000000000000FF0000000000", NumberStyles.HexNumber)) >> 40), 
       (byte)((ip & BigInteger.Parse("000000000000000000000000FF00000000", NumberStyles.HexNumber)) >> 32), 
       (byte)((ip & BigInteger.Parse("00000000000000000000000000FF000000", NumberStyles.HexNumber)) >> 24), 
       (byte)((ip & BigInteger.Parse("0000000000000000000000000000FF0000", NumberStyles.HexNumber)) >> 16), 
       (byte)((ip & BigInteger.Parse("000000000000000000000000000000FF00", NumberStyles.HexNumber)) >> 8), 
       (byte)((ip & BigInteger.Parse("00000000000000000000000000000000FF", NumberStyles.HexNumber)) >> 0), 
      }; 

      return Tuple.Create(subnetAddress, new IPAddress(maskBytes)); 
     } 
     else 
     { 
      // ipv4 
      uint ip = 0xFFFFFFFF << (32 - int.Parse(mask)); 

      var maskBytes = new[] 
      { 
       (byte)((ip & 0xFF000000) >> 24), 
       (byte)((ip & 0x00FF0000) >> 16), 
       (byte)((ip & 0x0000FF00) >> 8), 
       (byte)((ip & 0x000000FF) >> 0), 
      }; 

      return Tuple.Create(subnetAddress, new IPAddress(maskBytes)); 
     } 
    } 

    public static bool IsAddressOnSubnet(IPAddress address, IPAddress subnet, IPAddress mask) 
    { 
     byte[] addressOctets = address.GetAddressBytes(); 
     byte[] subnetOctets = mask.GetAddressBytes(); 
     byte[] networkOctets = subnet.GetAddressBytes(); 

     // ensure that IPv4 isn't mixed with IPv6 
     if (addressOctets.Length != subnetOctets.Length 
      || addressOctets.Length != networkOctets.Length) 
     { 
      return false; 
     } 

     for (int i = 0; i < addressOctets.Length; i += 1) 
     { 
      var addressOctet = addressOctets[i]; 
      var subnetOctet = subnetOctets[i]; 
      var networkOctet = networkOctets[i]; 

      if (networkOctet != (addressOctet & subnetOctet)) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 
} 

Beispiel Nutzung:

var subnetAndMask = IpAddresses.GetSubnetAndMaskFromCidr("10.132.0.0/20"); 
bool result = IpAddresses.IsAddressOnSubnet(
    IPAddress.Parse("10.132.12.34"), 
    subnetAndMask.Item1, 
    subnetAndMask.Item2); 
0

ich hier spät zur Party bin, aber ein ähnliches Bedürfnis hatte, und zusammen ein schnelles Paket mach genau das.

https://www.nuget.org/packages/IpMatcher/

und Quelle:

https://github.com/jchristn/IpMatcher

Einfache Anwendung:

using IpMatcher; 

Matcher matcher = new Matcher(); 
matcher.Add("192.168.1.0", "255.255.255.0"); 
matcher.Add("192.168.2.0", "255.255.255.0"); 
matcher.Remove("192.168.2.0"); 
matcher.Exists("192.168.1.0", "255.255.255.0"); // true 
matcher.Match("192.168.1.34"); // true 
matcher.Match("10.10.10.10"); // false 
Verwandte Themen