Skip to content

Commit 49d6db3

Browse files
[release/6.0-maui] [Android] Fix accessing network interfaces information (#63628)
* [Android] Fix accessing network interfaces information (#62780) * Re-enable tests * Dynamically load getifaddrs if necessary * Prevent redeclaration of the ifaddrs struct * Fix typo * Do not close the dynamic library * Enable the fixed functional tests in CI * Reduce code duplication for obtaining libc file name * Simplify usage of the function pointers * Move typedefs * Rename the _ensure_ function * Remove fptr typedefs * Update comment * Add missing include * Update comment * Remove unnecessary comment * Move static variable * Remove unnecessary change * Move LIBC_FILENAME to the utilities header * Avoid error if constant is undefined * Conditionally include ifaddrs * Try to fix cmake_symbol_exists issue for browser * Minor tweaks * Try different way of detecting getifaddrs * Use the hack only for Android builds * Revert "Move LIBC_FILENAME to the utilities header" This reverts commit 4e67687. * Revert "Reduce code duplication for obtaining libc file name" This reverts commit aca15d1. * Simplify opening libc * Update code style * Fix race condition * Prevent race condition * Switch locking implementation for a lock-free implementation * Enable unit test for Android * Try using weak symbols * Fix function name * Revert "Fix function name" This reverts commit f927aae. * Revert "Try using weak symbols" This reverts commit 46d3ede. * Refactor code to use pthread_once * [Android] Throw PNSE for unavailable network information (#63633) * Update tests * Add android specific implementation * Add UnsupportedOSPlatform attributes * Fix typo * Remove unnecessary file reference * Clean-up code * Minor code clean-up * Remove dictionary * Refactoring * Revert comment change * Fix usage of Interop.Sys.GetNetworkInterfaces
1 parent fd2cdbb commit 49d6db3

26 files changed

+865
-21
lines changed

src/libraries/Native/Unix/Common/pal_config.h.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#cmakedefine01 HAVE_F_FULLFSYNC
1313
#cmakedefine01 HAVE_O_CLOEXEC
1414
#cmakedefine01 HAVE_GETIFADDRS
15+
#cmakedefine01 HAVE_IFADDRS
1516
#cmakedefine01 HAVE_UTSNAME_DOMAINNAME
1617
#cmakedefine01 HAVE_STAT64
1718
#cmakedefine01 HAVE_FORK

src/libraries/Native/Unix/System.Native/pal_interfaceaddresses.c

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111
#include <stdlib.h>
1212
#include <sys/types.h>
1313
#include <assert.h>
14+
#if HAVE_IFADDRS || HAVE_GETIFADDRS
1415
#include <ifaddrs.h>
16+
#endif
17+
#if !HAVE_GETIFADDRS && TARGET_ANDROID
18+
#include <dlfcn.h>
19+
#include <pthread.h>
20+
#endif
1521
#include <net/if.h>
1622
#include <netinet/in.h>
1723
#include <string.h>
@@ -55,7 +61,6 @@
5561
#endif
5662
#endif
5763

58-
#if HAVE_GETIFADDRS
5964
// Convert mask to prefix length e.g. 255.255.255.0 -> 24
6065
// mask parameter is pointer to buffer where address starts and length is
6166
// buffer length e.g. 4 for IPv4 and 16 for IPv6.
@@ -95,14 +100,67 @@ static inline uint8_t mask2prefix(uint8_t* mask, int length)
95100

96101
return len;
97102
}
103+
104+
#if !HAVE_IFADDRS && TARGET_ANDROID
105+
// This structure is exactly the same as struct ifaddrs defined in ifaddrs.h but since the header
106+
// might not be available (e.g., in bionics used in Android before API 24) we need to mirror it here
107+
// so that we can dynamically load the getifaddrs function and use it.
108+
struct ifaddrs
109+
{
110+
struct ifaddrs *ifa_next;
111+
char *ifa_name;
112+
unsigned int ifa_flags;
113+
struct sockaddr *ifa_addr;
114+
struct sockaddr *ifa_netmask;
115+
union
116+
{
117+
struct sockaddr *ifu_broadaddr;
118+
struct sockaddr *ifu_dstaddr;
119+
} ifa_ifu;
120+
void *ifa_data;
121+
};
122+
#endif
123+
124+
#if !HAVE_GETIFADDRS && TARGET_ANDROID
125+
// Try to load the getifaddrs and freeifaddrs functions manually.
126+
// This workaround is necessary on Android prior to API 24 and it can be removed once
127+
// we drop support for earlier Android versions.
128+
static int (*getifaddrs)(struct ifaddrs**) = NULL;
129+
static void (*freeifaddrs)(struct ifaddrs*) = NULL;
130+
131+
static void try_loading_getifaddrs()
132+
{
133+
void *libc = dlopen("libc.so", RTLD_NOW);
134+
if (libc)
135+
{
136+
getifaddrs = (int (*)(struct ifaddrs**)) dlsym(libc, "getifaddrs");
137+
freeifaddrs = (void (*)(struct ifaddrs*)) dlsym(libc, "freeifaddrs");
138+
}
139+
}
140+
141+
static bool ensure_getifaddrs_is_loaded()
142+
{
143+
static pthread_once_t getifaddrs_is_loaded = PTHREAD_ONCE_INIT;
144+
pthread_once(&getifaddrs_is_loaded, try_loading_getifaddrs);
145+
return getifaddrs != NULL && freeifaddrs != NULL;
146+
}
98147
#endif
99148

100149
int32_t SystemNative_EnumerateInterfaceAddresses(void* context,
101150
IPv4AddressFound onIpv4Found,
102151
IPv6AddressFound onIpv6Found,
103152
LinkLayerAddressFound onLinkLayerFound)
104153
{
105-
#if HAVE_GETIFADDRS
154+
#if !HAVE_GETIFADDRS && TARGET_ANDROID
155+
// Workaround for Android API < 24
156+
if (!ensure_getifaddrs_is_loaded())
157+
{
158+
errno = ENOTSUP;
159+
return -1;
160+
}
161+
#endif
162+
163+
#if HAVE_GETIFADDRS || TARGET_ANDROID
106164
struct ifaddrs* headAddr;
107165
if (getifaddrs(&headAddr) == -1)
108166
{
@@ -235,7 +293,7 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context,
235293
freeifaddrs(headAddr);
236294
return 0;
237295
#else
238-
// Not supported on e.g. Android. Also, prevent a compiler error because parameters are unused
296+
// Not supported. Also, prevent a compiler error because parameters are unused
239297
(void)context;
240298
(void)onIpv4Found;
241299
(void)onIpv6Found;
@@ -247,7 +305,16 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context,
247305

248306
int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInterfaceInfo **interfaceList, int32_t * addressCount, IpAddressInfo **addressList )
249307
{
250-
#if HAVE_GETIFADDRS
308+
#if !HAVE_GETIFADDRS && TARGET_ANDROID
309+
// Workaround for Android API < 24
310+
if (!ensure_getifaddrs_is_loaded())
311+
{
312+
errno = ENOTSUP;
313+
return -1;
314+
}
315+
#endif
316+
317+
#if HAVE_GETIFADDRS || TARGET_ANDROID
251318
struct ifaddrs* head; // Pointer to block allocated by getifaddrs().
252319
struct ifaddrs* ifaddrsEntry;
253320
IpAddressInfo *ai;
@@ -453,7 +520,7 @@ int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInter
453520

454521
return 0;
455522
#else
456-
// Not supported on e.g. Android. Also, prevent a compiler error because parameters are unused
523+
// Not supported. Also, prevent a compiler error because parameters are unused
457524
(void)interfaceCount;
458525
(void)interfaceList;
459526
(void)addressCount;

src/libraries/Native/Unix/configure.cmake

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ include(CheckStructHasMember)
77
include(CheckSymbolExists)
88
include(CheckTypeSize)
99
include(CheckLibraryExists)
10+
include(CheckFunctionExists)
1011

1112
# CMP0075 Include file check macros honor CMAKE_REQUIRED_LIBRARIES.
1213
if(POLICY CMP0075)
@@ -141,6 +142,18 @@ check_c_source_compiles(
141142
"
142143
HAVE_FLOCK64)
143144

145+
check_c_source_compiles(
146+
"
147+
#include <sys/types.h>
148+
#include <ifaddrs.h>
149+
int main(void)
150+
{
151+
struct ifaddrs ia;
152+
return 0;
153+
}
154+
"
155+
HAVE_IFADDRS)
156+
144157
check_symbol_exists(
145158
O_CLOEXEC
146159
fcntl.h
@@ -156,9 +169,8 @@ check_symbol_exists(
156169
fcntl.h
157170
HAVE_F_FULLFSYNC)
158171

159-
check_symbol_exists(
172+
check_function_exists(
160173
getifaddrs
161-
ifaddrs.h
162174
HAVE_GETIFADDRS)
163175

164176
check_symbol_exists(

src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,11 @@ public virtual void CopyTo(System.Net.NetworkInformation.IPAddressInformation[]
123123
public abstract partial class IPGlobalProperties
124124
{
125125
protected IPGlobalProperties() { }
126+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
126127
public abstract string DhcpScopeName { get; }
127128
public abstract string DomainName { get; }
128129
public abstract string HostName { get; }
130+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
129131
public abstract bool IsWinsProxy { get; }
130132
public abstract System.Net.NetworkInformation.NetBiosNodeType NodeType { get; }
131133
public virtual System.IAsyncResult BeginGetUnicastAddresses(System.AsyncCallback? callback, object? state) { throw null; }
@@ -136,58 +138,92 @@ protected IPGlobalProperties() { }
136138
public abstract System.Net.IPEndPoint[] GetActiveTcpListeners();
137139
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
138140
public abstract System.Net.IPEndPoint[] GetActiveUdpListeners();
141+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
139142
public abstract System.Net.NetworkInformation.IcmpV4Statistics GetIcmpV4Statistics();
143+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
140144
public abstract System.Net.NetworkInformation.IcmpV6Statistics GetIcmpV6Statistics();
141145
[System.Runtime.Versioning.UnsupportedOSPlatform("illumos")]
142146
[System.Runtime.Versioning.UnsupportedOSPlatform("solaris")]
143147
public static System.Net.NetworkInformation.IPGlobalProperties GetIPGlobalProperties() { throw null; }
144148
public abstract System.Net.NetworkInformation.IPGlobalStatistics GetIPv4GlobalStatistics();
145149
public abstract System.Net.NetworkInformation.IPGlobalStatistics GetIPv6GlobalStatistics();
150+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
146151
public abstract System.Net.NetworkInformation.TcpStatistics GetTcpIPv4Statistics();
152+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
147153
public abstract System.Net.NetworkInformation.TcpStatistics GetTcpIPv6Statistics();
154+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
148155
public abstract System.Net.NetworkInformation.UdpStatistics GetUdpIPv4Statistics();
156+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
149157
public abstract System.Net.NetworkInformation.UdpStatistics GetUdpIPv6Statistics();
150158
public virtual System.Net.NetworkInformation.UnicastIPAddressInformationCollection GetUnicastAddresses() { throw null; }
151159
public virtual System.Threading.Tasks.Task<System.Net.NetworkInformation.UnicastIPAddressInformationCollection> GetUnicastAddressesAsync() { throw null; }
152160
}
153161
public abstract partial class IPGlobalStatistics
154162
{
155163
protected IPGlobalStatistics() { }
164+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
156165
public abstract int DefaultTtl { get; }
166+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
157167
public abstract bool ForwardingEnabled { get; }
158168
public abstract int NumberOfInterfaces { get; }
159169
public abstract int NumberOfIPAddresses { get; }
170+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
160171
public abstract int NumberOfRoutes { get; }
172+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
161173
public abstract long OutputPacketRequests { get; }
174+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
162175
public abstract long OutputPacketRoutingDiscards { get; }
176+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
163177
public abstract long OutputPacketsDiscarded { get; }
178+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
164179
public abstract long OutputPacketsWithNoRoute { get; }
180+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
165181
public abstract long PacketFragmentFailures { get; }
182+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
166183
public abstract long PacketReassembliesRequired { get; }
184+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
167185
public abstract long PacketReassemblyFailures { get; }
186+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
168187
public abstract long PacketReassemblyTimeout { get; }
188+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
169189
public abstract long PacketsFragmented { get; }
190+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
170191
public abstract long PacketsReassembled { get; }
192+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
171193
public abstract long ReceivedPackets { get; }
194+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
172195
public abstract long ReceivedPacketsDelivered { get; }
196+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
173197
public abstract long ReceivedPacketsDiscarded { get; }
198+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
174199
public abstract long ReceivedPacketsForwarded { get; }
200+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
175201
public abstract long ReceivedPacketsWithAddressErrors { get; }
202+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
176203
public abstract long ReceivedPacketsWithHeadersErrors { get; }
204+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
177205
public abstract long ReceivedPacketsWithUnknownProtocol { get; }
178206
}
179207
public abstract partial class IPInterfaceProperties
180208
{
181209
protected IPInterfaceProperties() { }
210+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
182211
public abstract System.Net.NetworkInformation.IPAddressInformationCollection AnycastAddresses { get; }
212+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
183213
public abstract System.Net.NetworkInformation.IPAddressCollection DhcpServerAddresses { get; }
214+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
184215
public abstract System.Net.NetworkInformation.IPAddressCollection DnsAddresses { get; }
216+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
185217
public abstract string DnsSuffix { get; }
218+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
186219
public abstract System.Net.NetworkInformation.GatewayIPAddressInformationCollection GatewayAddresses { get; }
220+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
187221
public abstract bool IsDnsEnabled { get; }
222+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
188223
public abstract bool IsDynamicDnsEnabled { get; }
189224
public abstract System.Net.NetworkInformation.MulticastIPAddressInformationCollection MulticastAddresses { get; }
190225
public abstract System.Net.NetworkInformation.UnicastIPAddressInformationCollection UnicastAddresses { get; }
226+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
191227
public abstract System.Net.NetworkInformation.IPAddressCollection WinsServersAddresses { get; }
192228
public abstract System.Net.NetworkInformation.IPv4InterfaceProperties GetIPv4Properties();
193229
public abstract System.Net.NetworkInformation.IPv6InterfaceProperties GetIPv6Properties();
@@ -212,11 +248,16 @@ public abstract partial class IPv4InterfaceProperties
212248
{
213249
protected IPv4InterfaceProperties() { }
214250
public abstract int Index { get; }
251+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
215252
public abstract bool IsAutomaticPrivateAddressingActive { get; }
253+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
216254
public abstract bool IsAutomaticPrivateAddressingEnabled { get; }
255+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
217256
public abstract bool IsDhcpEnabled { get; }
257+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
218258
public abstract bool IsForwardingEnabled { get; }
219259
public abstract int Mtu { get; }
260+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
220261
public abstract bool UsesWins { get; }
221262
}
222263
public abstract partial class IPv4InterfaceStatistics
@@ -316,7 +357,9 @@ protected NetworkInterface() { }
316357
[System.Runtime.Versioning.UnsupportedOSPlatform("solaris")]
317358
public static System.Net.NetworkInformation.NetworkInterface[] GetAllNetworkInterfaces() { throw null; }
318359
public virtual System.Net.NetworkInformation.IPInterfaceProperties GetIPProperties() { throw null; }
360+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
319361
public virtual System.Net.NetworkInformation.IPInterfaceStatistics GetIPStatistics() { throw null; }
362+
[System.Runtime.Versioning.UnsupportedOSPlatform("android")]
320363
public virtual System.Net.NetworkInformation.IPv4InterfaceStatistics GetIPv4Statistics() { throw null; }
321364
[System.Runtime.Versioning.UnsupportedOSPlatform("illumos")]
322365
[System.Runtime.Versioning.UnsupportedOSPlatform("solaris")]

src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
4-
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-Solaris;$(NetCoreAppCurrent)</TargetFrameworks>
4+
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-Android;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-Solaris;$(NetCoreAppCurrent)</TargetFrameworks>
55
<Nullable>enable</Nullable>
66
</PropertyGroup>
77
<PropertyGroup>
@@ -118,8 +118,8 @@
118118
<Compile Include="$(CommonPath)Interop\Unix\Interop.Errors.cs" Link="Common\Interop\CoreLib\Unix\Interop.Errors.cs" />
119119
<Compile Include="$(CommonPath)System\IO\RowConfigReader.cs" Link="Common\System\IO\RowConfigReader.cs" />
120120
</ItemGroup>
121-
<!-- Linux -->
122-
<ItemGroup Condition="'$(TargetsLinux)' == 'true'">
121+
<!-- Linux (other than Android) -->
122+
<ItemGroup Condition="'$(TargetsLinux)' == 'true' and '$(TargetsAndroid)' != 'true'">
123123
<Compile Include="System\Net\NetworkInformation\ExceptionHelper.Linux.cs" />
124124
<Compile Include="System\Net\NetworkInformation\LinuxIcmpV4Statistics.cs" />
125125
<Compile Include="System\Net\NetworkInformation\LinuxIcmpV6Statistics.cs" />
@@ -144,6 +144,17 @@
144144
<Compile Include="$(CommonPath)System\IO\StringParser.cs" Link="Common\System\IO\StringParser.cs" />
145145
<Compile Include="$(CommonPath)Interop\Linux\Interop.LinuxNetDeviceFlags.cs" Link="Common\Interop\Linux\Interop.LinuxNetDeviceFlags.cs" />
146146
</ItemGroup>
147+
<!-- Android -->
148+
<ItemGroup Condition="'$(TargetsAndroid)' == 'true'">
149+
<Compile Include="System\Net\NetworkInformation\IPGlobalPropertiesPal.Android.cs" />
150+
<Compile Include="System\Net\NetworkInformation\AndroidIPGlobalProperties.cs" />
151+
<Compile Include="System\Net\NetworkInformation\AndroidIPGlobalStatistics.cs" />
152+
<Compile Include="System\Net\NetworkInformation\AndroidIPInterfaceProperties.cs" />
153+
<Compile Include="System\Net\NetworkInformation\AndroidIPv4InterfaceProperties.cs" />
154+
<Compile Include="System\Net\NetworkInformation\AndroidIPv6InterfaceProperties.cs" />
155+
<Compile Include="System\Net\NetworkInformation\NetworkInterfacePal.Android.cs" />
156+
<Compile Include="System\Net\NetworkInformation\AndroidNetworkInterface.cs" />
157+
</ItemGroup>
147158
<!-- OSX -->
148159
<ItemGroup Condition="'$(TargetsOSX)' == 'true' or '$(TargetsiOS)' == 'true' or '$(TargetstvOS)' == 'true' or '$(TargetsFreeBSD)' == 'true'">
149160
<Compile Include="System\Net\NetworkInformation\IPGlobalPropertiesPal.Bsd.cs" />
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace System.Net.NetworkInformation
5+
{
6+
internal sealed class AndroidIPGlobalProperties : UnixIPGlobalProperties
7+
{
8+
public override TcpConnectionInformation[] GetActiveTcpConnections() => throw new PlatformNotSupportedException();
9+
10+
public override IPEndPoint[] GetActiveTcpListeners() => throw new PlatformNotSupportedException();
11+
12+
public override IPEndPoint[] GetActiveUdpListeners() => throw new PlatformNotSupportedException();
13+
14+
public override IcmpV4Statistics GetIcmpV4Statistics() => throw new PlatformNotSupportedException();
15+
16+
public override IcmpV6Statistics GetIcmpV6Statistics() => throw new PlatformNotSupportedException();
17+
18+
public override IPGlobalStatistics GetIPv4GlobalStatistics()
19+
=> new AndroidIPGlobalStatistics(ipv4: true);
20+
21+
public override IPGlobalStatistics GetIPv6GlobalStatistics()
22+
=> new AndroidIPGlobalStatistics(ipv4: false);
23+
24+
public override TcpStatistics GetTcpIPv4Statistics() => throw new PlatformNotSupportedException();
25+
26+
public override TcpStatistics GetTcpIPv6Statistics() => throw new PlatformNotSupportedException();
27+
28+
public override UdpStatistics GetUdpIPv4Statistics() => throw new PlatformNotSupportedException();
29+
30+
public override UdpStatistics GetUdpIPv6Statistics() => throw new PlatformNotSupportedException();
31+
}
32+
}

0 commit comments

Comments
 (0)