get {
Win32_IP_ADAPTER_INFO ai = Win32NetworkInterface2.GetAdapterInfoByIndex (mib4.Index);
// FIXME: should ipv6 DhcpServer be considered?
- return ai != null ? Win32FromUnicast ((int) ai.Index, addr.FirstUnicastAddress) : new UnicastIPAddressInformationCollection ();
+ return ai != null ? Win32FromUnicast (addr.FirstUnicastAddress) : new UnicastIPAddressInformationCollection ();
}
}
- static UnicastIPAddressInformationCollection Win32FromUnicast (int ifIndex, IntPtr ptr)
+ static UnicastIPAddressInformationCollection Win32FromUnicast (IntPtr ptr)
{
UnicastIPAddressInformationCollection c = new UnicastIPAddressInformationCollection ();
Win32_IP_ADAPTER_UNICAST_ADDRESS a;
for (IntPtr p = ptr; p != IntPtr.Zero; p = a.Next) {
a = (Win32_IP_ADAPTER_UNICAST_ADDRESS) Marshal.PtrToStructure (p, typeof (Win32_IP_ADAPTER_UNICAST_ADDRESS));
- c.InternalAdd (new Win32UnicastIPAddressInformation (ifIndex, a));
+ c.InternalAdd (new Win32UnicastIPAddressInformation (a));
}
return c;
}
using System;
using System.Runtime.InteropServices;
using System.Net.Sockets;
+using System.Diagnostics.Contracts;
namespace System.Net.NetworkInformation {
#if !MOBILE
class Win32UnicastIPAddressInformation : UnicastIPAddressInformation
{
- int if_index;
Win32_IP_ADAPTER_UNICAST_ADDRESS info;
+ IPAddress ipv4Mask;
- public Win32UnicastIPAddressInformation (int ifIndex, Win32_IP_ADAPTER_UNICAST_ADDRESS info)
+ public Win32UnicastIPAddressInformation (Win32_IP_ADAPTER_UNICAST_ADDRESS info)
{
- this.if_index = ifIndex;
this.info = info;
+ IPAddress ipAddress = info.Address.GetIPAddress ();
+ // IPv6 returns 0.0.0.0 for consistancy with XP
+ if (ipAddress.AddressFamily == AddressFamily.InterNetwork) {
+ ipv4Mask = PrefixLengthToSubnetMask (info.OnLinkPrefixLength, ipAddress.AddressFamily);
+ }
}
public override IPAddress Address {
get { return info.DadState; }
}
- public override IPAddress IPv4Mask {
+ public override IPAddress IPv4Mask{
get {
- Win32_IP_ADAPTER_INFO ai = Win32NetworkInterface2.GetAdapterInfoByIndex (if_index);
- if (ai == null)
- throw new Exception ("huh? " + if_index);
- if (this.Address == null)
- return null;
- string expected = this.Address.ToString ();
- unsafe {
- Win32_IP_ADDR_STRING p = ai.IpAddressList;
- while (true) {
- if (p.IpAddress == expected)
- return IPAddress.Parse (p.IpMask);
- if (p.Next == IntPtr.Zero)
- break;
- p = (Win32_IP_ADDR_STRING) Marshal.PtrToStructure (p.Next, typeof (Win32_IP_ADDR_STRING));
- }
-
- // Or whatever it should be...
- return null;
+ // The IPv6 equivilant was never available on XP, and we've kept this behavior for legacy reasons.
+ // For IPv6 use PrefixLength instead.
+ if (Address.AddressFamily != AddressFamily.InterNetwork) {
+ return IPAddress.Any;
}
+
+ return ipv4Mask;
}
}
public override SuffixOrigin SuffixOrigin {
get { return info.SuffixOrigin; }
}
+
+ // Convert a CIDR prefix length to a subnet mask "255.255.255.0" format
+ private static IPAddress PrefixLengthToSubnetMask (byte prefixLength, AddressFamily family) {
+ Contract.Requires ((0 <= prefixLength) && (prefixLength <= 126));
+ Contract.Requires ((family == AddressFamily.InterNetwork) || (family == AddressFamily.InterNetworkV6));
+
+ byte[] addressBytes;
+ if (family == AddressFamily.InterNetwork) {
+ addressBytes = new byte [4];
+ } else { // v6
+ addressBytes = new byte [16];
+ }
+
+ Contract.Assert (prefixLength < (addressBytes.Length * 8));
+
+ // Enable bits one at a time from left/high to right/low
+ for (int bit = 0; bit < prefixLength; bit++) {
+ addressBytes [bit / 8] |= (byte) (0x80 >> (bit % 8));
+ }
+
+ return new IPAddress (addressBytes);
+ }
}
#endif