2009-09-30 14 views

Odpowiedz

23

Spójrz na IP Address Calculations with C# na blogach MSDN. Zawiera metodę rozszerzenia (IsInSameSubnet), która powinna spełniać Twoje potrzeby, a także kilka innych dodatków.

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

Co z adresami IPv6? – ageroh

+0

@ageroh GitHub wydaje się mieć kilka bibliotek C#, które mogą obsługiwać adresy IPv6. IPNetwork, na przykład https://github.com/lduchosal/ipnetwork –

10

Obsługa bitów działa. Rzeczy IP na 32-bitową liczbę całkowitą bez znaku, to samo z adresem podsieci, w & maskowanego zarówno z 0xFFFFFFFF << (32-20) i porównać:

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

Lub, jeśli tak powszechne, podsieć jest podana jako liczba jak 255.255.240.0, po prostu rzeczy maskę do 32-bitowej liczby całkowitej zamiast przesunięcia. – erikkallen

+3

Znalazłem klasę System.Net.IPAddress przydatną do analizowania i dekompilowania adresów IP w bajtach. –

0

Rozwiązaniem jest konwersja adresu IP w bajtach korzystających System.Net.IPAddress i wykonywać bitowe porównań na oktety adres podsieci i maski.

Binary AND Operator & kopiuje bit do wyniku, jeśli istnieje w obu operandach.

Kod:

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

Specjalne podziękowania dla Спасибо! Прекрасное решение! Reference

+1

pamiętaj, że zepsuje się, jeśli zostanie wyświetlony z adresami IPv6 – Fowl

2

Ponieważ kod blogu MSDN opiera się na emisji i IPv6 nie ma go, nie wiem, czy działa z IPv6.

Skończyło się na tych metod (dzięki nu everest). Możesz pobrać podsieć i maskę z notacji CIDR ("1.2.3.4/5") i sprawdzić, czy adres jest w tej sieci, czy nie.

Działa to dla IPv4 i IPv6:

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

Przykład wykorzystania:

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

spóźnienie do partii tutaj, ale miał podobną potrzebę, i ułożyła szybki pakiet zrób dokładnie to.

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

i źródło:

https://github.com/jchristn/IpMatcher

Proste zastosowanie:

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 
Powiązane problemy