/// /// Provides support for ip configuation information and statistics. /// /// namespace System.Net.NetworkInformation { using System.Net; using System.Net.Sockets; using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Diagnostics.Contracts; internal class SystemNetworkInterface:NetworkInterface { //common properties private string name; private string id; private string description; private byte[] physicalAddress; private uint addressLength; private NetworkInterfaceType type; private OperationalStatus operStatus; private long speed; //Unfortunately, any interface can //have two completely different valid indexes for ipv4 and ipv6 private uint index = 0; private uint ipv6Index = 0; private AdapterFlags adapterFlags; private SystemIPInterfaceProperties interfaceProperties = null; internal static int InternalLoopbackInterfaceIndex { get { return GetBestInterfaceForAddress(IPAddress.Loopback); } } internal static int InternalIPv6LoopbackInterfaceIndex { get { return GetBestInterfaceForAddress(IPAddress.IPv6Loopback); } } private static int GetBestInterfaceForAddress(IPAddress addr) { int index; SocketAddress address = new SocketAddress(addr); int error = (int)UnsafeNetInfoNativeMethods.GetBestInterfaceEx(address.m_Buffer, out index); if (error != 0) { throw new NetworkInformationException(error); } return index; } internal static bool InternalGetIsNetworkAvailable(){ try { NetworkInterface[] networkInterfaces = GetNetworkInterfaces(); foreach (NetworkInterface netInterface in networkInterfaces) { if (netInterface.OperationalStatus == OperationalStatus.Up && netInterface.NetworkInterfaceType != NetworkInterfaceType.Tunnel && netInterface.NetworkInterfaceType != NetworkInterfaceType.Loopback){ return true; } } } catch (NetworkInformationException nie) { if (Logging.On) Logging.Exception(Logging.Web, "SystemNetworkInterface", "InternalGetIsNetworkAvailable", nie); } return false; } // Vista+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", Justification = "DangerousGetHandle is required for marshaling")] internal static NetworkInterface[] GetNetworkInterfaces() { Contract.Ensures(Contract.Result() != null); AddressFamily family = AddressFamily.Unspecified; uint bufferSize = 0; SafeLocalFree buffer = null; FixedInfo fixedInfo = SystemIPGlobalProperties.GetFixedInfo(); List interfaceList = new List(); GetAdaptersAddressesFlags flags = GetAdaptersAddressesFlags.IncludeGateways | GetAdaptersAddressesFlags.IncludeWins; // Figure out the right buffer size for the adapter information uint result = UnsafeNetInfoNativeMethods.GetAdaptersAddresses( family, (uint)flags, IntPtr.Zero, SafeLocalFree.Zero, ref bufferSize); while (result == IpHelperErrors.ErrorBufferOverflow) { try { // Allocate the buffer and get the adapter info buffer = SafeLocalFree.LocalAlloc((int)bufferSize); result = UnsafeNetInfoNativeMethods.GetAdaptersAddresses( family, (uint)flags, IntPtr.Zero, buffer, ref bufferSize); // If succeeded, we're going to add each new interface if (result == IpHelperErrors.Success) { // Linked list of interfaces IntPtr ptr = buffer.DangerousGetHandle(); while (ptr != IntPtr.Zero) { // Traverse the list, marshal in the native structures, and create new NetworkInterfaces IpAdapterAddresses adapterAddresses = (IpAdapterAddresses)Marshal.PtrToStructure(ptr, typeof(IpAdapterAddresses)); interfaceList.Add(new SystemNetworkInterface(fixedInfo, adapterAddresses)); ptr = adapterAddresses.next; } } } finally { if (buffer != null) { buffer.Close(); } buffer = null; } } // if we don't have any interfaces detected, return empty. if (result == IpHelperErrors.ErrorNoData || result == IpHelperErrors.ErrorInvalidParameter) { return new SystemNetworkInterface[0]; } // Otherwise we throw on an error if (result != IpHelperErrors.Success) { throw new NetworkInformationException((int)result); } return interfaceList.ToArray(); } // Vista+ internal SystemNetworkInterface(FixedInfo fixedInfo, IpAdapterAddresses ipAdapterAddresses) { //store the common api information id = ipAdapterAddresses.AdapterName; name = ipAdapterAddresses.friendlyName; description = ipAdapterAddresses.description; index = ipAdapterAddresses.index; physicalAddress = ipAdapterAddresses.address; addressLength = ipAdapterAddresses.addressLength; type = ipAdapterAddresses.type; operStatus = ipAdapterAddresses.operStatus; speed = (long)ipAdapterAddresses.receiveLinkSpeed; //api specific info ipv6Index = ipAdapterAddresses.ipv6Index; adapterFlags = ipAdapterAddresses.flags; interfaceProperties = new SystemIPInterfaceProperties(fixedInfo, ipAdapterAddresses); } /// Basic Properties public override string Id{get {return id;}} public override string Name{get {return name;}} public override string Description{get {return description;}} public override PhysicalAddress GetPhysicalAddress(){ byte[] newAddr = new byte[addressLength]; Array.Copy(physicalAddress,newAddr,addressLength); return new PhysicalAddress(newAddr); } public override NetworkInterfaceType NetworkInterfaceType{get {return type;}} public override IPInterfaceProperties GetIPProperties(){ return interfaceProperties; } /// Despite the naming, the results are not IPv4 specific. /// Do not use this method, use GetIPStatistics instead. /// public override IPv4InterfaceStatistics GetIPv4Statistics(){ return new SystemIPv4InterfaceStatistics(index); } public override IPInterfaceStatistics GetIPStatistics() { return new SystemIPInterfaceStatistics(index); } public override bool Supports(NetworkInterfaceComponent networkInterfaceComponent){ if (networkInterfaceComponent == NetworkInterfaceComponent.IPv6 && ((adapterFlags & AdapterFlags.IPv6Enabled) != 0)) { return true; } if (networkInterfaceComponent == NetworkInterfaceComponent.IPv4 && ((adapterFlags & AdapterFlags.IPv4Enabled) != 0)) { return true; } return false; } //We cache this to be consistent across all platforms public override OperationalStatus OperationalStatus{ get { return operStatus; } } public override long Speed{ get { return speed; } } public override bool IsReceiveOnly { get { return ((adapterFlags & AdapterFlags.ReceiveOnly) > 0); } } /// The interface doesn't allow multicast. public override bool SupportsMulticast { get { return ((adapterFlags & AdapterFlags.NoMulticast) == 0); } } } }