diff --git a/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs b/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs index b8d331ba9918c..66ab317a7d93d 100644 --- a/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs +++ b/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs @@ -123,9 +123,11 @@ public virtual void CopyTo(System.Net.NetworkInformation.IPAddressInformation[] public abstract partial class IPGlobalProperties { protected IPGlobalProperties() { } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract string DhcpScopeName { get; } public abstract string DomainName { get; } public abstract string HostName { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsWinsProxy { get; } public abstract System.Net.NetworkInformation.NetBiosNodeType NodeType { get; } public virtual System.IAsyncResult BeginGetUnicastAddresses(System.AsyncCallback? callback, object? state) { throw null; } @@ -136,16 +138,22 @@ protected IPGlobalProperties() { } public abstract System.Net.IPEndPoint[] GetActiveTcpListeners(); [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.IPEndPoint[] GetActiveUdpListeners(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IcmpV4Statistics GetIcmpV4Statistics(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IcmpV6Statistics GetIcmpV6Statistics(); [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] public static System.Net.NetworkInformation.IPGlobalProperties GetIPGlobalProperties() { throw null; } public abstract System.Net.NetworkInformation.IPGlobalStatistics GetIPv4GlobalStatistics(); public abstract System.Net.NetworkInformation.IPGlobalStatistics GetIPv6GlobalStatistics(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.TcpStatistics GetTcpIPv4Statistics(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.TcpStatistics GetTcpIPv6Statistics(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.UdpStatistics GetUdpIPv4Statistics(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.UdpStatistics GetUdpIPv6Statistics(); public virtual System.Net.NetworkInformation.UnicastIPAddressInformationCollection GetUnicastAddresses() { throw null; } public virtual System.Threading.Tasks.Task GetUnicastAddressesAsync() { throw null; } @@ -153,41 +161,69 @@ protected IPGlobalProperties() { } public abstract partial class IPGlobalStatistics { protected IPGlobalStatistics() { } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract int DefaultTtl { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool ForwardingEnabled { get; } public abstract int NumberOfInterfaces { get; } public abstract int NumberOfIPAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract int NumberOfRoutes { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long OutputPacketRequests { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long OutputPacketRoutingDiscards { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long OutputPacketsDiscarded { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long OutputPacketsWithNoRoute { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketFragmentFailures { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketReassembliesRequired { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketReassemblyFailures { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketReassemblyTimeout { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketsFragmented { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketsReassembled { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPackets { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsDelivered { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsDiscarded { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsForwarded { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithAddressErrors { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithHeadersErrors { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithUnknownProtocol { get; } } public abstract partial class IPInterfaceProperties { protected IPInterfaceProperties() { } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IPAddressInformationCollection AnycastAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IPAddressCollection DhcpServerAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IPAddressCollection DnsAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract string DnsSuffix { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.GatewayIPAddressInformationCollection GatewayAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsDnsEnabled { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsDynamicDnsEnabled { get; } public abstract System.Net.NetworkInformation.MulticastIPAddressInformationCollection MulticastAddresses { get; } public abstract System.Net.NetworkInformation.UnicastIPAddressInformationCollection UnicastAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IPAddressCollection WinsServersAddresses { get; } public abstract System.Net.NetworkInformation.IPv4InterfaceProperties GetIPv4Properties(); public abstract System.Net.NetworkInformation.IPv6InterfaceProperties GetIPv6Properties(); @@ -212,11 +248,16 @@ public abstract partial class IPv4InterfaceProperties { protected IPv4InterfaceProperties() { } public abstract int Index { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsAutomaticPrivateAddressingActive { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsAutomaticPrivateAddressingEnabled { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsDhcpEnabled { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsForwardingEnabled { get; } public abstract int Mtu { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool UsesWins { get; } } public abstract partial class IPv4InterfaceStatistics @@ -316,7 +357,9 @@ protected NetworkInterface() { } [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] public static System.Net.NetworkInformation.NetworkInterface[] GetAllNetworkInterfaces() { throw null; } public virtual System.Net.NetworkInformation.IPInterfaceProperties GetIPProperties() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public virtual System.Net.NetworkInformation.IPInterfaceStatistics GetIPStatistics() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public virtual System.Net.NetworkInformation.IPv4InterfaceStatistics GetIPv4Statistics() { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] diff --git a/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj b/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj index dc251f9c75dc4..b1c5a10f45a64 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj +++ b/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj @@ -1,7 +1,7 @@ true - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-Solaris;$(NetCoreAppCurrent) + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-Android;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-Solaris;$(NetCoreAppCurrent) enable @@ -118,8 +118,8 @@ - - + + @@ -144,6 +144,17 @@ + + + + + + + + + + + diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalProperties.cs new file mode 100644 index 0000000000000..4cebb2c55efa9 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalProperties.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPGlobalProperties : UnixIPGlobalProperties + { + public override TcpConnectionInformation[] GetActiveTcpConnections() => throw new PlatformNotSupportedException(); + + public override IPEndPoint[] GetActiveTcpListeners() => throw new PlatformNotSupportedException(); + + public override IPEndPoint[] GetActiveUdpListeners() => throw new PlatformNotSupportedException(); + + public override IcmpV4Statistics GetIcmpV4Statistics() => throw new PlatformNotSupportedException(); + + public override IcmpV6Statistics GetIcmpV6Statistics() => throw new PlatformNotSupportedException(); + + public override IPGlobalStatistics GetIPv4GlobalStatistics() + => new AndroidIPGlobalStatistics(ipv4: true); + + public override IPGlobalStatistics GetIPv6GlobalStatistics() + => new AndroidIPGlobalStatistics(ipv4: false); + + public override TcpStatistics GetTcpIPv4Statistics() => throw new PlatformNotSupportedException(); + + public override TcpStatistics GetTcpIPv6Statistics() => throw new PlatformNotSupportedException(); + + public override UdpStatistics GetUdpIPv4Statistics() => throw new PlatformNotSupportedException(); + + public override UdpStatistics GetUdpIPv6Statistics() => throw new PlatformNotSupportedException(); + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalStatistics.cs new file mode 100644 index 0000000000000..de57e068a1ddb --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalStatistics.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using System.Net.Sockets; + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPGlobalStatistics : IPGlobalStatistics + { + public AndroidIPGlobalStatistics(bool ipv4) + { + AndroidNetworkInterface[] networkInterfaces = NetworkInterfacePal.GetAndroidNetworkInterfaces(); + + foreach (var networkInterface in networkInterfaces) + { + var component = ipv4 ? NetworkInterfaceComponent.IPv4 : NetworkInterfaceComponent.IPv6; + if (networkInterface.Supports(component)) + { + NumberOfInterfaces++; + } + + foreach (UnixUnicastIPAddressInformation addressInformation in networkInterface.UnicastAddress) + { + bool isIPv4 = addressInformation.Address.AddressFamily == AddressFamily.InterNetwork; + if (isIPv4 == ipv4) + { + NumberOfIPAddresses++; + } + } + + if (networkInterface.MulticastAddresess != null) + { + foreach (IPAddress address in networkInterface.MulticastAddresess) + { + bool isIPv4 = address.AddressFamily == AddressFamily.InterNetwork; + if (isIPv4 == ipv4) + { + NumberOfIPAddresses++; + } + } + } + } + } + + public override int NumberOfInterfaces { get; } + public override int NumberOfIPAddresses { get; } + + public override int DefaultTtl => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override bool ForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override int NumberOfRoutes => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long OutputPacketRequests => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long OutputPacketRoutingDiscards => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long OutputPacketsDiscarded => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long OutputPacketsWithNoRoute => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketFragmentFailures => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketReassembliesRequired => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketReassemblyFailures => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketReassemblyTimeout => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketsFragmented => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketsReassembled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPackets => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsDelivered => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsDiscarded => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsForwarded => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsWithAddressErrors => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsWithHeadersErrors => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsWithUnknownProtocol => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPInterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPInterfaceProperties.cs new file mode 100644 index 0000000000000..cee58c47d8447 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPInterfaceProperties.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPInterfaceProperties : UnixIPInterfaceProperties + { + private readonly AndroidIPv4InterfaceProperties _ipv4Properties; + private readonly AndroidIPv6InterfaceProperties _ipv6Properties; + + public AndroidIPInterfaceProperties(AndroidNetworkInterface ani) + : base(ani, globalConfig: true) + { + _ipv4Properties = new AndroidIPv4InterfaceProperties(ani); + _ipv6Properties = new AndroidIPv6InterfaceProperties(ani); + } + + public override IPv4InterfaceProperties GetIPv4Properties() => _ipv4Properties; + public override IPv6InterfaceProperties GetIPv6Properties() => _ipv6Properties; + + public override bool IsDynamicDnsEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override IPAddressInformationCollection AnycastAddresses => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override GatewayIPAddressInformationCollection GatewayAddresses => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override IPAddressCollection DhcpServerAddresses => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override IPAddressCollection WinsServersAddresses => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs new file mode 100644 index 0000000000000..cc12cf7f35745 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPv4InterfaceProperties : UnixIPv4InterfaceProperties + { + public AndroidIPv4InterfaceProperties(AndroidNetworkInterface androidNetworkInterface) + : base(androidNetworkInterface) + { + Mtu = androidNetworkInterface._mtu; + } + + public override int Mtu { get; } + + public override bool IsAutomaticPrivateAddressingActive => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override bool IsAutomaticPrivateAddressingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override bool IsDhcpEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override bool IsForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override bool UsesWins => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv6InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv6InterfaceProperties.cs new file mode 100644 index 0000000000000..9a5f872231efd --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv6InterfaceProperties.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPv6InterfaceProperties : UnixIPv6InterfaceProperties + { + private readonly AndroidNetworkInterface _androidNetworkInterface; + + public AndroidIPv6InterfaceProperties(AndroidNetworkInterface androidNetworkInterface) + : base(androidNetworkInterface) + { + _androidNetworkInterface = androidNetworkInterface; + } + + public override int Mtu => _androidNetworkInterface._mtu; + + public override long GetScopeId(ScopeLevel scopeLevel) + { + if (scopeLevel == ScopeLevel.None || scopeLevel == ScopeLevel.Interface || + scopeLevel == ScopeLevel.Link || scopeLevel == ScopeLevel.Subnet) + { + return _androidNetworkInterface.Index; + } + + return 0; + } + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidNetworkInterface.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidNetworkInterface.cs new file mode 100644 index 0000000000000..dcf66895aea7b --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidNetworkInterface.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Net; + +namespace System.Net.NetworkInformation +{ + /// + /// Implements a NetworkInterface on Android. + /// + internal sealed class AndroidNetworkInterface : UnixNetworkInterface + { + internal readonly int _mtu; + private readonly AndroidIPInterfaceProperties _ipProperties; + + internal unsafe AndroidNetworkInterface(string name, Interop.Sys.NetworkInterfaceInfo *networkInterfaceInfo) + : base(name) + { + _index = networkInterfaceInfo->InterfaceIndex; + if (networkInterfaceInfo->NumAddressBytes > 0) + { + _physicalAddress = new PhysicalAddress(new ReadOnlySpan(networkInterfaceInfo->AddressBytes, networkInterfaceInfo->NumAddressBytes).ToArray()); + } + + _mtu = networkInterfaceInfo->Mtu; + _ipProperties = new AndroidIPInterfaceProperties(this); + + OperationalStatus = (OperationalStatus)networkInterfaceInfo->OperationalState; + Speed = networkInterfaceInfo->Speed; + SupportsMulticast = networkInterfaceInfo->SupportsMulticast != 0; + NetworkInterfaceType = (NetworkInterfaceType)networkInterfaceInfo->HardwareType; + } + + internal unsafe void AddAddress(Interop.Sys.IpAddressInfo *addressInfo) + { + var address = new IPAddress(new ReadOnlySpan(addressInfo->AddressBytes, addressInfo->NumAddressBytes)); + if (address.IsIPv6LinkLocal) + { + address.ScopeId = addressInfo->InterfaceIndex; + } + + AddAddress(address, addressInfo->PrefixLength); + } + + public override bool SupportsMulticast { get; } + public override IPInterfaceProperties GetIPProperties() => _ipProperties; + public override IPInterfaceStatistics GetIPStatistics() => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override IPv4InterfaceStatistics GetIPv4Statistics() => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override OperationalStatus OperationalStatus { get; } + public override NetworkInterfaceType NetworkInterfaceType { get; } + public override long Speed { get; } + public override bool IsReceiveOnly => false; + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs index d835ce2ecd65b..1371a47d3ed94 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs @@ -40,6 +40,7 @@ public static IPGlobalProperties GetIPGlobalProperties() /// /// Gets the Dynamic Host Configuration Protocol (DHCP) scope name. /// + [UnsupportedOSPlatform("android")] public abstract string DhcpScopeName { get; } /// @@ -55,6 +56,7 @@ public static IPGlobalProperties GetIPGlobalProperties() /// /// Gets a bool value that specifies whether the local computer is acting as a Windows Internet Name Service (WINS) proxy. /// + [UnsupportedOSPlatform("android")] public abstract bool IsWinsProxy { get; } /// @@ -72,25 +74,31 @@ public virtual UnicastIPAddressInformationCollection EndGetUnicastAddresses(IAsy throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); } + [UnsupportedOSPlatform("android")] public abstract TcpStatistics GetTcpIPv4Statistics(); + [UnsupportedOSPlatform("android")] public abstract TcpStatistics GetTcpIPv6Statistics(); /// /// Provides User Datagram Protocol (UDP) statistical data for the local computer. /// + [UnsupportedOSPlatform("android")] public abstract UdpStatistics GetUdpIPv4Statistics(); + [UnsupportedOSPlatform("android")] public abstract UdpStatistics GetUdpIPv6Statistics(); /// /// Provides Internet Control Message Protocol (ICMP) version 4 statistical data for the local computer. /// + [UnsupportedOSPlatform("android")] public abstract IcmpV4Statistics GetIcmpV4Statistics(); /// /// Provides Internet Control Message Protocol (ICMP) version 6 statistical data for the local computer. /// + [UnsupportedOSPlatform("android")] public abstract IcmpV6Statistics GetIcmpV6Statistics(); /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalPropertiesPal.Android.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalPropertiesPal.Android.cs new file mode 100644 index 0000000000000..33e09ece17c69 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalPropertiesPal.Android.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Net.NetworkInformation +{ + internal static class IPGlobalPropertiesPal + { + public static IPGlobalProperties GetIPGlobalProperties() + { + return new AndroidIPGlobalProperties(); + } + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalStatistics.cs index a8103f867e83d..04b9f14f1eab2 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalStatistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalStatistics.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -11,11 +13,13 @@ public abstract class IPGlobalStatistics /// /// Gets the default time-to-live (TTL) value for Internet Protocol (IP) packets. /// + [UnsupportedOSPlatform("android")] public abstract int DefaultTtl { get; } /// /// Gets a bool value that specifies whether Internet Protocol (IP) packet forwarding is enabled. /// + [UnsupportedOSPlatform("android")] public abstract bool ForwardingEnabled { get; } /// @@ -31,91 +35,109 @@ public abstract class IPGlobalStatistics /// /// Gets the number of outbound Internet Protocol (IP) packets. /// + [UnsupportedOSPlatform("android")] public abstract long OutputPacketRequests { get; } /// /// Gets the number of routes in the routing table that have been discarded. /// + [UnsupportedOSPlatform("android")] public abstract long OutputPacketRoutingDiscards { get; } /// /// Gets the number of transmitted Internet Protocol (IP) packets that have been discarded. /// + [UnsupportedOSPlatform("android")] public abstract long OutputPacketsDiscarded { get; } /// /// Gets the number of Internet Protocol (IP) packets for which the local computer could not determine a route to the destination address. /// + [UnsupportedOSPlatform("android")] public abstract long OutputPacketsWithNoRoute { get; } /// /// Gets the number of Internet Protocol (IP) packets that could not be fragmented. /// + [UnsupportedOSPlatform("android")] public abstract long PacketFragmentFailures { get; } /// /// Gets the number of Internet Protocol (IP) packets that required reassembly. /// + [UnsupportedOSPlatform("android")] public abstract long PacketReassembliesRequired { get; } /// /// Gets the number of Internet Protocol (IP) packets that were not successfully reassembled. /// + [UnsupportedOSPlatform("android")] public abstract long PacketReassemblyFailures { get; } /// /// Gets the maximum amount of time within which all fragments of an Internet Protocol (IP) packet must arrive. /// + [UnsupportedOSPlatform("android")] public abstract long PacketReassemblyTimeout { get; } /// /// Gets the number of Internet Protocol (IP) packets fragmented. /// + [UnsupportedOSPlatform("android")] public abstract long PacketsFragmented { get; } /// /// Gets the number of Internet Protocol (IP) packets reassembled. /// + [UnsupportedOSPlatform("android")] public abstract long PacketsReassembled { get; } /// /// Gets the number of Internet Protocol (IP) packets received. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPackets { get; } /// /// Gets the number of Internet Protocol(IP) packets received and delivered. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsDelivered { get; } /// /// Gets the number of Internet Protocol (IP) packets that have been received and discarded. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsDiscarded { get; } /// /// Gets the number of Internet Protocol (IP) packets forwarded. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsForwarded { get; } /// /// Gets the number of Internet Protocol (IP) packets with address errors that were received. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithAddressErrors { get; } /// /// Gets the number of Internet Protocol (IP) packets with header errors that were received. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithHeadersErrors { get; } /// /// Gets the number of Internet Protocol (IP) packets received on the local machine with an unknown protocol in the header. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithUnknownProtocol { get; } /// /// Gets the number of routes in the Internet Protocol (IP) routing table. /// + [UnsupportedOSPlatform("android")] public abstract int NumberOfRoutes { get; } } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs index e659598f5e4f4..863737ce18f6d 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -12,16 +14,19 @@ public abstract class IPInterfaceProperties /// /// Gets a bool value that indicates whether this interface is configured to send name resolution queries to a Domain Name System (DNS) server. /// + [UnsupportedOSPlatform("android")] public abstract bool IsDnsEnabled { get; } /// /// Gets the Domain Name System (DNS) suffix associated with this interface. /// + [UnsupportedOSPlatform("android")] public abstract string DnsSuffix { get; } /// /// Gets a bool value that indicates whether this interface is configured to automatically register its IP address information with the Domain Name System (DNS). /// + [UnsupportedOSPlatform("android")] public abstract bool IsDynamicDnsEnabled { get; } /// @@ -37,26 +42,31 @@ public abstract class IPInterfaceProperties /// /// The address identifies multiple computers. Packets sent to an anycast address are sent to one of the computers identified by the address. /// + [UnsupportedOSPlatform("android")] public abstract IPAddressInformationCollection AnycastAddresses { get; } /// /// The address is that of a Domain Name Service (DNS) server for the local computer. /// + [UnsupportedOSPlatform("android")] public abstract IPAddressCollection DnsAddresses { get; } /// /// Gets the network gateway addresses. /// + [UnsupportedOSPlatform("android")] public abstract GatewayIPAddressInformationCollection GatewayAddresses { get; } /// /// Gets the addresses for Dynamic Host Configuration Protocol (DHCP) servers. /// + [UnsupportedOSPlatform("android")] public abstract IPAddressCollection DhcpServerAddresses { get; } /// /// Gets the list of Wins Servers registered with this interface /// + [UnsupportedOSPlatform("android")] public abstract IPAddressCollection WinsServersAddresses { get; } /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs index 0f104e3fce8fc..9f9d0b1e3766d 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -11,21 +13,25 @@ public abstract class IPv4InterfaceProperties /// /// Gets a bool value that indicates whether an interface uses Windows Internet Name Service (WINS). /// + [UnsupportedOSPlatform("android")] public abstract bool UsesWins { get; } /// /// Gets a bool value that indicates whether the interface is configured to use a dynamic host configuration protocol (DHCP) server to obtain an IP address. /// + [UnsupportedOSPlatform("android")] public abstract bool IsDhcpEnabled { get; } /// /// Gets a bool value that indicates whether this interface has an automatic private IP addressing (APIPA) address. /// + [UnsupportedOSPlatform("android")] public abstract bool IsAutomaticPrivateAddressingActive { get; } /// /// Gets a bool value that indicates whether this interface has automatic private IP addressing (APIPA) enabled. /// + [UnsupportedOSPlatform("android")] public abstract bool IsAutomaticPrivateAddressingEnabled { get; } /// @@ -36,6 +42,7 @@ public abstract class IPv4InterfaceProperties /// /// Gets a bool value that indicates whether this interface can route packets. /// + [UnsupportedOSPlatform("android")] public abstract bool IsForwardingEnabled { get; } /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterface.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterface.cs index 94cb8fb0b9d81..24f02186c3dc3 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterface.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterface.cs @@ -70,6 +70,7 @@ public virtual IPInterfaceProperties GetIPProperties() /// Provides Internet Protocol (IP) statistical data for this network interface. /// /// The interface's IP statistics. + [UnsupportedOSPlatform("android")] public virtual IPInterfaceStatistics GetIPStatistics() { throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); @@ -81,6 +82,7 @@ public virtual IPInterfaceStatistics GetIPStatistics() /// Do not use this method, use GetIPStatistics instead. /// /// The interface's IP statistics. + [UnsupportedOSPlatform("android")] public virtual IPv4InterfaceStatistics GetIPv4Statistics() { throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterfacePal.Android.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterfacePal.Android.cs new file mode 100644 index 0000000000000..3b68b90e5a5fc --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterfacePal.Android.cs @@ -0,0 +1,110 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +namespace System.Net.NetworkInformation +{ + internal static class NetworkInterfacePal + { + /// Returns objects that describe the network interfaces on the local computer. + public static NetworkInterface[] GetAllNetworkInterfaces() => GetAndroidNetworkInterfaces(); + public static bool GetIsNetworkAvailable() => TransformNetworkInterfacess(IsSomeNetworkUp); + public static int IPv6LoopbackInterfaceIndex => LoopbackInterfaceIndex; + public static int LoopbackInterfaceIndex => TransformNetworkInterfacess(FindLoopbackInterfaceIndex); + + internal static unsafe AndroidNetworkInterface[] GetAndroidNetworkInterfaces() + => TransformNetworkInterfacess(ToAndroidNetworkInterfaceArray); + + private static unsafe T TransformNetworkInterfacess(Func transform) + { + int interfaceCount = 0; + int addressCount = 0; + Interop.Sys.NetworkInterfaceInfo *networkInterfaceInfo = null; + Interop.Sys.IpAddressInfo *addressInfo = null; + + if (Interop.Sys.GetNetworkInterfaces(&interfaceCount, &networkInterfaceInfo, &addressCount, &addressInfo) != 0) + { + string message = Interop.Sys.GetLastErrorInfo().GetErrorMessage(); + throw new NetworkInformationException(message); + } + + // the native implementation of Interop.Sys.GetNetworkInterfaces allocates one block of memory + // for both networkInterfaceInfo and addressInfo so we only need to call free once pointing at + // the start of the network itnerfaces list + var globalMemory = (IntPtr)networkInterfaceInfo; + + try + { + return transform(interfaceCount, (IntPtr)networkInterfaceInfo, addressCount, (IntPtr)addressInfo); + } + finally + { + Marshal.FreeHGlobal(globalMemory); + } + } + + private static unsafe AndroidNetworkInterface[] ToAndroidNetworkInterfaceArray(int interfaceCount, IntPtr networkInterfacesPtr, int addressCount, IntPtr addressPtr) + { + var networkInterfaces = new AndroidNetworkInterface[interfaceCount]; + + var networkInterfaceInfo = (Interop.Sys.NetworkInterfaceInfo*)networkInterfacesPtr; + for (int i = 0; i < interfaceCount; i++, networkInterfaceInfo++) + { + var name = Marshal.PtrToStringAnsi((IntPtr)networkInterfaceInfo->Name); + networkInterfaces[i] = new AndroidNetworkInterface(name!, networkInterfaceInfo); + } + + var addressInfo = (Interop.Sys.IpAddressInfo*)addressPtr; + for (int i = 0; i < addressCount; i++, addressInfo++) + { + // there is usually just a handful of few network interfaces on Android devices + // and this linear search does not have any impact on performance + foreach (var networkInterface in networkInterfaces) + { + if (networkInterface.Index == addressInfo->InterfaceIndex) + { + networkInterface.AddAddress(addressInfo); + break; + } + } + } + + return networkInterfaces; + } + + private static unsafe int FindLoopbackInterfaceIndex(int interfaceCount, IntPtr networkInterfacesPtr, int addressCount, IntPtr addressPtr) + { + var networkInterfaceInfo = (Interop.Sys.NetworkInterfaceInfo*)networkInterfacesPtr; + for (int i = 0; i < interfaceCount; i++, networkInterfaceInfo++) + { + if (networkInterfaceInfo->HardwareType == (int)NetworkInterfaceType.Loopback) + { + return networkInterfaceInfo->InterfaceIndex; + } + } + + throw new NetworkInformationException(SR.net_NoLoopback); + } + + private static unsafe bool IsSomeNetworkUp(int interfaceCount, IntPtr networkInterfacesPtr, int addressCount, IntPtr addressPtr) + { + var networkInterfaceInfo = (Interop.Sys.NetworkInterfaceInfo*)networkInterfacesPtr; + for (int i = 0; i < interfaceCount; i++, networkInterfaceInfo++) + { + if (networkInterfaceInfo->HardwareType == (int)NetworkInterfaceType.Loopback + || networkInterfaceInfo->HardwareType == (int)NetworkInterfaceType.Tunnel) + { + continue; + } + + if (networkInterfaceInfo->OperationalState == (int)OperationalStatus.Up) + { + return true; + } + } + + return false; + } + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixIPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixIPGlobalProperties.cs index cca949a317a6f..eafa42ff3fec1 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixIPGlobalProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixIPGlobalProperties.cs @@ -13,6 +13,7 @@ namespace System.Net.NetworkInformation internal abstract class UnixIPGlobalProperties : IPGlobalProperties { [UnsupportedOSPlatform("linux")] + [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("osx")] [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] @@ -26,6 +27,7 @@ internal abstract class UnixIPGlobalProperties : IPGlobalProperties public override string HostName { get { return HostInformation.HostName; } } [UnsupportedOSPlatform("linux")] + [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("osx")] [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixNetworkInterface.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixNetworkInterface.cs index d248c72b6930c..00c5b3a9a3028 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixNetworkInterface.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixNetworkInterface.cs @@ -60,7 +60,7 @@ public override bool Supports(NetworkInterfaceComponent networkInterfaceComponen public List UnicastAddress { get { return _unicastAddresses; } } /// - /// Returns a list of all Unicast addresses of the interface's IP Addresses. + /// Returns a list of all Multicast addresses of the interface's IP Addresses. /// public List? MulticastAddresess { get { return _multicastAddresses; } } diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPGlobalPropertiesTest.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPGlobalPropertiesTest.cs index ef127d5dd06ca..70804e19499e2 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPGlobalPropertiesTest.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPGlobalPropertiesTest.cs @@ -26,7 +26,7 @@ public IPGlobalPropertiesTest(ITestOutputHelper output) } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] + [SkipOnPlatform(TestPlatforms.Android, "Expected behavior is different on Android")] public void IPGlobalProperties_AccessAllMethods_NoErrors() { IPGlobalProperties gp = IPGlobalProperties.GetIPGlobalProperties(); @@ -50,9 +50,71 @@ public void IPGlobalProperties_AccessAllMethods_NoErrors() Assert.NotNull(gp.GetUdpIPv6Statistics()); } + [Fact] + [PlatformSpecific(TestPlatforms.Android)] + public void IPGlobalProperties_AccessAllMethods_NoErrors_Android() + { + IPGlobalProperties gp = IPGlobalProperties.GetIPGlobalProperties(); + + Assert.NotNull(gp.GetIPv4GlobalStatistics()); + Assert.NotNull(gp.GetIPv6GlobalStatistics()); + + Assert.Throws(() => gp.GetActiveTcpConnections()); + Assert.Throws(() => gp.GetActiveTcpListeners()); + Assert.Throws(() => gp.GetActiveUdpListeners()); + Assert.Throws(() => gp.GetIcmpV4Statistics()); + Assert.Throws(() => gp.GetIcmpV6Statistics()); + Assert.Throws(() => gp.GetTcpIPv4Statistics()); + Assert.Throws(() => gp.GetTcpIPv6Statistics()); + Assert.Throws(() => gp.GetUdpIPv4Statistics()); + Assert.Throws(() => gp.GetUdpIPv6Statistics()); + } + + [Theory] + [InlineData(4)] + [InlineData(6)] + [PlatformSpecific(TestPlatforms.Android)] + public void IPGlobalProperties_IPv4_IPv6_NoErrors_Android(int ipVersion) + { + IPGlobalProperties gp = IPGlobalProperties.GetIPGlobalProperties(); + IPGlobalStatistics statistics = ipVersion switch { + 4 => gp.GetIPv4GlobalStatistics(), + 6 => gp.GetIPv6GlobalStatistics(), + _ => throw new ArgumentOutOfRangeException() + }; + + _log.WriteLine($"- IPv{ipVersion} statistics: -"); + _log.WriteLine($"Number of interfaces: {statistics.NumberOfInterfaces}"); + _log.WriteLine($"Number of IP addresses: {statistics.NumberOfIPAddresses}"); + + Assert.InRange(statistics.NumberOfInterfaces, 1, int.MaxValue); + Assert.InRange(statistics.NumberOfIPAddresses, 1, int.MaxValue); + + Assert.Throws(() => statistics.DefaultTtl); + Assert.Throws(() => statistics.ForwardingEnabled); + Assert.Throws(() => statistics.OutputPacketRequests); + Assert.Throws(() => statistics.OutputPacketRoutingDiscards); + Assert.Throws(() => statistics.OutputPacketsDiscarded); + Assert.Throws(() => statistics.OutputPacketsWithNoRoute); + Assert.Throws(() => statistics.PacketFragmentFailures); + Assert.Throws(() => statistics.PacketReassembliesRequired); + Assert.Throws(() => statistics.PacketReassemblyFailures); + Assert.Throws(() => statistics.PacketReassemblyTimeout); + Assert.Throws(() => statistics.PacketsFragmented); + Assert.Throws(() => statistics.PacketsReassembled); + Assert.Throws(() => statistics.ReceivedPackets); + Assert.Throws(() => statistics.ReceivedPacketsDelivered); + Assert.Throws(() => statistics.ReceivedPacketsDiscarded); + Assert.Throws(() => statistics.ReceivedPacketsForwarded); + Assert.Throws(() => statistics.ReceivedPacketsWithAddressErrors); + Assert.Throws(() => statistics.ReceivedPacketsWithHeadersErrors); + Assert.Throws(() => statistics.ReceivedPacketsWithUnknownProtocol); + Assert.Throws(() => statistics.NumberOfRoutes); + } + [Theory] [MemberData(nameof(Loopbacks))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] + [SkipOnPlatform(TestPlatforms.Android, "Unsupported on Android")] public void IPGlobalProperties_TcpListeners_Succeed(IPAddress address) { using (var server = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) @@ -78,9 +140,8 @@ public void IPGlobalProperties_TcpListeners_Succeed(IPAddress address) [Theory] [ActiveIssue("https://github.com/dotnet/runtime/issues/34690", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [PlatformSpecific(~(TestPlatforms.iOS | TestPlatforms.tvOS))] + [PlatformSpecific(~(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.Android))] [MemberData(nameof(Loopbacks))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] public async Task IPGlobalProperties_TcpActiveConnections_Succeed(IPAddress address) { using (var server = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) @@ -110,7 +171,7 @@ public async Task IPGlobalProperties_TcpActiveConnections_Succeed(IPAddress addr } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] + [SkipOnPlatform(TestPlatforms.Android, "Unsupported on Android")] public void IPGlobalProperties_TcpActiveConnections_NotListening() { TcpConnectionInformation[] tcpCconnections = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections(); diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPInterfacePropertiesTest_Android.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPInterfacePropertiesTest_Android.cs new file mode 100644 index 0000000000000..61e57c854aa47 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPInterfacePropertiesTest_Android.cs @@ -0,0 +1,221 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using System.Net.Http.Functional.Tests; +using System.Net.Sockets; +using System.Net.Test.Common; +using System.Threading.Tasks; + +using Xunit; +using Xunit.Abstractions; + +namespace System.Net.NetworkInformation.Tests +{ + [PlatformSpecific(TestPlatforms.Android)] + public class IPInterfacePropertiesTest_Android + { + private readonly ITestOutputHelper _log; + + public IPInterfacePropertiesTest_Android(ITestOutputHelper output) + { + _log = output; + } + + [Fact] + public async Task IPInfoTest_AccessAllProperties_NoErrors() + { + await Task.Run(() => + { + foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) + { + _log.WriteLine("Nic: " + nic.Name); + _log.WriteLine("- Speed:" + nic.Speed); + Assert.Equal(-1, nic.Speed); + _log.WriteLine("- Supports IPv4: " + nic.Supports(NetworkInterfaceComponent.IPv4)); + _log.WriteLine("- Supports IPv6: " + nic.Supports(NetworkInterfaceComponent.IPv6)); + Assert.False(nic.IsReceiveOnly); + + IPInterfaceProperties ipProperties = nic.GetIPProperties(); + + Assert.NotNull(ipProperties); + + Assert.Throws(() => ipProperties.AnycastAddresses); + Assert.Throws(() => ipProperties.DhcpServerAddresses); + Assert.Throws(() => ipProperties.DnsAddresses); + Assert.Throws(() => ipProperties.DnsSuffix); + Assert.Throws(() => ipProperties.GatewayAddresses); + Assert.Throws(() => ipProperties.IsDnsEnabled); + Assert.Throws(() => ipProperties.IsDynamicDnsEnabled); + + Assert.NotNull(ipProperties.MulticastAddresses); + _log.WriteLine("- Multicast Addresses: " + ipProperties.MulticastAddresses.Count); + foreach (IPAddressInformation multi in ipProperties.MulticastAddresses) + { + _log.WriteLine("-- " + multi.Address.ToString()); + Assert.Throws(() => multi.IsDnsEligible); + Assert.Throws(() => multi.IsTransient); + } + + Assert.NotNull(ipProperties.UnicastAddresses); + _log.WriteLine("- Unicast Addresses: " + ipProperties.UnicastAddresses.Count); + foreach (UnicastIPAddressInformation uni in ipProperties.UnicastAddresses) + { + _log.WriteLine("-- " + uni.Address.ToString()); + Assert.Throws(() => uni.AddressPreferredLifetime); + Assert.Throws(() => uni.AddressValidLifetime); + Assert.Throws(() => uni.DhcpLeaseLifetime); + Assert.Throws(() => uni.DuplicateAddressDetectionState); + + Assert.NotNull(uni.IPv4Mask); + _log.WriteLine("--- IPv4 Mask: " + uni.IPv4Mask); + Assert.Throws(() => uni.IsDnsEligible); + Assert.Throws(() => uni.IsTransient); + Assert.Throws(() => uni.PrefixOrigin); + Assert.Throws(() => uni.SuffixOrigin); + + // Prefix Length + _log.WriteLine("--- PrefixLength: " + uni.PrefixLength); + Assert.True(uni.PrefixLength > 0); + Assert.True((uni.Address.AddressFamily == AddressFamily.InterNetwork ? 33 : 129) > uni.PrefixLength); + } + + Assert.Throws(() => ipProperties.WinsServersAddresses); + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + + [Fact] + public async Task IPInfoTest_AccessAllIPv4Properties_NoErrors() + { + await Task.Run(() => + { + foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) + { + _log.WriteLine("Nic: " + nic.Name); + + IPInterfaceProperties ipProperties = nic.GetIPProperties(); + + _log.WriteLine("IPv4 Properties:"); + + IPv4InterfaceProperties ipv4Properties = ipProperties.GetIPv4Properties(); + + _log.WriteLine("Index: " + ipv4Properties.Index); + Assert.Throws(() => ipv4Properties.IsAutomaticPrivateAddressingActive); + Assert.Throws(() => ipv4Properties.IsAutomaticPrivateAddressingEnabled); + Assert.Throws(() => ipv4Properties.IsDhcpEnabled); + Assert.Throws(() => ipv4Properties.IsForwardingEnabled); + _log.WriteLine("Mtu: " + ipv4Properties.Mtu); + Assert.Throws(() => ipv4Properties.UsesWins); + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + + [Fact] + public async Task IPInfoTest_AccessAllIPv6Properties_NoErrors() + { + await Task.Run(() => + { + foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) + { + _log.WriteLine("Nic: " + nic.Name); + + IPInterfaceProperties ipProperties = nic.GetIPProperties(); + + _log.WriteLine("IPv6 Properties:"); + + IPv6InterfaceProperties ipv6Properties = ipProperties.GetIPv6Properties(); + + if (ipv6Properties == null) + { + _log.WriteLine("IPv6Properties is null"); + continue; + } + + _log.WriteLine("Index: " + ipv6Properties.Index); + _log.WriteLine("Mtu: " + ipv6Properties.Mtu); + _log.WriteLine("Scope: " + ipv6Properties.GetScopeId(ScopeLevel.Link)); + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + + [Fact] + [Trait("IPv6", "true")] + public async Task IPv6ScopeId_AccessAllValues_Success() + { + await Task.Run(() => + { + Assert.True(Capability.IPv6Support()); + + foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) + { + _log.WriteLine("Nic: " + nic.Name); + + if (!nic.Supports(NetworkInterfaceComponent.IPv6)) + { + continue; + } + + IPInterfaceProperties ipProperties = nic.GetIPProperties(); + + IPv6InterfaceProperties ipv6Properties = ipProperties.GetIPv6Properties(); + + Array values = Enum.GetValues(typeof(ScopeLevel)); + foreach (ScopeLevel level in values) + { + _log.WriteLine("-- Level: " + level + "; " + ipv6Properties.GetScopeId(level)); + } + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + + [Fact] + [Trait("IPv4", "true")] + public async Task IPInfoTest_IPv4Loopback_ProperAddress() + { + await Task.Run(() => + { + Assert.True(Capability.IPv4Support()); + + _log.WriteLine("Loopback IPv4 index: " + NetworkInterface.LoopbackInterfaceIndex); + + NetworkInterface loopback = NetworkInterface.GetAllNetworkInterfaces().First(ni => ni.Name == "lo"); + Assert.NotNull(loopback); + + foreach (UnicastIPAddressInformation unicast in loopback.GetIPProperties().UnicastAddresses) + { + if (unicast.Address.Equals(IPAddress.Loopback)) + { + Assert.Equal(IPAddress.Parse("255.0.0.0"), unicast.IPv4Mask); + Assert.Equal(8, unicast.PrefixLength); + break; + } + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + + [Fact] + [Trait("IPv6", "true")] + public async Task IPInfoTest_IPv6Loopback_ProperAddress() + { + await Task.Run(() => + { + Assert.True(Capability.IPv6Support()); + + _log.WriteLine("Loopback IPv6 index: " + NetworkInterface.IPv6LoopbackInterfaceIndex); + + NetworkInterface loopback = NetworkInterface.GetAllNetworkInterfaces().First(ni => ni.Name == "lo"); + Assert.NotNull(loopback); + + foreach (UnicastIPAddressInformation unicast in loopback.GetIPProperties().UnicastAddresses) + { + if (unicast.Address.Equals(IPAddress.IPv6Loopback)) + { + Assert.Equal(128, unicast.PrefixLength); + break; + } + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + } +} diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceIPv4Statistics.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceIPv4Statistics.cs index 52aceb0d3f9c1..9b73374e99b26 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceIPv4Statistics.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceIPv4Statistics.cs @@ -69,6 +69,17 @@ public void BasicTest_GetIPv4InterfaceStatistics_Success_Linux() } } + [Fact] + [PlatformSpecific(TestPlatforms.Android)] // This API is not supported on Android + public void BasicTest_GetIPv4InterfaceStatistics_NotSupported_Android() + { + // This API is not actually IPv4 specific. + foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) + { + Assert.Throws(() => nic.GetIPv4Statistics()); + } + } + [Fact] [PlatformSpecific(TestPlatforms.OSX)] // Some APIs are not supported on OSX public void BasicTest_GetIPv4InterfaceStatistics_Success_OSX()