Skip to content
Merged
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
6 changes: 6 additions & 0 deletions src/libraries/Native/Unix/System.Native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ if (CMAKE_SYSTEM_NAME STREQUAL Linux)
if (!HAVE_LINUX_RTNETLINK_H)
message(FATAL_ERROR "Could not find linux/rtnetlink.h")
endif ()
elseif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
set(NATIVE_SOURCES ${NATIVE_SOURCES} pal_networkchange.c)

if (!HAVE_RT_MSGHDR)
message(FATAL_ERROR "Could not find net/route.h")
endif ()
endif ()

if (GEN_SHARED_LIB)
Expand Down
57 changes: 56 additions & 1 deletion src/libraries/Native/Unix/System.Native/pal_networkchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,48 @@
#include "pal_utilities.h"

#include <errno.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#if HAVE_LINUX_RTNETLINK_H
#include <linux/rtnetlink.h>
#elif HAVE_RT_MSGHDR
#include <net/route.h>
#else
#error System must have linux/rtnetlink.h or net/route.h.
#endif

#pragma clang diagnostic ignored "-Wcast-align" // NLMSG_* macros trigger this

Error SystemNative_CreateNetworkChangeListenerSocket(int32_t* retSocket)
{
#if HAVE_LINUX_RTNETLINK_H
struct sockaddr_nl sa;
memset(&sa, 0, sizeof(struct sockaddr_nl));

sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE;
int32_t sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
#elif HAVE_RT_MSGHDR
int32_t sock = socket(PF_ROUTE, SOCK_RAW, 0);
#endif
if (sock == -1)
{
*retSocket = -1;
return (Error)(SystemNative_ConvertErrorPlatformToPal(errno));
}

#if HAVE_LINUX_RTNETLINK_H
if (bind(sock, (struct sockaddr*)(&sa), sizeof(sa)) != 0)
{
*retSocket = -1;
Error palError = (Error)(SystemNative_ConvertErrorPlatformToPal(errno));
close(sock);
return palError;
}
#endif

*retSocket = sock;
return Error_SUCCESS;
Expand All @@ -50,6 +63,7 @@ Error SystemNative_CloseNetworkChangeListenerSocket(int32_t socket)
return err == 0 || CheckInterrupted(err) ? Error_SUCCESS : (Error)(SystemNative_ConvertErrorPlatformToPal(errno));
}

#if HAVE_LINUX_RTNETLINK_H
static NetworkChangeKind ReadNewLinkMessage(struct nlmsghdr* hdr)
{
assert(hdr != NULL);
Expand Down Expand Up @@ -117,3 +131,44 @@ void SystemNative_ReadEvents(int32_t sock, NetworkChangeEvent onNetworkChange)
}
}
}
#elif HAVE_RT_MSGHDR
void SystemNative_ReadEvents(int32_t sock, NetworkChangeEvent onNetworkChange)
{
char buffer[4096];
ssize_t count = read(sock, buffer, sizeof(buffer));
if (count < 0)
{
return;
}

struct rt_msghdr msghdr;
for (char *ptr = buffer; (ptr + sizeof(struct rt_msghdr)) <= (buffer + count); ptr += msghdr.rtm_msglen)
{
memcpy(&msghdr, ptr, sizeof(msghdr));
if (msghdr.rtm_version != RTM_VERSION)
{
// version mismatch
return;
}

switch (msghdr.rtm_type)
{
case RTM_NEWADDR:
onNetworkChange(sock, AddressAdded);
break;
case RTM_DELADDR:
onNetworkChange(sock, AddressRemoved);
break;
case RTM_ADD:
case RTM_DELETE:
case RTM_REDIRECT:
{
onNetworkChange(sock, AvailabilityChanged);
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why are the braces needed here but not for the other cases?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in #2071.

default:
break;
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

#include "pal_compiler.h"
#include "pal_types.h"
#include <linux/netlink.h>

typedef enum
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@
<Compile Include="System\Net\NetworkInformation\LinuxIcmpV6Statistics.cs" />
<Compile Include="System\Net\NetworkInformation\LinuxTcpStatistics.cs" />
<Compile Include="System\Net\NetworkInformation\LinuxUdpStatistics.cs" />
<Compile Include="System\Net\NetworkInformation\NetworkAddressChange.Linux.cs" />
<Compile Include="System\Net\NetworkInformation\IPGlobalPropertiesPal.Linux.cs" />
<Compile Include="System\Net\NetworkInformation\LinuxIPAddressInformation.cs" />
<Compile Include="System\Net\NetworkInformation\LinuxIPGlobalProperties.cs" />
Expand All @@ -222,9 +221,6 @@
<Compile Include="$(CommonPath)Interop\Linux\Interop.LinuxNetDeviceFlags.cs">
<Link>Common\Interop\Linux\Interop.LinuxNetDeviceFlags.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Linux\System.Native\Interop.NetworkChange.cs">
<Link>Common\Interop\Linux\System.Native\Interop.NetworkChange.cs</Link>
</Compile>
</ItemGroup>
<!-- OSX -->
<ItemGroup Condition=" '$(TargetsOsx)' == 'true' or '$(TargetsFreeBSD)' == 'true'">
Expand Down Expand Up @@ -270,11 +266,16 @@
</Compile>
</ItemGroup>
<ItemGroup Condition=" '$(TargetsFreeBSD)' == 'true'">
<Compile Include="System\Net\NetworkInformation\NetworkAddressChange.UnknownUnix.cs" />
<Compile Include="$(CommonPath)Interop\FreeBSD\Interop.Libraries.cs">
<Link>Common\Interop\FreeBSD\Interop.Libraries.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition=" '$(TargetsLinux)' == 'true' OR '$(TargetsFreeBSD)' == 'true'">
<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</Link>
</Compile>
</ItemGroup>
<!-- Unknown Unix -->
<ItemGroup Condition=" '$(TargetsUnknownUnix)' == 'true' ">
<Compile Include="System\Net\NetworkInformation\IPGlobalPropertiesPal.UnknownUnix.cs" />
Expand Down Expand Up @@ -303,7 +304,7 @@
<Reference Include="System.IO.FileSystem" />
<Reference Include="System.Threading.Thread" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsLinux)' == 'true'">
<ItemGroup Condition="'$(TargetsLinux)' == 'true' OR '$(TargetsFreeBSD)' == 'true'">
<Reference Include="System.Threading.Timer" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ public partial class NetworkChangedTests
private readonly NetworkAddressChangedEventHandler _addressHandler = delegate { };

[Fact]
[ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAddressChanged_AddRemove_Success()
{
NetworkChange.NetworkAddressChanged += _addressHandler;
NetworkChange.NetworkAddressChanged -= _addressHandler;
}

[Fact]
[ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAddressChanged_JustRemove_Success()
{
NetworkChange.NetworkAddressChanged -= _addressHandler;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,19 @@ public partial class NetworkChangedTests
private readonly NetworkAvailabilityChangedEventHandler _availabilityHandler = delegate { };

[Fact]
[ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAvailabilityChanged_AddRemove_Success()
{
NetworkChange.NetworkAvailabilityChanged += _availabilityHandler;
NetworkChange.NetworkAvailabilityChanged -= _availabilityHandler;
}

[Fact]
[ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAvailabilityChanged_JustRemove_Success()
{
NetworkChange.NetworkAvailabilityChanged -= _availabilityHandler;
}

[Fact]
[ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAddressChanged_Add_DoesNotBlock()
{
// Register without unregistering.
Expand All @@ -42,7 +39,6 @@ public void NetworkAddressChanged_Add_DoesNotBlock()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAddressChanged_AddAndRemove_NetworkAvailabilityChanged_JustRemove_Success()
{
NetworkChange.NetworkAddressChanged += _addressHandler;
Expand All @@ -55,7 +51,6 @@ public void NetworkAddressChanged_AddAndRemove_NetworkAvailabilityChanged_JustRe
[InlineData(false, true)]
[InlineData(true, false)]
[InlineData(true, true)]
[ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAvailabilityChanged_NetworkAddressChanged_AddAndRemove_Success(bool addAddressFirst, bool removeAddressFirst)
{
if (addAddressFirst)
Expand Down