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)
#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;
close(sock);
return palError;
}
+#endif
*retSocket = sock;
return Error_SUCCESS;
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);
}
}
}
+#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;
+ }
+ default:
+ break;
+ }
+ }
+}
+#endif
#include "pal_compiler.h"
#include "pal_types.h"
-#include <linux/netlink.h>
typedef enum
{
<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" />
<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'">
</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" />
<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>
private readonly NetworkAddressChangedEventHandler _addressHandler = delegate { };
[Fact]
- [ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAddressChanged_AddRemove_Success()
{
NetworkChange.NetworkAddressChanged += _addressHandler;
}
[Fact]
- [ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAddressChanged_JustRemove_Success()
{
NetworkChange.NetworkAddressChanged -= _addressHandler;
private readonly NetworkAvailabilityChangedEventHandler _availabilityHandler = delegate { };
[Fact]
- [ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAvailabilityChanged_AddRemove_Success()
{
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.
}
[Fact]
- [ActiveIssue("https://github.com/dotnet/corefx/issues/33530", TestPlatforms.FreeBSD)]
public void NetworkAddressChanged_AddAndRemove_NetworkAvailabilityChanged_JustRemove_Success()
{
NetworkChange.NetworkAddressChanged += _addressHandler;
[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)