Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions eng/versioning.targets
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@

<!-- Add target platforms into MSBuild SupportedPlatform list -->
<ItemGroup Condition="'$(IsTestProject)' != 'true'">
<SupportedPlatform Condition="'$(TargetPlatformIdentifier)' == 'openbsd'" Include="OpenBSD" />
<SupportedPlatform Condition="'$(TargetPlatformIdentifier)' == 'illumos'" Include="illumos" />
<SupportedPlatform Condition="'$(TargetPlatformIdentifier)' == 'solaris'" Include="Solaris" />
<SupportedPlatform Condition="'$(TargetPlatformIdentifier)' == 'haiku'" Include="Haiku" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-linux;$(NetCoreAppCurrent)-android;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-freebsd;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-solaris;$(NetCoreAppCurrent)-haiku;$(NetCoreAppCurrent)</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-linux;$(NetCoreAppCurrent)-android;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-freebsd;$(NetCoreAppCurrent)-openbsd;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-solaris;$(NetCoreAppCurrent)-haiku;$(NetCoreAppCurrent)</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<UseCompilerGeneratedDocXmlFile>false</UseCompilerGeneratedDocXmlFile>
</PropertyGroup>
Expand Down Expand Up @@ -166,8 +166,8 @@
<Compile Include="System\Net\NetworkInformation\NetworkAddressChange.Android.cs" />
</ItemGroup>

<!-- OSX -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'osx' or '$(TargetPlatformIdentifier)' == 'ios' or '$(TargetPlatformIdentifier)' == 'tvos' or '$(TargetPlatformIdentifier)' == 'freebsd'">
<!-- OSX/FreeBSD/OpenBSD -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'osx' or '$(TargetPlatformIdentifier)' == 'ios' or '$(TargetPlatformIdentifier)' == 'tvos' or '$(TargetPlatformIdentifier)' == 'freebsd' or '$(TargetPlatformIdentifier)' == 'openbsd'">
<Compile Include="System\Net\NetworkInformation\IPGlobalPropertiesPal.Bsd.cs" />
<Compile Include="System\Net\NetworkInformation\NetworkInterfacePal.Bsd.cs" />
<Compile Include="System\Net\NetworkInformation\BsdIcmpV4Statistics.cs" />
Expand Down Expand Up @@ -201,7 +201,7 @@
<Compile Include="$(CommonPath)Interop\FreeBSD\Interop.Libraries.cs" Link="Common\Interop\FreeBSD\Interop.Libraries.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'linux' or '$(TargetPlatformIdentifier)' == 'freebsd'">
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'linux' or '$(TargetPlatformIdentifier)' == 'freebsd' or '$(TargetPlatformIdentifier)' == 'openbsd'">
<Compile Include="System\Net\NetworkInformation\NetworkAddressChange.Unix.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.NetworkChange.cs" Link="Common\Interop\Unix\System.Native\Interop.NetworkChange.cs" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ internal sealed class BsdIPGlobalProperties : UnixIPGlobalProperties
private unsafe TcpConnectionInformation[] GetTcpConnections(bool listeners)
{
int realCount = Interop.Sys.GetEstimatedTcpConnectionCount();
if (realCount == -1)
{
// The platform (e.g. OpenBSD) does not expose the TCP connection table.
throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);
}

int infoCount = realCount * 2;
Interop.Sys.NativeTcpConnectionInformation[] infos = new Interop.Sys.NativeTcpConnectionInformation[infoCount];
fixed (Interop.Sys.NativeTcpConnectionInformation* infosPtr = infos)
Expand Down Expand Up @@ -70,6 +76,12 @@ public override IPEndPoint[] GetActiveTcpListeners()
public override unsafe IPEndPoint[] GetActiveUdpListeners()
{
int realCount = Interop.Sys.GetEstimatedUdpListenerCount();
if (realCount == -1)
{
// The platform (e.g. OpenBSD) does not expose the UDP listener table.
throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);
}

int infoCount = realCount * 2;
Interop.Sys.IPEndPointInfo[] infos = new Interop.Sys.IPEndPointInfo[infoCount];
fixed (Interop.Sys.IPEndPointInfo* infosPtr = infos)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public IPGlobalPropertiesTest(ITestOutputHelper output)

[Fact]
[SkipOnPlatform(TestPlatforms.Android, "Expected behavior is different on Android")]
[SkipOnPlatform(TestPlatforms.OpenBSD, "TCP/UDP connection enumeration is unsupported on OpenBSD")]
public void IPGlobalProperties_AccessAllMethods_NoErrors()
{
IPGlobalProperties gp = IPGlobalProperties.GetIPGlobalProperties();
Expand Down Expand Up @@ -129,6 +130,7 @@ public void IPGlobalProperties_IPv4_IPv6_NoErrors_Android(int ipVersion)
[Theory]
[MemberData(nameof(Loopbacks))]
[SkipOnPlatform(TestPlatforms.Android, "Unsupported on Android")]
[SkipOnPlatform(TestPlatforms.OpenBSD, "TCP connection enumeration is unsupported on OpenBSD")]
public void IPGlobalProperties_TcpListeners_Succeed(IPAddress address)
{
using (var server = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
Expand All @@ -145,6 +147,7 @@ public void IPGlobalProperties_TcpListeners_Succeed(IPAddress address)
[Theory]
[MemberData(nameof(Loopbacks))]
[SkipOnPlatform(TestPlatforms.Android, "Unsupported on Android")]
[SkipOnPlatform(TestPlatforms.OpenBSD, "UDP listener enumeration is unsupported on OpenBSD")]
public void IPGlobalProperties_UdpListeners_Succeed(IPAddress address)
{
using (var server = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp))
Expand All @@ -158,7 +161,7 @@ public void IPGlobalProperties_UdpListeners_Succeed(IPAddress address)
}

[Theory]
[PlatformSpecific(~(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.Android))]
[PlatformSpecific(~(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.Android | TestPlatforms.OpenBSD))]
[MemberData(nameof(Loopbacks))]
public async Task IPGlobalProperties_TcpActiveConnections_Succeed(IPAddress address)
{
Expand Down Expand Up @@ -190,6 +193,7 @@ public async Task IPGlobalProperties_TcpActiveConnections_Succeed(IPAddress addr

[Fact]
[SkipOnPlatform(TestPlatforms.Android, "Unsupported on Android")]
[SkipOnPlatform(TestPlatforms.OpenBSD, "TCP connection enumeration is unsupported on OpenBSD")]
public void IPGlobalProperties_TcpActiveConnections_NotListening()
{
TcpConnectionInformation[] tcpCconnections = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ public void BasicTest_GetIsNetworkAvailable_Success()
}

[ConditionalTheory]
[SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.FreeBSD, "Expected behavior is different on OSX or FreeBSD")]
[SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.FreeBSD | TestPlatforms.OpenBSD, "Expected behavior is different on OSX, FreeBSD, or OpenBSD")]
[SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")]
[InlineData(false)]
[InlineData(true)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ private static SafeSocketHandle ValidateHandle(SafeSocketHandle handle)
public static bool OSSupportsIPv4 => SocketProtocolSupportPal.OSSupportsIPv4;
public static bool OSSupportsIPv6 => SocketProtocolSupportPal.OSSupportsIPv6;
[UnsupportedOSPlatformGuard("wasi")]
internal static bool OSSupportsIPv6DualMode => !OperatingSystem.IsWasi() && OSSupportsIPv6;
// OpenBSD does not support dual-mode (IPv4-mapped IPv6) sockets: setting IPV6_V6ONLY to 0 fails with EINVAL.
internal static bool OSSupportsIPv6DualMode => !OperatingSystem.IsWasi() && OSSupportsIPv6 && !RuntimeInformation.IsOSPlatform(OSPlatform.Create("OPENBSD"));
[UnsupportedOSPlatformGuard("wasi")]
internal static bool OSSupportsThreads => !OperatingSystem.IsWasi();
public static bool OSSupportsUnixDomainSockets => SocketProtocolSupportPal.OSSupportsUnixDomainSockets;
Expand Down
12 changes: 12 additions & 0 deletions src/native/libs/System.Native/pal_interfaceaddresses.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,18 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context,
memcpy_s(iai.AddressBytes, sizeof_member(IpAddressInfo, AddressBytes), sain6->sin6_addr.s6_addr, sizeof(sain6->sin6_addr.s6_addr));
uint32_t scopeId = sain6->sin6_scope_id;

#ifdef TARGET_OPENBSD
// OpenBSD's KAME-derived stack embeds the scope id (interface index) in the second
// 16-bit word of a link-local address and leaves sin6_scope_id set to 0. Recover the
// scope id from the address bytes and restore the canonical link-local form.
if (scopeId == 0 && iai.AddressBytes[0] == 0xFE && (iai.AddressBytes[1] & 0xC0) == 0x80)
{
scopeId = (uint32_t)((iai.AddressBytes[2] << 8) | iai.AddressBytes[3]);
iai.AddressBytes[2] = 0;
iai.AddressBytes[3] = 0;
}
#endif

struct sockaddr_in6* mask_sain6 = (struct sockaddr_in6*)current->ifa_netmask;
iai.PrefixLength = mask_sain6 != NULL ? mask2prefix((uint8_t*)&mask_sain6->sin6_addr.s6_addr, NUM_BYTES_IN_IPV6_ADDRESS) : NUM_BYTES_IN_IPV6_ADDRESS * 8;
onIpv6Found(context, actualName, &iai, &scopeId);
Expand Down
6 changes: 4 additions & 2 deletions src/native/libs/System.Native/pal_networking.c
Original file line number Diff line number Diff line change
Expand Up @@ -3370,9 +3370,11 @@ static int32_t TryChangeSocketEventRegistrationInner(
0,
0,
GetKeventUdata(data));
#if defined(__FreeBSD__)
#if defined(__FreeBSD__) || defined(__OpenBSD__)
// Issue: #30698
// FreeBSD seems to have some issue when setting read/write events together.
// FreeBSD and OpenBSD have an issue when setting read/write events together
// in a single kevent() call: the second (write) filter is silently not armed,
// so connect-completion is never delivered and async connect hangs.
// As a workaround use separate kevent() calls.
if (writeChanged)
{
Expand Down
157 changes: 93 additions & 64 deletions src/native/libs/System.Native/pal_networkstatistics.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,97 @@ int32_t SystemNative_GetActiveUdpListeners(IPEndPointInfo* infos, int32_t* infoC
return 0;
}

#else
int32_t SystemNative_GetTcpGlobalStatistics(TcpGlobalStatistics* retStats)
{
(void)retStats;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetIPv4GlobalStatistics(IPv4GlobalStatistics* retStats)
{
(void)retStats;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetUdpGlobalStatistics(UdpGlobalStatistics* retStats)
{
(void)retStats;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetIcmpv4GlobalStatistics(Icmpv4GlobalStatistics* retStats)
{
(void)retStats;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetIcmpv6GlobalStatistics(Icmpv6GlobalStatistics* retStats)
{
(void)retStats;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetEstimatedTcpConnectionCount(void)
{
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetActiveTcpConnectionInfos(NativeTcpConnectionInformation* infos, int32_t* infoCount)
{
(void)infos;
(void)infoCount;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetEstimatedUdpListenerCount(void)
{
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetActiveUdpListeners(IPEndPointInfo* infos, int32_t* infoCount)
{
(void)infos;
(void)infoCount;
errno = ENOTSUP;
return -1;
}
#endif // HAVE_NETINET_TCP_VAR_H

// SystemNative_GetNativeIPInterfaceStatistics and SystemNative_GetNumRoutes only require the
// route/interface sysctl APIs (rt_msghdr), not the protocol statistics that live in tcp_var.h.
// Gate them on HAVE_RT_MSGHDR so platforms that lack tcp_var.h but do have rt_msghdr (e.g. OpenBSD)
// still get the real implementation instead of the ENOTSUP stub.
#if HAVE_RT_MSGHDR
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#if HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
#include <sys/ioctl.h>
#include <unistd.h>
#include <net/if.h>
#if HAVE_IOS_NET_ROUTE_H
#include "ios/net/route.h"
#else
#include <net/route.h>
#endif
#if HAVE_NET_IFMEDIA_H
#include <net/if_media.h>
#elif HAVE_IOS_NET_IFMEDIA_H
#include "ios/net/if_media.h"
#endif

int32_t SystemNative_GetNativeIPInterfaceStatistics(char* interfaceName, NativeIPInterfaceStatistics* retStats)
{
assert(interfaceName != NULL && retStats != NULL);
Expand Down Expand Up @@ -709,6 +800,7 @@ int32_t SystemNative_GetNativeIPInterfaceStatistics(char* interfaceName, NativeI
memset(retStats, 0, sizeof(NativeIPInterfaceStatistics));
return -1;
}

int32_t SystemNative_GetNumRoutes(void)
{
int32_t count = 0;
Expand Down Expand Up @@ -753,69 +845,6 @@ int32_t SystemNative_GetNumRoutes(void)
return count;
}
#else
int32_t SystemNative_GetTcpGlobalStatistics(TcpGlobalStatistics* retStats)
{
(void)retStats;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetIPv4GlobalStatistics(IPv4GlobalStatistics* retStats)
{
(void)retStats;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetUdpGlobalStatistics(UdpGlobalStatistics* retStats)
{
(void)retStats;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetIcmpv4GlobalStatistics(Icmpv4GlobalStatistics* retStats)
{
(void)retStats;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetIcmpv6GlobalStatistics(Icmpv6GlobalStatistics* retStats)
{
(void)retStats;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetEstimatedTcpConnectionCount(void)
{
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetActiveTcpConnectionInfos(NativeTcpConnectionInformation* infos, int32_t* infoCount)
{
(void)infos;
(void)infoCount;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetEstimatedUdpListenerCount(void)
{
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetActiveUdpListeners(IPEndPointInfo* infos, int32_t* infoCount)
{
(void)infos;
(void)infoCount;
errno = ENOTSUP;
return -1;
}

int32_t SystemNative_GetNativeIPInterfaceStatistics(char* interfaceName, NativeIPInterfaceStatistics* retStats)
{
(void)interfaceName;
Expand All @@ -829,4 +858,4 @@ int32_t SystemNative_GetNumRoutes(void)
errno = ENOTSUP;
return -1;
}
#endif // HAVE_NETINET_TCP_VAR_H
#endif // HAVE_RT_MSGHDR
Loading