From 6f744721e66a0e2e9de469aee458435ded435b56 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Tue, 11 Jan 2022 16:39:11 +0100 Subject: [PATCH 01/10] Update tests --- .../FunctionalTests/IPGlobalPropertiesTest.cs | 71 +++++- .../IPInterfacePropertiesTest_Android.cs | 221 ++++++++++++++++++ .../NetworkInterfaceBasicTest.cs | 2 +- .../NetworkInterfaceIPv4Statistics.cs | 11 + 4 files changed, 299 insertions(+), 6 deletions(-) create mode 100644 src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPInterfacePropertiesTest_Android.cs 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/NetworkInterfaceBasicTest.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs index c022f74b2c234..3477f0ec72da9 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs @@ -56,7 +56,7 @@ public void BasicTest_AccessInstanceProperties_NoExceptions() } [Fact] - [PlatformSpecific(TestPlatforms.Linux|TestPlatforms.Android)] // Some APIs are not supported on Linux and Android + [PlatformSpecific(TestPlatforms.Linux|TestPlatforms.Android)] // Some APIs are not supported on Linux public void BasicTest_AccessInstanceProperties_NoExceptions_Linux() { foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) 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() From 27bc12362386a8a79d08b7448e1834b287fa51ff Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Tue, 11 Jan 2022 16:41:08 +0100 Subject: [PATCH 02/10] Add android specific implementation --- .../src/System.Net.NetworkInformation.csproj | 18 ++- .../AndroidIPGlobalProperties.cs | 32 +++++ .../AndroidIPGlobalStatistics.cs | 96 +++++++++++++++ .../AndroidIPInterfaceProperties.cs | 35 ++++++ .../AndroidIPv4InterfaceProperties.cs | 36 ++++++ .../AndroidIPv6InterfaceProperties.cs | 31 +++++ .../AndroidNetworkInterface.cs | 111 ++++++++++++++++++ .../IPGlobalPropertiesPal.Android.cs | 13 ++ .../NetworkInterfacePal.Android.cs | 51 ++++++++ 9 files changed, 420 insertions(+), 3 deletions(-) create mode 100644 src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalProperties.cs create mode 100644 src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalStatistics.cs create mode 100644 src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPInterfaceProperties.cs create mode 100644 src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs create mode 100644 src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv6InterfaceProperties.cs create mode 100644 src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidNetworkInterface.cs create mode 100644 src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalPropertiesPal.Android.cs create mode 100644 src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterfacePal.Android.cs 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..07da04596a7fc 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,18 @@ + + + + + + + + + + + + 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..ca2258824ab9a --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalStatistics.cs @@ -0,0 +1,96 @@ +// 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) + { + NetworkInterface[] networkInterfaces = AndroidNetworkInterface.GetAndroidNetworkInterfaces(); + + foreach (NetworkInterface networkInterface in networkInterfaces) + { + var component = ipv4 ? NetworkInterfaceComponent.IPv4 : NetworkInterfaceComponent.IPv6; + if (networkInterface.Supports(component)) + { + NumberOfInterfaces++; + } + + if (networkInterface is AndroidNetworkInterface androidNetworkInterface) + { + foreach (UnixUnicastIPAddressInformation addressInformation in androidNetworkInterface.UnicastAddress) + { + bool isIPv4 = addressInformation.Address.AddressFamily == AddressFamily.InterNetwork; + if (isIPv4 == ipv4) + { + NumberOfIPAddresses++; + } + } + + if (androidNetworkInterface.MulticastAddresess != null) + { + foreach (IPAddress address in androidNetworkInterface.MulticastAddresess) + { + bool isIPv4 = address.AddressFamily == AddressFamily.InterNetwork; + if (isIPv4 == ipv4) + { + NumberOfIPAddresses++; + } + } + } + } + } + } + + public override int DefaultTtl => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + + public override bool ForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + + public override int NumberOfInterfaces { get; } + + public override int NumberOfIPAddresses { get; } + + 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..bfc243c518e49 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPInterfaceProperties.cs @@ -0,0 +1,35 @@ +// 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 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); + + public override IPv4InterfaceProperties GetIPv4Properties() => _ipv4Properties; + + public override IPv6InterfaceProperties GetIPv6Properties() => _ipv6Properties; + } +} 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..e0031d9bf6147 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs @@ -0,0 +1,36 @@ +// 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; +using System.Runtime.Versioning; + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPv4InterfaceProperties : UnixIPv4InterfaceProperties + { + private readonly AndroidNetworkInterface _androidNetworkInterface; + + public AndroidIPv4InterfaceProperties(AndroidNetworkInterface androidNetworkInterface) + : base(androidNetworkInterface) + { + _androidNetworkInterface = androidNetworkInterface; + } + + public override int Mtu => _androidNetworkInterface._mtu; + + [UnsupportedOSPlatform("android")] + public override bool IsAutomaticPrivateAddressingActive => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + + [UnsupportedOSPlatform("android")] + public override bool IsAutomaticPrivateAddressingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + + [UnsupportedOSPlatform("android")] + public override bool IsDhcpEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + + [UnsupportedOSPlatform("android")] + public override bool IsForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + + [UnsupportedOSPlatform("android")] + 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..b0bff8dd4b995 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidNetworkInterface.cs @@ -0,0 +1,111 @@ +// 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; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using System.Text; +using System.Net; + +namespace System.Net.NetworkInformation +{ + /// + /// Implements a NetworkInterface on Android. + /// + internal sealed class AndroidNetworkInterface : UnixNetworkInterface + { + private OperationalStatus _operationalStatus; + private bool _supportsMulticast; + private long _speed; + internal int _mtu; + private NetworkInterfaceType _interfaceType = NetworkInterfaceType.Unknown; + private readonly AndroidIPInterfaceProperties _ipProperties; + + internal AndroidNetworkInterface(string name, int index) : base(name) + { + _index = index; + _ipProperties = new AndroidIPInterfaceProperties(this); + } + + public static unsafe NetworkInterface[] GetAndroidNetworkInterfaces() + { + int interfaceCount=0; + int addressCount=0; + Interop.Sys.NetworkInterfaceInfo * nii = null; + Interop.Sys.IpAddressInfo * ai = null; + IntPtr globalMemory = (IntPtr)null; + + if (Interop.Sys.GetNetworkInterfaces(&interfaceCount, &nii, &addressCount, &ai) != 0) + { + string message = Interop.Sys.GetLastErrorInfo().GetErrorMessage(); + throw new NetworkInformationException(message); + } + + globalMemory = (IntPtr)nii; + try + { + NetworkInterface[] interfaces = new NetworkInterface[interfaceCount]; + Dictionary interfacesByIndex = new Dictionary(interfaceCount); + + for (int i = 0; i < interfaceCount; i++) + { + var ani = new AndroidNetworkInterface(Marshal.PtrToStringAnsi((IntPtr)nii->Name)!, nii->InterfaceIndex); + ani._interfaceType = (NetworkInterfaceType)nii->HardwareType; + ani._operationalStatus = (OperationalStatus)nii->OperationalState; + ani._mtu = nii->Mtu; + ani._speed = nii->Speed; + ani._supportsMulticast = nii->SupportsMulticast != 0; + + if (nii->NumAddressBytes > 0) + { + ani._physicalAddress = new PhysicalAddress(new ReadOnlySpan(nii->AddressBytes, nii->NumAddressBytes).ToArray()); + } + + interfaces[i] = ani; + interfacesByIndex.Add(nii->InterfaceIndex, ani); + nii++; + } + + while (addressCount != 0) + { + var address = new IPAddress(new ReadOnlySpan(ai->AddressBytes, ai->NumAddressBytes)); + if (address.IsIPv6LinkLocal) + { + address.ScopeId = ai->InterfaceIndex; + } + + if (interfacesByIndex.TryGetValue(ai->InterfaceIndex, out AndroidNetworkInterface? ani)) + { + ani.AddAddress(address, ai->PrefixLength); + } + + ai++; + addressCount--; + } + + return interfaces; + } + finally + { + Marshal.FreeHGlobal(globalMemory); + } + } + + public override bool SupportsMulticast => _supportsMulticast; + + 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 { return _operationalStatus; } } + + public override NetworkInterfaceType NetworkInterfaceType { get { return _interfaceType; } } + + public override long Speed => _speed; + + public override bool IsReceiveOnly { get { return false; } } + } +} 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/NetworkInterfacePal.Android.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterfacePal.Android.cs new file mode 100644 index 0000000000000..98663830fe147 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterfacePal.Android.cs @@ -0,0 +1,51 @@ +// 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 NetworkInterfacePal + { + /// Returns objects that describe the network interfaces on the local computer. + public static NetworkInterface[] GetAllNetworkInterfaces() + { + return AndroidNetworkInterface.GetAndroidNetworkInterfaces(); + } + + public static bool GetIsNetworkAvailable() + { + foreach (var ni in GetAllNetworkInterfaces()) + { + if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback + || ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel) + { + continue; + } + if (ni.OperationalStatus == OperationalStatus.Up) + { + return true; + } + } + + return false; + } + + public static int IPv6LoopbackInterfaceIndex { get { return LoopbackInterfaceIndex; } } + + public static int LoopbackInterfaceIndex + { + get + { + NetworkInterface[] interfaces = AndroidNetworkInterface.GetAndroidNetworkInterfaces(); + for (int i = 0; i < interfaces.Length; i++) + { + if (interfaces[i].NetworkInterfaceType == NetworkInterfaceType.Loopback) + { + return ((UnixNetworkInterface)interfaces[i]).Index; + } + } + + throw new NetworkInformationException(SR.net_NoLoopback); + } + } + } +} From 6b5e5f3d82f75a4c23cdaf8f4a95eaa8282c8ac5 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Tue, 11 Jan 2022 16:42:16 +0100 Subject: [PATCH 03/10] Add UnsupportedOSPlatform attributes --- .../ref/System.Net.NetworkInformation.cs | 43 +++++++++++++++++++ .../NetworkInformation/IPGlobalProperties.cs | 8 ++++ .../NetworkInformation/IPGlobalStatistics.cs | 22 ++++++++++ .../IPInterfaceProperties.cs | 10 +++++ .../IPv4InterfaceProperties.cs | 7 +++ .../NetworkInformation/NetworkInterface.cs | 2 + .../UnixIPGlobalProperties.cs | 2 + 7 files changed, 94 insertions(+) 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/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/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/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")] From 5b07b5348aa7afb5d7731e90725414349a47554a Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Tue, 11 Jan 2022 16:42:31 +0100 Subject: [PATCH 04/10] Fix typo --- .../src/System/Net/NetworkInformation/UnixNetworkInterface.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; } } From 11b1ea5b9d2b706dffbbe539a9713d047cdebc05 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Tue, 11 Jan 2022 18:55:30 +0100 Subject: [PATCH 05/10] Remove unnecessary file reference --- .../src/System.Net.NetworkInformation.csproj | 1 - 1 file changed, 1 deletion(-) 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 07da04596a7fc..b1c5a10f45a64 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj +++ b/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj @@ -146,7 +146,6 @@ - From f9203dae78f560dc16654edbc3098bd043ccc4eb Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Wed, 12 Jan 2022 15:31:18 +0100 Subject: [PATCH 06/10] Clean-up code --- .../AndroidIPGlobalStatistics.cs | 53 +++------ .../AndroidIPv4InterfaceProperties.cs | 16 +-- .../AndroidNetworkInterface.cs | 107 ++++-------------- .../NetworkInterfacePal.Android.cs | 65 +++++++++-- 4 files changed, 97 insertions(+), 144 deletions(-) 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 index ca2258824ab9a..de57e068a1ddb 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalStatistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalStatistics.cs @@ -13,9 +13,9 @@ internal sealed class AndroidIPGlobalStatistics : IPGlobalStatistics { public AndroidIPGlobalStatistics(bool ipv4) { - NetworkInterface[] networkInterfaces = AndroidNetworkInterface.GetAndroidNetworkInterfaces(); + AndroidNetworkInterface[] networkInterfaces = NetworkInterfacePal.GetAndroidNetworkInterfaces(); - foreach (NetworkInterface networkInterface in networkInterfaces) + foreach (var networkInterface in networkInterfaces) { var component = ipv4 ? NetworkInterfaceComponent.IPv4 : NetworkInterfaceComponent.IPv6; if (networkInterface.Supports(component)) @@ -23,74 +23,51 @@ public AndroidIPGlobalStatistics(bool ipv4) NumberOfInterfaces++; } - if (networkInterface is AndroidNetworkInterface androidNetworkInterface) + foreach (UnixUnicastIPAddressInformation addressInformation in networkInterface.UnicastAddress) { - foreach (UnixUnicastIPAddressInformation addressInformation in androidNetworkInterface.UnicastAddress) + bool isIPv4 = addressInformation.Address.AddressFamily == AddressFamily.InterNetwork; + if (isIPv4 == ipv4) { - bool isIPv4 = addressInformation.Address.AddressFamily == AddressFamily.InterNetwork; - if (isIPv4 == ipv4) - { - NumberOfIPAddresses++; - } + NumberOfIPAddresses++; } + } - if (androidNetworkInterface.MulticastAddresess != null) + if (networkInterface.MulticastAddresess != null) + { + foreach (IPAddress address in networkInterface.MulticastAddresess) { - foreach (IPAddress address in androidNetworkInterface.MulticastAddresess) + bool isIPv4 = address.AddressFamily == AddressFamily.InterNetwork; + if (isIPv4 == ipv4) { - bool isIPv4 = address.AddressFamily == AddressFamily.InterNetwork; - if (isIPv4 == ipv4) - { - NumberOfIPAddresses++; - } + NumberOfIPAddresses++; } } } } } - public override int DefaultTtl => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); - - public override bool ForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); - 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/AndroidIPv4InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs index e0031d9bf6147..cc12cf7f35745 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs @@ -2,35 +2,23 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.IO; -using System.Runtime.Versioning; namespace System.Net.NetworkInformation { internal sealed class AndroidIPv4InterfaceProperties : UnixIPv4InterfaceProperties { - private readonly AndroidNetworkInterface _androidNetworkInterface; - public AndroidIPv4InterfaceProperties(AndroidNetworkInterface androidNetworkInterface) : base(androidNetworkInterface) { - _androidNetworkInterface = androidNetworkInterface; + Mtu = androidNetworkInterface._mtu; } - public override int Mtu => _androidNetworkInterface._mtu; + public override int Mtu { get; } - [UnsupportedOSPlatform("android")] public override bool IsAutomaticPrivateAddressingActive => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); - - [UnsupportedOSPlatform("android")] public override bool IsAutomaticPrivateAddressingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); - - [UnsupportedOSPlatform("android")] public override bool IsDhcpEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); - - [UnsupportedOSPlatform("android")] public override bool IsForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); - - [UnsupportedOSPlatform("android")] public override bool UsesWins => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); } } 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 index b0bff8dd4b995..dcf66895aea7b 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidNetworkInterface.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidNetworkInterface.cs @@ -1,11 +1,6 @@ // 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; -using System.Runtime.InteropServices; -using System.Runtime.Versioning; -using System.Text; using System.Net; namespace System.Net.NetworkInformation @@ -15,97 +10,45 @@ namespace System.Net.NetworkInformation /// internal sealed class AndroidNetworkInterface : UnixNetworkInterface { - private OperationalStatus _operationalStatus; - private bool _supportsMulticast; - private long _speed; - internal int _mtu; - private NetworkInterfaceType _interfaceType = NetworkInterfaceType.Unknown; + internal readonly int _mtu; private readonly AndroidIPInterfaceProperties _ipProperties; - internal AndroidNetworkInterface(string name, int index) : base(name) + internal unsafe AndroidNetworkInterface(string name, Interop.Sys.NetworkInterfaceInfo *networkInterfaceInfo) + : base(name) { - _index = index; - _ipProperties = new AndroidIPInterfaceProperties(this); - } - - public static unsafe NetworkInterface[] GetAndroidNetworkInterfaces() - { - int interfaceCount=0; - int addressCount=0; - Interop.Sys.NetworkInterfaceInfo * nii = null; - Interop.Sys.IpAddressInfo * ai = null; - IntPtr globalMemory = (IntPtr)null; - - if (Interop.Sys.GetNetworkInterfaces(&interfaceCount, &nii, &addressCount, &ai) != 0) + _index = networkInterfaceInfo->InterfaceIndex; + if (networkInterfaceInfo->NumAddressBytes > 0) { - string message = Interop.Sys.GetLastErrorInfo().GetErrorMessage(); - throw new NetworkInformationException(message); + _physicalAddress = new PhysicalAddress(new ReadOnlySpan(networkInterfaceInfo->AddressBytes, networkInterfaceInfo->NumAddressBytes).ToArray()); } - globalMemory = (IntPtr)nii; - try - { - NetworkInterface[] interfaces = new NetworkInterface[interfaceCount]; - Dictionary interfacesByIndex = new Dictionary(interfaceCount); - - for (int i = 0; i < interfaceCount; i++) - { - var ani = new AndroidNetworkInterface(Marshal.PtrToStringAnsi((IntPtr)nii->Name)!, nii->InterfaceIndex); - ani._interfaceType = (NetworkInterfaceType)nii->HardwareType; - ani._operationalStatus = (OperationalStatus)nii->OperationalState; - ani._mtu = nii->Mtu; - ani._speed = nii->Speed; - ani._supportsMulticast = nii->SupportsMulticast != 0; - - if (nii->NumAddressBytes > 0) - { - ani._physicalAddress = new PhysicalAddress(new ReadOnlySpan(nii->AddressBytes, nii->NumAddressBytes).ToArray()); - } - - interfaces[i] = ani; - interfacesByIndex.Add(nii->InterfaceIndex, ani); - nii++; - } - - while (addressCount != 0) - { - var address = new IPAddress(new ReadOnlySpan(ai->AddressBytes, ai->NumAddressBytes)); - if (address.IsIPv6LinkLocal) - { - address.ScopeId = ai->InterfaceIndex; - } - - if (interfacesByIndex.TryGetValue(ai->InterfaceIndex, out AndroidNetworkInterface? ani)) - { - ani.AddAddress(address, ai->PrefixLength); - } + _mtu = networkInterfaceInfo->Mtu; + _ipProperties = new AndroidIPInterfaceProperties(this); - ai++; - addressCount--; - } + OperationalStatus = (OperationalStatus)networkInterfaceInfo->OperationalState; + Speed = networkInterfaceInfo->Speed; + SupportsMulticast = networkInterfaceInfo->SupportsMulticast != 0; + NetworkInterfaceType = (NetworkInterfaceType)networkInterfaceInfo->HardwareType; + } - return interfaces; - } - finally + internal unsafe void AddAddress(Interop.Sys.IpAddressInfo *addressInfo) + { + var address = new IPAddress(new ReadOnlySpan(addressInfo->AddressBytes, addressInfo->NumAddressBytes)); + if (address.IsIPv6LinkLocal) { - Marshal.FreeHGlobal(globalMemory); + address.ScopeId = addressInfo->InterfaceIndex; } - } - public override bool SupportsMulticast => _supportsMulticast; + 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 { return _operationalStatus; } } - - public override NetworkInterfaceType NetworkInterfaceType { get { return _interfaceType; } } - - public override long Speed => _speed; - - public override bool IsReceiveOnly { get { return false; } } + 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/NetworkInterfacePal.Android.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterfacePal.Android.cs index 98663830fe147..4ffb55a517621 100644 --- 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 @@ -1,19 +1,19 @@ // 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.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() - { - return AndroidNetworkInterface.GetAndroidNetworkInterfaces(); - } + public static NetworkInterface[] GetAllNetworkInterfaces() => GetAndroidNetworkInterfaces(); public static bool GetIsNetworkAvailable() { - foreach (var ni in GetAllNetworkInterfaces()) + foreach (var ni in GetAndroidNetworkInterfaces()) { if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback || ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel) @@ -29,23 +29,68 @@ public static bool GetIsNetworkAvailable() return false; } - public static int IPv6LoopbackInterfaceIndex { get { return LoopbackInterfaceIndex; } } + public static int IPv6LoopbackInterfaceIndex => LoopbackInterfaceIndex; public static int LoopbackInterfaceIndex { get { - NetworkInterface[] interfaces = AndroidNetworkInterface.GetAndroidNetworkInterfaces(); - for (int i = 0; i < interfaces.Length; i++) + foreach (var networkInterface in GetAndroidNetworkInterfaces()) { - if (interfaces[i].NetworkInterfaceType == NetworkInterfaceType.Loopback) + if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Loopback) { - return ((UnixNetworkInterface)interfaces[i]).Index; + return networkInterface.Index; } } throw new NetworkInformationException(SR.net_NoLoopback); } } + + internal static unsafe AndroidNetworkInterface[] GetAndroidNetworkInterfaces() + { + 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 + { + var networkInterfaces = new AndroidNetworkInterface[interfaceCount]; + var interfacesByIndex = new Dictionary(interfaceCount); + + for (int i = 0; i < interfaceCount; i++, networkInterfaceInfo++) + { + var name = Marshal.PtrToStringAnsi((IntPtr)networkInterfaceInfo->Name); + var networkInterface = new AndroidNetworkInterface(name!, networkInterfaceInfo); + networkInterfaces[i] = interfacesByIndex[networkInterface.Index] = networkInterface; + } + + for (int i = 0; i < addressCount; i++, addressInfo++) + { + if (interfacesByIndex.TryGetValue(addressInfo->InterfaceIndex, out var networkInterface)) + { + networkInterface.AddAddress(addressInfo); + } + } + + return networkInterfaces; + } + finally + { + Marshal.FreeHGlobal(globalMemory); + } + } } } From bc2ba2751042ae84121aa9bc6c03692f3f049f9a Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Wed, 12 Jan 2022 15:38:18 +0100 Subject: [PATCH 07/10] Minor code clean-up --- .../AndroidIPInterfaceProperties.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) 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 index bfc243c518e49..cee58c47d8447 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPInterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPInterfaceProperties.cs @@ -18,18 +18,13 @@ public AndroidIPInterfaceProperties(AndroidNetworkInterface ani) _ipv6Properties = new AndroidIPv6InterfaceProperties(ani); } - public override bool IsDynamicDnsEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + 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); - - public override IPv4InterfaceProperties GetIPv4Properties() => _ipv4Properties; - - public override IPv6InterfaceProperties GetIPv6Properties() => _ipv6Properties; } } From c133682a134c1d48993f36018e4a927f4706f174 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Wed, 12 Jan 2022 16:47:38 +0100 Subject: [PATCH 08/10] Remove dictionary --- .../NetworkInterfacePal.Android.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) 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 index 4ffb55a517621..0e290e327fad1 100644 --- 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 @@ -1,7 +1,6 @@ // 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.Runtime.InteropServices; namespace System.Net.NetworkInformation @@ -68,20 +67,24 @@ internal static unsafe AndroidNetworkInterface[] GetAndroidNetworkInterfaces() try { var networkInterfaces = new AndroidNetworkInterface[interfaceCount]; - var interfacesByIndex = new Dictionary(interfaceCount); for (int i = 0; i < interfaceCount; i++, networkInterfaceInfo++) { var name = Marshal.PtrToStringAnsi((IntPtr)networkInterfaceInfo->Name); - var networkInterface = new AndroidNetworkInterface(name!, networkInterfaceInfo); - networkInterfaces[i] = interfacesByIndex[networkInterface.Index] = networkInterface; + networkInterfaces[i] = new AndroidNetworkInterface(name!, networkInterfaceInfo); } for (int i = 0; i < addressCount; i++, addressInfo++) { - if (interfacesByIndex.TryGetValue(addressInfo->InterfaceIndex, out var networkInterface)) + // 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) { - networkInterface.AddAddress(addressInfo); + if (networkInterface.Index == addressInfo->InterfaceIndex) + { + networkInterface.AddAddress(addressInfo); + break; + } } } From 77e4c8831f6fdecd352cbd09d8a7d726cfbd8752 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Wed, 12 Jan 2022 21:23:40 +0100 Subject: [PATCH 09/10] Refactoring --- .../NetworkInterfacePal.Android.cs | 117 ++++++++++-------- 1 file changed, 64 insertions(+), 53 deletions(-) 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 index 0e290e327fad1..3b68b90e5a5fc 100644 --- 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 @@ -9,44 +9,14 @@ internal static class NetworkInterfacePal { /// Returns objects that describe the network interfaces on the local computer. public static NetworkInterface[] GetAllNetworkInterfaces() => GetAndroidNetworkInterfaces(); - - public static bool GetIsNetworkAvailable() - { - foreach (var ni in GetAndroidNetworkInterfaces()) - { - if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback - || ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel) - { - continue; - } - if (ni.OperationalStatus == OperationalStatus.Up) - { - return true; - } - } - - return false; - } - + public static bool GetIsNetworkAvailable() => TransformNetworkInterfacess(IsSomeNetworkUp); public static int IPv6LoopbackInterfaceIndex => LoopbackInterfaceIndex; - - public static int LoopbackInterfaceIndex - { - get - { - foreach (var networkInterface in GetAndroidNetworkInterfaces()) - { - if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Loopback) - { - return networkInterface.Index; - } - } - - throw new NetworkInformationException(SR.net_NoLoopback); - } - } + 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; @@ -66,34 +36,75 @@ internal static unsafe AndroidNetworkInterface[] GetAndroidNetworkInterfaces() try { - var networkInterfaces = new AndroidNetworkInterface[interfaceCount]; + return transform(interfaceCount, (IntPtr)networkInterfaceInfo, addressCount, (IntPtr)addressInfo); + } + finally + { + Marshal.FreeHGlobal(globalMemory); + } + } - for (int i = 0; i < interfaceCount; i++, networkInterfaceInfo++) - { - var name = Marshal.PtrToStringAnsi((IntPtr)networkInterfaceInfo->Name); - networkInterfaces[i] = new AndroidNetworkInterface(name!, networkInterfaceInfo); - } + private static unsafe AndroidNetworkInterface[] ToAndroidNetworkInterfaceArray(int interfaceCount, IntPtr networkInterfacesPtr, int addressCount, IntPtr addressPtr) + { + var networkInterfaces = new AndroidNetworkInterface[interfaceCount]; - for (int i = 0; i < addressCount; i++, addressInfo++) + 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) { - // 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) { - if (networkInterface.Index == addressInfo->InterfaceIndex) - { - networkInterface.AddAddress(addressInfo); - break; - } + networkInterface.AddAddress(addressInfo); + break; } } + } + + return networkInterfaces; + } - 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; + } } - finally + + 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++) { - Marshal.FreeHGlobal(globalMemory); + if (networkInterfaceInfo->HardwareType == (int)NetworkInterfaceType.Loopback + || networkInterfaceInfo->HardwareType == (int)NetworkInterfaceType.Tunnel) + { + continue; + } + + if (networkInterfaceInfo->OperationalState == (int)OperationalStatus.Up) + { + return true; + } } + + return false; } } } From baeabaeb5a3efae0c4634a011eb20cab9d7ed53e Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Thu, 13 Jan 2022 10:05:48 +0100 Subject: [PATCH 10/10] Revert comment change --- .../tests/FunctionalTests/NetworkInterfaceBasicTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs index 3477f0ec72da9..c022f74b2c234 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs @@ -56,7 +56,7 @@ public void BasicTest_AccessInstanceProperties_NoExceptions() } [Fact] - [PlatformSpecific(TestPlatforms.Linux|TestPlatforms.Android)] // Some APIs are not supported on Linux + [PlatformSpecific(TestPlatforms.Linux|TestPlatforms.Android)] // Some APIs are not supported on Linux and Android public void BasicTest_AccessInstanceProperties_NoExceptions_Linux() { foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())