2011-08-16 36 views
6

Tôi đã thấy rất nhiều C# examples tuyệt vời thể hiện cách chuyển đổi địa chỉ IPv4 được cung cấp trong ký hiệu CIDR (ví dụ: 192.168.0.1/25) thành các phạm vi có liên quan của chúng (192.168.0.1 - 192.168 .0.126). Chương trình của tôi cần để có thể làm điều này (để tính toán tất cả các địa chỉ trong mạng con cục bộ của tôi) nhưng tôi cũng muốn hỗ trợ IPv6.Tính tất cả các địa chỉ trong mạng con ... cho IPv6

Nếu chương trình C# của tôi có tất cả thông tin ipconfig điển hình của tôi (địa chỉ IPv4, mặt nạ mạng con, địa chỉ IPv6, địa chỉ v6 liên kết cục bộ, cổng mặc định) - làm cách nào để tạo danh sách tất cả địa chỉ IPv6 trong subnet địa phương của tôi và xuất chúng vào giao diện điều khiển?

+2

Bạn có lẽ cần phải suy nghĩ lại chức năng của mình. Theo thiết kế, hầu như mọi subnet bạn sẽ thấy ở IPv6 sẽ là/64, hoặc (2^64) -1 host lớn. – Joe

+2

Đúng vậy, tôi muốn tất cả 18,446,744,073,709,551,616 địa chỉ IP;) – DaveUK

+8

Và bạn sẽ làm gì với chúng? Ngay cả ở mức 10 triệu giây, bạn cần 58.000 năm để trải qua tất cả. – Joe

Trả lời

9

Bạn có thể sử dụng lớp eExNetworkLibrary.IP.IPAddressAnalysis từ eExNetworkLibrary.

Mã sau hoạt động với IPv4 và IPv6 (chỉ được kiểm tra).

 string strIn = "2001:DB8::/120"; 

     //Split the string in parts for address and prefix 
     string strAddress = strIn.Substring(0, strIn.IndexOf('/')); 
     string strPrefix = strIn.Substring(strIn.IndexOf('/') + 1); 

     int iPrefix = Int32.Parse(strPrefix); 
     IPAddress ipAddress = IPAddress.Parse(strAddress); 

     //Convert the prefix length to a valid SubnetMask 

     int iMaskLength = 32; 

     if(ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) 
     { 
      iMaskLength = 128; 
     } 

     BitArray btArray = new BitArray(iMaskLength); 
     for (int iC1 = 0; iC1 < iMaskLength; iC1++) 
     { 
      //Index calculation is a bit strange, since you have to make your mind about byte order. 
      int iIndex = (int)((iMaskLength - iC1 - 1)/8) * 8 + (iC1 % 8); 

      if (iC1 < (iMaskLength - iPrefix)) 
      { 
       btArray.Set(iIndex, false); 
      } 
      else 
      { 
       btArray.Set(iIndex, true); 
      } 
     } 

     byte[] bMaskData = new byte[iMaskLength/8]; 

     btArray.CopyTo(bMaskData, 0); 

     //Create subnetmask 
     Subnetmask smMask = new Subnetmask(bMaskData); 

     //Get the IP range 
     IPAddress ipaStart = IPAddressAnalysis.GetClasslessNetworkAddress(ipAddress, smMask); 
     IPAddress ipaEnd = IPAddressAnalysis.GetClasslessBroadcastAddress(ipAddress, smMask); 

     //Omit the following lines if your network range is large 
     IPAddress[] ipaRange = IPAddressAnalysis.GetIPRange(ipaStart, ipaEnd); 

     //Debug output 
     foreach (IPAddress ipa in ipaRange) 
     { 
      Console.WriteLine(ipa.ToString()); 
     } 

     Console.ReadLine(); 

Tôi không hoàn toàn chắc chắn nếu tôi đã làm việc chuyển đổi từ độ dài tiền tố để một mảng byte chứa subnet mask đúng, nhưng mã này sẽ cho bạn một điểm khởi đầu tốt.

Chỉnh sửa: Cập nhật phần uốn bit của mã. Có thể xấu xí, nhưng hoạt động cho ví dụ này. Tôi nghĩ rằng bạn sẽ có khả năng tìm kiếm một giải pháp tốt hơn, nếu bạn cần. Những BitArrays là một cơn đau ở cổ.

Lưu ý rằng việc tạo phạm vi mạng IPv6 có thể là tác vụ hết sức bộ nhớ/cpu nếu mạng lớn.

+0

Điều này gần như làm việc cho tôi. Cần thay đổi iIndex bằng (iMaskLength - iC1 - 1). Đây là mã trước khi chỉnh sửa, vì vậy tôi không chắc tại sao nó lại bị thay đổi. –

1

exNetworkLibrary là một công cụ tuyệt vời nhưng nếu bạn không thể sử dụng nó trong dự án của bạn sau đó bạn chỉ có thể muốn xem bài viết này:

http://www.codeproject.com/Articles/112020/IP-Address-Extension

Nó vạch ra cách ngụy trang địa chỉ được tính toán để sử dụng trong IPv4 .

Câu hỏi của bạn có liên quan đến IPv6 tôi thấy và Kể từ .Net 4.5 có phương thức IPAddress.MapToIPv6.

https://msdn.microsoft.com/en-us/library/system.net.ipaddress.maptoipv6(v=vs.110).aspx

Bạn có thể sử dụng rằng với sự kiểm tra trong bài viết để sản xuất mã này:

private static IPAddress empty = IPAddress.Parse("0.0.0.0"); 
    private static IPAddress intranetMask1 = IPAddress.Parse("10.255.255.255"); 
    private static IPAddress intranetMask2 = IPAddress.Parse("172.16.0.0"); 
    private static IPAddress intranetMask3 = IPAddress.Parse("172.31.255.255"); 
    private static IPAddress intranetMask4 = IPAddress.Parse("192.168.255.255"); 

    /// <summary> 
    /// Retuns true if the ip address is one of the following 
    /// IANA-reserved private IPv4 network ranges (from http://en.wikipedia.org/wiki/IP_address) 
    /// Start  End 
    /// 10.0.0.0  10.255.255.255 
    /// 172.16.0.0  172.31.255.255  
    /// 192.168.0.0 192.168.255.255 
    /// </summary> 
    /// <returns></returns> 
    public static bool IsOnIntranet(this IPAddress ipAddress) 
    { 
     if (empty.Equals(ipAddress)) 
     { 
      return false; 
     } 

     bool onIntranet = IPAddress.IsLoopback(ipAddress); 

     if (false == onIntranet) 
     { 
      //Handle IPv6 by getting the IPv4 Mapped Address. 
      if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6) 
      { 
       onIntranet = ipAddress.Equals(ipAddress.And(intranetMask1.MapToIPv6())); //10.255.255.255 
       onIntranet = onIntranet || ipAddress.Equals(ipAddress.And(intranetMask4.MapToIPv6())); ////192.168.255.255 

       onIntranet = onIntranet || (intranetMask2.Equals(ipAddress.And(intranetMask2.MapToIPv6())) 
        && ipAddress.Equals(ipAddress.And(intranetMask3.MapToIPv6()))); 
      } 
      else 
      { 
       onIntranet = ipAddress.Equals(ipAddress.And(intranetMask1)); //10.255.255.255 
       onIntranet = onIntranet || ipAddress.Equals(ipAddress.And(intranetMask4)); ////192.168.255.255 

       onIntranet = onIntranet || (intranetMask2.Equals(ipAddress.And(intranetMask2)) 
        && ipAddress.Equals(ipAddress.And(intranetMask3))); 
      } 


     } 

     return onIntranet; 
    } 

private static void CheckIPVersion(IPAddress ipAddress, IPAddress mask, out byte[] addressBytes, out byte[] maskBytes) 
    { 
     if (mask == null) 
     { 
      throw new ArgumentException(); 
     } 

     addressBytes = ipAddress.GetAddressBytes(); 
     maskBytes = mask.GetAddressBytes(); 

     if (addressBytes.Length != maskBytes.Length) 
     { 
      throw new ArgumentException("The address and mask don't use the same IP standard"); 
     } 
    } 

    public static IPAddress And(this IPAddress ipAddress, IPAddress mask) 
    { 
     byte[] addressBytes; 
     byte[] maskBytes; 
     CheckIPVersion(ipAddress, mask, out addressBytes, out maskBytes); 

     byte[] resultBytes = new byte[addressBytes.Length]; 
     for (int i = 0, e = addressBytes.Length; i < e; ++i) 
     { 
      resultBytes[i] = (byte)(addressBytes[i] & maskBytes[i]); 
     } 

     return new IPAddress(resultBytes); 
    } 
1

Tôi muốn giới thiệu việc sử dụng IPNetwork Thư viện https://github.com/lduchosal/ipnetwork. Kể từ phiên bản 2, nó cũng hỗ trợ IPv4 và IPv6.

IPv6

IPNetwork ipnetwork = IPNetwork.Parse("2001:0db8::/64"); 

    Console.WriteLine("Network : {0}", ipnetwork.Network); 
    Console.WriteLine("Netmask : {0}", ipnetwork.Netmask); 
    Console.WriteLine("Broadcast : {0}", ipnetwork.Broadcast); 
    Console.WriteLine("FirstUsable : {0}", ipnetwork.FirstUsable); 
    Console.WriteLine("LastUsable : {0}", ipnetwork.LastUsable); 
    Console.WriteLine("Usable : {0}", ipnetwork.Usable); 
    Console.WriteLine("Cidr : {0}", ipnetwork.Cidr); 

Output

Network : 2001:db8:: 
Netmask : ffff:ffff:ffff:ffff:: 
Broadcast : 
FirstUsable : 2001:db8:: 
LastUsable : 2001:db8::ffff:ffff:ffff:ffff 
Usable : 18446744073709551616 
Cidr : 64 

Enumeration

IPNetwork network = IPNetwork.Parse("::/124"); 
    IPNetworkCollection ips = IPNetwork.Subnet(network, 128); 

    foreach (IPNetwork ip in ips) { 
     Console.WriteLine("{0}", ip); 
    } 

Output

::/128 
::1/128 
::2/128 
::3/128 
::4/128 
::5/128 
::6/128 
::7/128 
::8/128 
::9/128 
::a/128 
::b/128 
::c/128 
::d/128 
::e/128 
::f/128 

Hãy vui vẻ!

+0

Đầu ra cho địa chỉ có thể sử dụng đầu tiên và cuối cùng không chính xác. IPv6, không giống như IPv4, có thể sử dụng tất cả các địa chỉ trong mạng con. Một mạng con IPv6 chuẩn là/64 (một số trường hợp đặc biệt sử dụng độ dài mặt nạ khác) và địa chỉ có thể sử dụng là từ ' :: 'tới' : ffff: ffff: ffff: ffff'.Không có đặt trước cho mạng con (' ::') và IPv6 không có khái niệm phát sóng, do đó không có địa chỉ quảng bá nào tồn tại tại ': ffff: ffff: ffff: ffff'. –

+1

Cảm ơn bạn đã chỉ ra điều này. Ví dụ đã được sửa. – LukeSkywalker

0

Tôi biết bài đăng này là 5yr cũ, nhưng với khả năng của Google, nó có thể cũng đã được cập nhật sáng nay. Vì vậy, tôi sẽ thêm một chút làm rõ từ quan điểm kỹ thuật mạng.

Tùy thuộc vào loại địa chỉ nào. Nếu bạn ngụ ý mọi địa chỉ trong phạm vi, thì cuộc thảo luận ở trên là chính xác. Nếu bạn ngụ ý các địa chỉ có thể được gán duy nhất cho một nút trong mạng con ("unicast"), hãy lưu ý rằng trong IPv6 (a) không có phát sóng, và (b) có phạm vi phát đa hướng đáng kể.

Về cơ bản: [subnet]: ff :: được dành riêng cho phát đa hướng. Nếu bạn không sử dụng/64 cho mặt nạ mạng con, bạn thực sự muốn cẩn thận vì nó đi ngược lại một giả định cơ bản là nhiều RFC liên quan đến IPv6. Có RFC khác ra rằng thận trọng chống lại bằng cách sử dụng tất cả các địa chỉ máy chủ 0 (nhưng tôi không biết một yêu cầu cụ thể để có hiệu lực đó).

Vì vậy, đối với/64 mạng phụ, điều đó có nghĩa là phạm vi địa chỉ unicast là :: 0: 0: 0: 1 đến :: feff: ffff: ffff: ffff.

Xem ở đây để thảo luận: http://www.tcpipguide.com/free/t_IPv6MulticastandAnycastAddressing.htm

weylin

+0

Địa chỉ máy chủ lưu trữ toàn bộ địa chỉ được dành riêng cho (các) bộ định tuyến mạng con, PHẢI trả lời trên địa chỉ này. Xem [RFC 4291 phần 2.6.1] (https://tools.ietf.org/html/rfc4291#section-2.6.1). Mặc dù yêu cầu này, các bộ định tuyến trên nhiều mạng không phản hồi địa chỉ này, nhưng nếu bạn cố gắng sử dụng địa chỉ này trên mạng nơi bộ định tuyến hoạt động đúng, bạn sẽ có một ngày tồi tệ. –

Các vấn đề liên quan