From 87134435197b29431909296c0df5c038ec7e2405 Mon Sep 17 00:00:00 2001 From: manicka Date: Tue, 1 Oct 2019 15:34:41 +0200 Subject: [PATCH 01/16] Added interop for getfiaddrs. --- .../Unix/System.Native/Interop.HostEntry.cs | 2 +- .../System.Native/Interop.HostInterfaces.cs | 48 ++++++++ .../Unix/System.Native/pal_networking.c | 104 +++++++++++++++++- .../Unix/System.Native/pal_networking.h | 16 ++- 4 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index 06fda65b62cc..c7614b7084a2 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -41,7 +41,7 @@ internal unsafe struct HostEntry [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostEntryForName")] internal static extern unsafe int GetHostEntryForName(string address, HostEntry* entry); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNextIPAddress")] + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNextIPAddress_AddrInfo")] internal static extern unsafe int GetNextIPAddress(HostEntry* entry, addrinfo** addressListHandle, IPAddress* endPoint); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeHostEntry")] diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs new file mode 100644 index 000000000000..fb5b88854350 --- /dev/null +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + internal const int NI_MAXHOST = 1025; + internal const int NI_MAXSERV = 32; + + internal enum GetAddrInfoErrorFlags : int + { + EAI_AGAIN = 1, // Temporary failure in name resolution. + EAI_BADFLAGS = 2, // Invalid value for `ai_flags' field. + EAI_FAIL = 3, // Non-recoverable failure in name resolution. + EAI_FAMILY = 4, // 'ai_family' not supported. + EAI_NONAME = 5, // NAME or SERVICE is unknown. + EAI_BADARG = 6, // One or more input arguments were invalid. + EAI_NOMORE = 7, // No more entries are present in the list. + } + + //opaque structure to maintain consistency with native function signature + internal unsafe struct ifaddrs + { + + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct HostInterfaces + { + internal ifaddrs* AddressListHandle; // Handle for socket address list + internal int IPAddressCount; // Number of IP addresses in the list + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostInterfaces")] + internal static extern unsafe int GetHostInterfaces(HostEntry* entry); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNextIPAddress_IfAddrs")] + internal static extern unsafe int GetNextIPAddress(HostEntry* entry, addrinfo** addressListHandle, IPAddress* endPoint); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeHostInterfaces")] + internal static extern unsafe void FreeHostInterfaces(HostEntry* entry); + } +} diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index 1ece3b648780..2678537499d0 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -24,6 +24,7 @@ #include #endif #include +#include #include #include #include @@ -313,9 +314,9 @@ static int32_t GetNextIPAddressFromAddrInfo(struct addrinfo** info, IPAddress* e return GetAddrInfoErrorFlags_EAI_NOMORE; } -int32_t SystemNative_GetNextIPAddress(const HostEntry* hostEntry, struct addrinfo** addressListHandle, IPAddress* endPoint) +int32_t SystemNative_GetNextIPAddress_AddrInfo(const HostEntry* entry, struct addrinfo** addressListHandle, IPAddress* endPoint) { - if (hostEntry == NULL || addressListHandle == NULL || endPoint == NULL) + if (entry == NULL || addressListHandle == NULL || endPoint == NULL) { return GetAddrInfoErrorFlags_EAI_BADARG; } @@ -327,7 +328,104 @@ void SystemNative_FreeHostEntry(HostEntry* entry) { if (entry != NULL) { - freeaddrinfo(entry->AddressListHandle); + freeaddrinfo(entry->AddressListHandle); + } +} + +int32_t SystemNative_GetHostInterfaces(HostInterfaces* interfaces) +{ + if (interfaces == NULL) + { + return GetAddrInfoErrorFlags_EAI_BADARG; + } + + // Get all address families and the canonical name + struct ifaddrs *addrs = NULL; + int result = getifaddrs(&addrs); + if (result != 0) + { + return ConvertGetAddrInfoAndGetNameInfoErrorsToPal(result); + } + + interfaces->AddressListHandle = addrs; + interfaces->IPAddressCount = 0; + + // Find the canonical name for this host (if any) and count the number of IP end points. + for (struct ifaddrs* ifa = addrs; ifa != NULL; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == NULL) + { + continue; + } + + if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) + { + interfaces->IPAddressCount++; + } + } + + return GetAddrInfoErrorFlags_EAI_SUCCESS; +} + +static int32_t GetNextIPAddressFromIfAddrs(struct ifaddrs** info, IPAddress* endPoint) +{ + assert(info != NULL); + assert(endPoint != NULL); + + for (struct ifaddrs* ifa = *info; ifa != NULL; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == NULL) + continue; + + switch (ifa->ifa_addr->sa_family) + { + case AF_INET: + { + struct sockaddr_in* inetSockAddr = (struct sockaddr_in*)ifa->ifa_addr; + + ConvertInAddrToByteArray(endPoint->Address, NUM_BYTES_IN_IPV4_ADDRESS, &inetSockAddr->sin_addr); + endPoint->IsIPv6 = 0; + break; + } + + case AF_INET6: + { + struct sockaddr_in6* inet6SockAddr = (struct sockaddr_in6*)ifa->ifa_addr; + + ConvertIn6AddrToByteArray(endPoint->Address, NUM_BYTES_IN_IPV6_ADDRESS, &inet6SockAddr->sin6_addr); + endPoint->IsIPv6 = 1; + endPoint->ScopeId = inet6SockAddr->sin6_scope_id; + break; + } + + default: + // Skip non-IPv4 and non-IPv6 addresses + continue; + } + + *info = ifa->ifa_next; + return GetAddrInfoErrorFlags_EAI_SUCCESS; + } + + return GetAddrInfoErrorFlags_EAI_NOMORE; +} + +int32_t SystemNative_GetNextIPAddress_IfAddrs(const HostInterfaces* interfaces, struct ifaddrs** interfaceListHandle, IPAddress* endPoint) +{ + + if (interfaces == NULL || interfaceListHandle == NULL || endPoint == NULL) + { + return GetAddrInfoErrorFlags_EAI_BADARG; + } + + return GetNextIPAddressFromIfAddrs(interfaceListHandle, endPoint); +} + +void SystemNative_FreeHostInterfaces(HostInterfaces* interfaces) +{ + if (interfaces != NULL) + { + freeifaddrs(interfaces->AddressListHandle); } } diff --git a/src/Native/Unix/System.Native/pal_networking.h b/src/Native/Unix/System.Native/pal_networking.h index 4a51cce60f07..a2c21ed5014b 100644 --- a/src/Native/Unix/System.Native/pal_networking.h +++ b/src/Native/Unix/System.Native/pal_networking.h @@ -252,9 +252,15 @@ typedef struct uint8_t* CanonicalName; // Canonical name of the host uint8_t** Aliases; // List of aliases for the host struct addrinfo* AddressListHandle; // Handle for host socket addresses - int32_t IPAddressCount; // Number of IP end points in the list + int32_t IPAddressCount; // Number of IP end points in the socket address list } HostEntry; +typedef struct +{ + struct ifaddrs* AddressListHandle; // Handle for interface addresses + int32_t IPAddressCount; // Number of IP end points in the interaface list +} HostInterfaces; + typedef struct { IPAddress Address; // Destination IP address @@ -311,10 +317,16 @@ typedef struct DLLEXPORT int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry); -DLLEXPORT int32_t SystemNative_GetNextIPAddress(const HostEntry* entry, struct addrinfo** addressListHandle, IPAddress* endPoint); +DLLEXPORT int32_t SystemNative_GetNextIPAddress_AddrInfo(const HostEntry* entry, struct addrinfo** addressListHandle, IPAddress* endPoint); DLLEXPORT void SystemNative_FreeHostEntry(HostEntry* entry); +DLLEXPORT int32_t SystemNative_GetHostInterfaces(HostInterfaces* interfaces); + +DLLEXPORT int32_t SystemNative_GetNextIPAddress_IfAddrs(const HostInterfaces* interfaces, struct ifaddrs** interfaceListHandle, IPAddress* endPoint); + +DLLEXPORT void SystemNative_FreeHostInterfaces(HostInterfaces* interfaces); + DLLEXPORT int32_t SystemNative_GetNameInfo(const uint8_t* address, int32_t addressLength, int8_t isIPv6, From c69c736cc5efb28992a88f12f6d6639f68cd3f9b Mon Sep 17 00:00:00 2001 From: Manicka Date: Tue, 1 Oct 2019 17:43:35 +0200 Subject: [PATCH 02/16] HostInterfaces parsed in C# Unix PAL. --- .../src/System/Net/NameResolutionPal.Unix.cs | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs index 47a6a2055041..e19e3fff2e3a 100644 --- a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs +++ b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs @@ -44,7 +44,7 @@ private static SocketError GetSocketErrorForNativeError(int error) } } - private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool justAddresses, out string hostName, out string[] aliases, out IPAddress[] addresses) + private static unsafe void ParseHostEntryAndInterfaces(Interop.Sys.HostEntry hostEntry, Interop.Sys.HostInterfaces hostInterfaces, bool justAddresses, out string hostName, out string[] aliases, out IPAddress[] addresses) { try { @@ -52,8 +52,11 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool Marshal.PtrToStringAnsi((IntPtr)hostEntry.CanonicalName) : null; + + var hostInterfacesCount = hostInterfaces == null ? 0 : hostInterfaces.IPAddressCount; + IPAddress[] localAddresses; - if (hostEntry.IPAddressCount == 0) + if (hostEntry.IPAddressCount == 0 && hostInterfacesCount == 0) { localAddresses = Array.Empty(); } @@ -70,14 +73,14 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool // is likely to involve extra allocations, hashing, etc., and so will probably be more expensive than // this one in the typical (short list) case. - var nativeAddresses = new Interop.Sys.IPAddress[hostEntry.IPAddressCount]; + var nativeAddresses = new Interop.Sys.IPAddress[hostEntry.IPAddressCount + hostInterfacesCount]; int nativeAddressCount = 0; - Interop.Sys.addrinfo* addressListHandle = hostEntry.AddressListHandle; + Interop.Sys.addrinfo* addrInfoHandle = hostEntry.AddressListHandle; for (int i = 0; i < hostEntry.IPAddressCount; i++) { Interop.Sys.IPAddress nativeIPAddress = default; - int err = Interop.Sys.GetNextIPAddress(&hostEntry, &addressListHandle, &nativeIPAddress); + int err = Interop.Sys.GetNextIPAddress(&hostEntry, &addrInfoHandle, &nativeIPAddress); Debug.Assert(err == 0); if (Array.IndexOf(nativeAddresses, nativeIPAddress, 0, nativeAddressCount) == -1) @@ -86,6 +89,22 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool } } + if (hostInterfaces != null) + { + Interop.Sys.ifaddrs* ifAddrsHandle = hostInterfaces.AddressListHandle; + for (int i = 0; i < hostInterfaces.IPAddressCount; i++) + { + Interop.Sys.IPAddress nativeIPAddress = default; + int err = Interop.Sys.GetNextIPAddress(&hostInterfaces, &ifAddrsHandle, &nativeIPAddress); + Debug.Assert(err == 0); + + if (Array.IndexOf(nativeAddresses, nativeIPAddress, 0, nativeAddressCount) == -1) + { + nativeAddresses[nativeAddressCount++] = nativeIPAddress; + } + } + } + localAddresses = new IPAddress[nativeAddressCount]; for (int i = 0; i < nativeAddressCount; i++) { @@ -118,15 +137,20 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool finally { Interop.Sys.FreeHostEntry(&hostEntry); + if (hostInterfaces != null) + { + Interop.Sys.FreeHostInterfaces(&hostInterfaces); + } } } public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, out string hostName, out string[] aliases, out IPAddress[] addresses, out int nativeErrorCode) { + string localHostName = Dns.GetHostName(); if (name == "") { // To match documented behavior on Windows, if an empty string is passed in, use the local host's name. - name = Dns.GetHostName(); + name = localHostName; } Interop.Sys.HostEntry entry; @@ -140,7 +164,21 @@ public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, return GetSocketErrorForNativeError(result); } - ParseHostEntry(entry, justAddresses, out hostName, out aliases, out addresses); + Interop.Sys.HostInterfaces interfaces = null; + if (name == localHostName) + { + int result = Interop.Sys.GetHostInterfaces(&interfaces); + if (result != 0) + { + nativeErrorCode = result; + hostName = name; + aliases = Array.Empty(); + addresses = Array.Empty(); + return GetSocketErrorForNativeError(result); + } + } + + ParseHostEntryAndInterfaces(entry, justAddresses, out hostName, out aliases, ref addresses); nativeErrorCode = 0; return SocketError.Success; } From 99de10f9926744cded3ef6066ae31834dcf6952e Mon Sep 17 00:00:00 2001 From: Manicka Date: Tue, 1 Oct 2019 18:24:59 +0200 Subject: [PATCH 03/16] Fixed linked files in csproj. --- .../src/System.Net.NameResolution.csproj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/System.Net.NameResolution/src/System.Net.NameResolution.csproj b/src/System.Net.NameResolution/src/System.Net.NameResolution.csproj index 3ee88c67689f..cea3307b307b 100644 --- a/src/System.Net.NameResolution/src/System.Net.NameResolution.csproj +++ b/src/System.Net.NameResolution/src/System.Net.NameResolution.csproj @@ -147,8 +147,11 @@ Interop\Unix\System.Native\Interop.HostEntries.cs + + Interop\Unix\System.Native\Interop.HostInterfaces.cs + - Interop\Unix\System.Native\Interop.HostEntries.cs + Interop\Unix\System.Native\Interop.IPAddress.cs Interop\Unix\System.Native\Interop.Socket.cs From c767b71e9f34b87e22d5e35cd72fde75aeeb2c99 Mon Sep 17 00:00:00 2001 From: manicka Date: Tue, 1 Oct 2019 22:24:54 +0200 Subject: [PATCH 04/16] Fixed compilation. --- .../Unix/System.Native/Interop.HostEntry.cs | 2 +- .../System.Native/Interop.HostInterfaces.cs | 20 ++------- .../src/System/Net/NameResolutionPal.Unix.cs | 43 ++++++++----------- 3 files changed, 23 insertions(+), 42 deletions(-) diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index c7614b7084a2..d36ffe12372f 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -42,7 +42,7 @@ internal unsafe struct HostEntry internal static extern unsafe int GetHostEntryForName(string address, HostEntry* entry); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNextIPAddress_AddrInfo")] - internal static extern unsafe int GetNextIPAddress(HostEntry* entry, addrinfo** addressListHandle, IPAddress* endPoint); + internal static extern unsafe int GetNextIPAddress_AddrInfo(HostEntry* entry, addrinfo** addressListHandle, IPAddress* endPoint); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeHostEntry")] internal static extern unsafe void FreeHostEntry(HostEntry* entry); diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs index fb5b88854350..196543ff5a2b 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs @@ -9,20 +9,6 @@ internal static partial class Interop { internal static partial class Sys { - internal const int NI_MAXHOST = 1025; - internal const int NI_MAXSERV = 32; - - internal enum GetAddrInfoErrorFlags : int - { - EAI_AGAIN = 1, // Temporary failure in name resolution. - EAI_BADFLAGS = 2, // Invalid value for `ai_flags' field. - EAI_FAIL = 3, // Non-recoverable failure in name resolution. - EAI_FAMILY = 4, // 'ai_family' not supported. - EAI_NONAME = 5, // NAME or SERVICE is unknown. - EAI_BADARG = 6, // One or more input arguments were invalid. - EAI_NOMORE = 7, // No more entries are present in the list. - } - //opaque structure to maintain consistency with native function signature internal unsafe struct ifaddrs { @@ -37,12 +23,12 @@ internal unsafe struct HostInterfaces } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostInterfaces")] - internal static extern unsafe int GetHostInterfaces(HostEntry* entry); + internal static extern unsafe int GetHostInterfaces(HostInterfaces* interfaces); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNextIPAddress_IfAddrs")] - internal static extern unsafe int GetNextIPAddress(HostEntry* entry, addrinfo** addressListHandle, IPAddress* endPoint); + internal static extern unsafe int GetNextIPAddress_IfAddrs(HostInterfaces* interfaces, ifaddrs** addressListHandle, IPAddress* endPoint); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeHostInterfaces")] - internal static extern unsafe void FreeHostInterfaces(HostEntry* entry); + internal static extern unsafe void FreeHostInterfaces(HostInterfaces* interfaces); } } diff --git a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs index e19e3fff2e3a..b7a02b9440ae 100644 --- a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs +++ b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs @@ -52,11 +52,8 @@ private static unsafe void ParseHostEntryAndInterfaces(Interop.Sys.HostEntry hos Marshal.PtrToStringAnsi((IntPtr)hostEntry.CanonicalName) : null; - - var hostInterfacesCount = hostInterfaces == null ? 0 : hostInterfaces.IPAddressCount; - IPAddress[] localAddresses; - if (hostEntry.IPAddressCount == 0 && hostInterfacesCount == 0) + if (hostEntry.IPAddressCount == 0 && hostInterfaces.IPAddressCount == 0) { localAddresses = Array.Empty(); } @@ -73,14 +70,14 @@ private static unsafe void ParseHostEntryAndInterfaces(Interop.Sys.HostEntry hos // is likely to involve extra allocations, hashing, etc., and so will probably be more expensive than // this one in the typical (short list) case. - var nativeAddresses = new Interop.Sys.IPAddress[hostEntry.IPAddressCount + hostInterfacesCount]; + var nativeAddresses = new Interop.Sys.IPAddress[hostEntry.IPAddressCount + hostInterfaces.IPAddressCount]; int nativeAddressCount = 0; Interop.Sys.addrinfo* addrInfoHandle = hostEntry.AddressListHandle; for (int i = 0; i < hostEntry.IPAddressCount; i++) { Interop.Sys.IPAddress nativeIPAddress = default; - int err = Interop.Sys.GetNextIPAddress(&hostEntry, &addrInfoHandle, &nativeIPAddress); + int err = Interop.Sys.GetNextIPAddress_AddrInfo(&hostEntry, &addrInfoHandle, &nativeIPAddress); Debug.Assert(err == 0); if (Array.IndexOf(nativeAddresses, nativeIPAddress, 0, nativeAddressCount) == -1) @@ -89,19 +86,16 @@ private static unsafe void ParseHostEntryAndInterfaces(Interop.Sys.HostEntry hos } } - if (hostInterfaces != null) + Interop.Sys.ifaddrs* ifAddrsHandle = hostInterfaces.AddressListHandle; + for (int i = 0; i < hostInterfaces.IPAddressCount; i++) { - Interop.Sys.ifaddrs* ifAddrsHandle = hostInterfaces.AddressListHandle; - for (int i = 0; i < hostInterfaces.IPAddressCount; i++) + Interop.Sys.IPAddress nativeIPAddress = default; + int err = Interop.Sys.GetNextIPAddress_IfAddrs(&hostInterfaces, &ifAddrsHandle, &nativeIPAddress); + Debug.Assert(err == 0); + + if (Array.IndexOf(nativeAddresses, nativeIPAddress, 0, nativeAddressCount) == -1) { - Interop.Sys.IPAddress nativeIPAddress = default; - int err = Interop.Sys.GetNextIPAddress(&hostInterfaces, &ifAddrsHandle, &nativeIPAddress); - Debug.Assert(err == 0); - - if (Array.IndexOf(nativeAddresses, nativeIPAddress, 0, nativeAddressCount) == -1) - { - nativeAddresses[nativeAddressCount++] = nativeIPAddress; - } + nativeAddresses[nativeAddressCount++] = nativeIPAddress; } } @@ -137,10 +131,7 @@ private static unsafe void ParseHostEntryAndInterfaces(Interop.Sys.HostEntry hos finally { Interop.Sys.FreeHostEntry(&hostEntry); - if (hostInterfaces != null) - { - Interop.Sys.FreeHostInterfaces(&hostInterfaces); - } + Interop.Sys.FreeHostInterfaces(&hostInterfaces); } } @@ -164,10 +155,10 @@ public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, return GetSocketErrorForNativeError(result); } - Interop.Sys.HostInterfaces interfaces = null; + Interop.Sys.HostInterfaces interfaces; if (name == localHostName) { - int result = Interop.Sys.GetHostInterfaces(&interfaces); + result = Interop.Sys.GetHostInterfaces(&interfaces); if (result != 0) { nativeErrorCode = result; @@ -177,8 +168,12 @@ public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, return GetSocketErrorForNativeError(result); } } + else + { + interfaces = new Interop.Sys.HostInterfaces(); + } - ParseHostEntryAndInterfaces(entry, justAddresses, out hostName, out aliases, ref addresses); + ParseHostEntryAndInterfaces(entry, interfaces, justAddresses, out hostName, out aliases, out addresses); nativeErrorCode = 0; return SocketError.Success; } From a2bb4511953450e71fd1dff52e0992569663e344 Mon Sep 17 00:00:00 2001 From: manicka Date: Wed, 2 Oct 2019 15:56:28 +0200 Subject: [PATCH 05/16] Fixed test project. --- .../tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj b/src/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj index 174a69812f43..74aab45c7dba 100644 --- a/src/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj +++ b/src/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj @@ -157,6 +157,9 @@ Interop\Unix\System.Native\Interop.HostEntry.cs + + Interop\Unix\System.Native\Interop.HostInterfaces.cs + Interop\Unix\System.Native\Interop.IPAddress.cs From 64d6052d57e1620cfc0010619c767f2c4967346c Mon Sep 17 00:00:00 2001 From: manicka Date: Tue, 8 Oct 2019 14:42:35 +0200 Subject: [PATCH 06/16] Merged getifaddrs into GetHostEntryForName --- .../Unix/System.Native/Interop.HostEntry.cs | 18 ++- .../System.Native/Interop.HostInterfaces.cs | 34 ----- .../Unix/System.Native/pal_networking.c | 127 ++++++++---------- .../Unix/System.Native/pal_networking.h | 23 ++-- .../src/System.Net.NameResolution.csproj | 3 - .../src/System/Net/NameResolutionPal.Unix.cs | 57 +++----- ...System.Net.NameResolution.Pal.Tests.csproj | 3 - 7 files changed, 97 insertions(+), 168 deletions(-) delete mode 100644 src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index d36ffe12372f..2c8edc874048 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -27,6 +27,11 @@ internal enum GetAddrInfoErrorFlags : int internal unsafe struct addrinfo { + } + //opaque structure to maintain consistency with native function signature + internal unsafe struct ifaddrs + { + } [StructLayout(LayoutKind.Sequential)] @@ -34,15 +39,20 @@ internal unsafe struct HostEntry { internal byte* CanonicalName; // Canonical Name of the Host internal byte** Aliases; // List of aliases for the host - internal addrinfo* AddressListHandle; // Handle for socket address list - internal int IPAddressCount; // Number of IP addresses in the list + internal addrinfo* AddressInfoListHandle; // Handle for socket address list + internal int AddressInfoCount; // Number of IP addresses in the list + internal ifaddrs* InterfaceAddressListHandle; // Handle for interface addresses + internal int InterfaceAddressCount; // Number of IP end points in the interaface list } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostEntryForName")] - internal static extern unsafe int GetHostEntryForName(string address, HostEntry* entry); + internal static extern unsafe int GetHostEntryForName(string address, HostEntry* entrym, int includeInterfaces); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNextIPAddress_AddrInfo")] - internal static extern unsafe int GetNextIPAddress_AddrInfo(HostEntry* entry, addrinfo** addressListHandle, IPAddress* endPoint); + internal static extern unsafe int GetNextIPAddress_AddrInfo(HostEntry* entry, addrinfo** addressInfoListHandle, IPAddress* endPoint); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNextIPAddress_IfAddrs")] + internal static extern unsafe int GetNextIPAddress_IfAddrs(HostEntry* entry, ifaddrs** interfaceAddressListHandle, IPAddress* endPoint); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeHostEntry")] internal static extern unsafe void FreeHostEntry(HostEntry* entry); diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs deleted file mode 100644 index 196543ff5a2b..000000000000 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostInterfaces.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Runtime.InteropServices; - -internal static partial class Interop -{ - internal static partial class Sys - { - //opaque structure to maintain consistency with native function signature - internal unsafe struct ifaddrs - { - - } - - [StructLayout(LayoutKind.Sequential)] - internal unsafe struct HostInterfaces - { - internal ifaddrs* AddressListHandle; // Handle for socket address list - internal int IPAddressCount; // Number of IP addresses in the list - } - - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostInterfaces")] - internal static extern unsafe int GetHostInterfaces(HostInterfaces* interfaces); - - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNextIPAddress_IfAddrs")] - internal static extern unsafe int GetNextIPAddress_IfAddrs(HostInterfaces* interfaces, ifaddrs** addressListHandle, IPAddress* endPoint); - - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeHostInterfaces")] - internal static extern unsafe void FreeHostInterfaces(HostInterfaces* interfaces); - } -} diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index 2678537499d0..4d8028461144 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -24,7 +24,6 @@ #include #endif #include -#include #include #include #include @@ -51,11 +50,9 @@ #elif HAVE_SENDFILE_6 #include #endif -#if !HAVE_IN_PKTINFO #if HAVE_GETIFADDRS #include #endif -#endif #ifdef AF_CAN #include #endif @@ -231,13 +228,13 @@ static int32_t ConvertGetAddrInfoAndGetNameInfoErrorsToPal(int32_t error) return -1; } -int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry) +int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry, int32_t includeInterfaces) { if (address == NULL || entry == NULL) { return GetAddrInfoErrorFlags_EAI_BADARG; } - + // Get all address families and the canonical name struct addrinfo hint; memset(&hint, 0, sizeof(struct addrinfo)); @@ -253,8 +250,10 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr entry->CanonicalName = NULL; entry->Aliases = NULL; - entry->AddressListHandle = info; - entry->IPAddressCount = 0; + entry->AddressInfoListHandle = info; + entry->AddressInfoCount = 0; + entry->InterfaceAddressListHandle = NULL; + entry->InterfaceAddressCount = 0; // Find the canonical name for this host (if any) and count the number of IP end points. for (struct addrinfo* ai = info; ai != NULL; ai = ai->ai_next) @@ -267,19 +266,48 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { - entry->IPAddressCount++; + entry->AddressInfoCount++; } } + if (includeInterfaces != 0) + { +#if HAVE_GETIFADDRS + // Get all interface addresses if the host name corresponds to the local host. + struct ifaddrs *addrs = NULL; + result = getifaddrs(&addrs); + + // If getifaddrs fails, just skip it, the data are no crucial for the result. + if (result == 0) + { + entry->InterfaceAddressListHandle = addrs; + + // Count the number of IP end points. + for (struct ifaddrs* ifa = addrs; ifa != NULL; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == NULL) + { + continue; + } + + if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) + { + entry->InterfaceAddressCount++; + } + } + } +#endif + } + return GetAddrInfoErrorFlags_EAI_SUCCESS; } -static int32_t GetNextIPAddressFromAddrInfo(struct addrinfo** info, IPAddress* endPoint) +static int32_t GetNextIPAddressFromAddrInfo(struct addrinfo** addrInfo, IPAddress* endPoint) { - assert(info != NULL); + assert(addrInfo != NULL); assert(endPoint != NULL); - for (struct addrinfo* ai = *info; ai != NULL; ai = ai->ai_next) + for (struct addrinfo* ai = *addrInfo; ai != NULL; ai = ai->ai_next) { switch (ai->ai_family) { @@ -307,72 +335,30 @@ static int32_t GetNextIPAddressFromAddrInfo(struct addrinfo** info, IPAddress* e continue; } - *info = ai->ai_next; + *addrInfo = ai->ai_next; return GetAddrInfoErrorFlags_EAI_SUCCESS; } return GetAddrInfoErrorFlags_EAI_NOMORE; } -int32_t SystemNative_GetNextIPAddress_AddrInfo(const HostEntry* entry, struct addrinfo** addressListHandle, IPAddress* endPoint) +int32_t SystemNative_GetNextIPAddress_AddrInfo(const HostEntry* entry, struct addrinfo** addressInfoListHandle, IPAddress* endPoint) { - if (entry == NULL || addressListHandle == NULL || endPoint == NULL) + if (entry == NULL || addressInfoListHandle == NULL || endPoint == NULL) { return GetAddrInfoErrorFlags_EAI_BADARG; } - return GetNextIPAddressFromAddrInfo(addressListHandle, endPoint); + return GetNextIPAddressFromAddrInfo(addressInfoListHandle, endPoint); } -void SystemNative_FreeHostEntry(HostEntry* entry) +static int32_t GetNextIPAddressFromIfAddrs(struct ifaddrs** ifAddrs, IPAddress* endPoint) { - if (entry != NULL) - { - freeaddrinfo(entry->AddressListHandle); - } -} - -int32_t SystemNative_GetHostInterfaces(HostInterfaces* interfaces) -{ - if (interfaces == NULL) - { - return GetAddrInfoErrorFlags_EAI_BADARG; - } - - // Get all address families and the canonical name - struct ifaddrs *addrs = NULL; - int result = getifaddrs(&addrs); - if (result != 0) - { - return ConvertGetAddrInfoAndGetNameInfoErrorsToPal(result); - } - - interfaces->AddressListHandle = addrs; - interfaces->IPAddressCount = 0; - - // Find the canonical name for this host (if any) and count the number of IP end points. - for (struct ifaddrs* ifa = addrs; ifa != NULL; ifa = ifa->ifa_next) - { - if (ifa->ifa_addr == NULL) - { - continue; - } - - if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) - { - interfaces->IPAddressCount++; - } - } - - return GetAddrInfoErrorFlags_EAI_SUCCESS; -} - -static int32_t GetNextIPAddressFromIfAddrs(struct ifaddrs** info, IPAddress* endPoint) -{ - assert(info != NULL); +#if HAVE_GETIFADDRS + assert(ifAddrs != NULL); assert(endPoint != NULL); - for (struct ifaddrs* ifa = *info; ifa != NULL; ifa = ifa->ifa_next) + for (struct ifaddrs* ifa = *ifAddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; @@ -403,29 +389,32 @@ static int32_t GetNextIPAddressFromIfAddrs(struct ifaddrs** info, IPAddress* end continue; } - *info = ifa->ifa_next; + *ifAddrs = ifa->ifa_next; return GetAddrInfoErrorFlags_EAI_SUCCESS; } - +#endif return GetAddrInfoErrorFlags_EAI_NOMORE; } -int32_t SystemNative_GetNextIPAddress_IfAddrs(const HostInterfaces* interfaces, struct ifaddrs** interfaceListHandle, IPAddress* endPoint) +int32_t SystemNative_GetNextIPAddress_IfAddrs(const HostEntry* entry, struct ifaddrs** interfaceAddressListHandle, IPAddress* endPoint) { - if (interfaces == NULL || interfaceListHandle == NULL || endPoint == NULL) + if (entry == NULL || interfaceAddressListHandle == NULL || endPoint == NULL) { return GetAddrInfoErrorFlags_EAI_BADARG; } - return GetNextIPAddressFromIfAddrs(interfaceListHandle, endPoint); + return GetNextIPAddressFromIfAddrs(interfaceAddressListHandle, endPoint); } -void SystemNative_FreeHostInterfaces(HostInterfaces* interfaces) +void SystemNative_FreeHostEntry(HostEntry* entry) { - if (interfaces != NULL) + if (entry != NULL) { - freeifaddrs(interfaces->AddressListHandle); + freeaddrinfo(entry->AddressInfoListHandle); +#if HAVE_GETIFADDRS + freeifaddrs(entry->InterfaceAddressListHandle); +#endif } } diff --git a/src/Native/Unix/System.Native/pal_networking.h b/src/Native/Unix/System.Native/pal_networking.h index a2c21ed5014b..afbe506e6d75 100644 --- a/src/Native/Unix/System.Native/pal_networking.h +++ b/src/Native/Unix/System.Native/pal_networking.h @@ -251,16 +251,12 @@ typedef struct { uint8_t* CanonicalName; // Canonical name of the host uint8_t** Aliases; // List of aliases for the host - struct addrinfo* AddressListHandle; // Handle for host socket addresses - int32_t IPAddressCount; // Number of IP end points in the socket address list + struct addrinfo* AddressInfoListHandle; // Handle for host socket addresses + int32_t AddressInfoCount; // Number of IP end points in the socket address list + struct ifaddrs* InterfaceAddressListHandle; // Handle for interface addresses + int32_t InterfaceAddressCount; // Number of IP end points in the interaface list } HostEntry; -typedef struct -{ - struct ifaddrs* AddressListHandle; // Handle for interface addresses - int32_t IPAddressCount; // Number of IP end points in the interaface list -} HostInterfaces; - typedef struct { IPAddress Address; // Destination IP address @@ -315,17 +311,14 @@ typedef struct uint32_t Padding; // Pad out to 8-byte alignment } SocketEvent; -DLLEXPORT int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry); +DLLEXPORT int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry, int32_t includeInterfaces); -DLLEXPORT int32_t SystemNative_GetNextIPAddress_AddrInfo(const HostEntry* entry, struct addrinfo** addressListHandle, IPAddress* endPoint); +DLLEXPORT int32_t SystemNative_GetNextIPAddress_AddrInfo(const HostEntry* entry, struct addrinfo** addressInfoListHandle, IPAddress* endPoint); -DLLEXPORT void SystemNative_FreeHostEntry(HostEntry* entry); - -DLLEXPORT int32_t SystemNative_GetHostInterfaces(HostInterfaces* interfaces); +DLLEXPORT int32_t SystemNative_GetNextIPAddress_IfAddrs(const HostEntry* entry, struct ifaddrs** interfaceAddressListHandle, IPAddress* endPoint); -DLLEXPORT int32_t SystemNative_GetNextIPAddress_IfAddrs(const HostInterfaces* interfaces, struct ifaddrs** interfaceListHandle, IPAddress* endPoint); +DLLEXPORT void SystemNative_FreeHostEntry(HostEntry* entry); -DLLEXPORT void SystemNative_FreeHostInterfaces(HostInterfaces* interfaces); DLLEXPORT int32_t SystemNative_GetNameInfo(const uint8_t* address, int32_t addressLength, diff --git a/src/System.Net.NameResolution/src/System.Net.NameResolution.csproj b/src/System.Net.NameResolution/src/System.Net.NameResolution.csproj index cea3307b307b..a5c305f657ea 100644 --- a/src/System.Net.NameResolution/src/System.Net.NameResolution.csproj +++ b/src/System.Net.NameResolution/src/System.Net.NameResolution.csproj @@ -147,9 +147,6 @@ Interop\Unix\System.Native\Interop.HostEntries.cs - - Interop\Unix\System.Native\Interop.HostInterfaces.cs - Interop\Unix\System.Native\Interop.IPAddress.cs diff --git a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs index b7a02b9440ae..c86d811f4a1b 100644 --- a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs +++ b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs @@ -44,7 +44,7 @@ private static SocketError GetSocketErrorForNativeError(int error) } } - private static unsafe void ParseHostEntryAndInterfaces(Interop.Sys.HostEntry hostEntry, Interop.Sys.HostInterfaces hostInterfaces, bool justAddresses, out string hostName, out string[] aliases, out IPAddress[] addresses) + private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool justAddresses, out string hostName, out string[] aliases, out IPAddress[] addresses) { try { @@ -53,7 +53,7 @@ private static unsafe void ParseHostEntryAndInterfaces(Interop.Sys.HostEntry hos null; IPAddress[] localAddresses; - if (hostEntry.IPAddressCount == 0 && hostInterfaces.IPAddressCount == 0) + if (hostEntry.AddressInfoCount == 0 && hostEntry.InterfaceAddressCount == 0) { localAddresses = Array.Empty(); } @@ -70,33 +70,29 @@ private static unsafe void ParseHostEntryAndInterfaces(Interop.Sys.HostEntry hos // is likely to involve extra allocations, hashing, etc., and so will probably be more expensive than // this one in the typical (short list) case. - var nativeAddresses = new Interop.Sys.IPAddress[hostEntry.IPAddressCount + hostInterfaces.IPAddressCount]; + Interop.Sys.IPAddress* nativeAddresses = stackalloc Interop.Sys.IPAddress[hostEntry.AddressInfoCount + hostEntry.InterfaceAddressCount]; int nativeAddressCount = 0; - Interop.Sys.addrinfo* addrInfoHandle = hostEntry.AddressListHandle; - for (int i = 0; i < hostEntry.IPAddressCount; i++) + Interop.Sys.addrinfo* addrInfoHandle = hostEntry.AddressInfoListHandle; + for (int i = 0; i < hostEntry.AddressInfoCount; i++) { - Interop.Sys.IPAddress nativeIPAddress = default; - int err = Interop.Sys.GetNextIPAddress_AddrInfo(&hostEntry, &addrInfoHandle, &nativeIPAddress); - Debug.Assert(err == 0); - - if (Array.IndexOf(nativeAddresses, nativeIPAddress, 0, nativeAddressCount) == -1) + int err = Interop.Sys.GetNextIPAddress_AddrInfo(&hostEntry, &addrInfoHandle, &(nativeAddresses[nativeAddressCount])); + if (new Span(nativeAddresses, nativeAddressCount).IndexOf(nativeAddresses[nativeAddressCount]) == -1) { - nativeAddresses[nativeAddressCount++] = nativeIPAddress; + nativeAddressCount++; } + Debug.Assert(err == 0); } - Interop.Sys.ifaddrs* ifAddrsHandle = hostInterfaces.AddressListHandle; - for (int i = 0; i < hostInterfaces.IPAddressCount; i++) + Interop.Sys.ifaddrs* ifAddrsHandle = hostEntry.InterfaceAddressListHandle; + for (int i = 0; i < hostEntry.InterfaceAddressCount; i++) { - Interop.Sys.IPAddress nativeIPAddress = default; - int err = Interop.Sys.GetNextIPAddress_IfAddrs(&hostInterfaces, &ifAddrsHandle, &nativeIPAddress); - Debug.Assert(err == 0); - - if (Array.IndexOf(nativeAddresses, nativeIPAddress, 0, nativeAddressCount) == -1) + int err = Interop.Sys.GetNextIPAddress_IfAddrs(&hostEntry, &ifAddrsHandle, &(nativeAddresses[nativeAddressCount])); + if (new Span(nativeAddresses, nativeAddressCount).IndexOf(nativeAddresses[nativeAddressCount]) == -1) { - nativeAddresses[nativeAddressCount++] = nativeIPAddress; + nativeAddressCount++; } + Debug.Assert(err == 0); } localAddresses = new IPAddress[nativeAddressCount]; @@ -131,7 +127,6 @@ private static unsafe void ParseHostEntryAndInterfaces(Interop.Sys.HostEntry hos finally { Interop.Sys.FreeHostEntry(&hostEntry); - Interop.Sys.FreeHostInterfaces(&hostInterfaces); } } @@ -145,7 +140,7 @@ public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, } Interop.Sys.HostEntry entry; - int result = Interop.Sys.GetHostEntryForName(name, &entry); + int result = Interop.Sys.GetHostEntryForName(name, &entry, name == localHostName ? 1 : 0); if (result != 0) { nativeErrorCode = result; @@ -155,25 +150,7 @@ public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, return GetSocketErrorForNativeError(result); } - Interop.Sys.HostInterfaces interfaces; - if (name == localHostName) - { - result = Interop.Sys.GetHostInterfaces(&interfaces); - if (result != 0) - { - nativeErrorCode = result; - hostName = name; - aliases = Array.Empty(); - addresses = Array.Empty(); - return GetSocketErrorForNativeError(result); - } - } - else - { - interfaces = new Interop.Sys.HostInterfaces(); - } - - ParseHostEntryAndInterfaces(entry, interfaces, justAddresses, out hostName, out aliases, out addresses); + ParseHostEntry(entry, justAddresses, out hostName, out aliases, out addresses); nativeErrorCode = 0; return SocketError.Success; } diff --git a/src/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj b/src/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj index 74aab45c7dba..174a69812f43 100644 --- a/src/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj +++ b/src/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj @@ -157,9 +157,6 @@ Interop\Unix\System.Native\Interop.HostEntry.cs - - Interop\Unix\System.Native\Interop.HostInterfaces.cs - Interop\Unix\System.Native\Interop.IPAddress.cs From dba4a46b75eea2347c029a7a64e6fb63482c7daf Mon Sep 17 00:00:00 2001 From: manicka Date: Tue, 8 Oct 2019 23:16:09 +0200 Subject: [PATCH 07/16] pal_networking returns IPAddress array instead of original lists. --- .../Unix/System.Native/Interop.HostEntry.cs | 6 +- .../Unix/System.Native/pal_networking.c | 144 ++++++------------ .../Unix/System.Native/pal_networking.h | 10 +- .../src/System/Net/NameResolutionPal.Unix.cs | 25 +-- 4 files changed, 56 insertions(+), 129 deletions(-) diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index 2c8edc874048..b68382799a8b 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -39,10 +39,8 @@ internal unsafe struct HostEntry { internal byte* CanonicalName; // Canonical Name of the Host internal byte** Aliases; // List of aliases for the host - internal addrinfo* AddressInfoListHandle; // Handle for socket address list - internal int AddressInfoCount; // Number of IP addresses in the list - internal ifaddrs* InterfaceAddressListHandle; // Handle for interface addresses - internal int InterfaceAddressCount; // Number of IP end points in the interaface list + internal IPAddress* AddressList; // Handle for socket address list + internal uint AddressCount; // Number of IP addresses in the list } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostEntryForName")] diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index 4d8028461144..ede4b03eb3d4 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -250,10 +250,8 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr entry->CanonicalName = NULL; entry->Aliases = NULL; - entry->AddressInfoListHandle = info; - entry->AddressInfoCount = 0; - entry->InterfaceAddressListHandle = NULL; - entry->InterfaceAddressCount = 0; + entry->AddressList = NULL; + entry->AddressCount = 0; // Find the canonical name for this host (if any) and count the number of IP end points. for (struct addrinfo* ai = info; ai != NULL; ai = ai->ai_next) @@ -266,22 +264,20 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { - entry->AddressInfoCount++; + entry->AddressCount++; } } + struct ifaddrs *addrs = NULL; if (includeInterfaces != 0) { #if HAVE_GETIFADDRS // Get all interface addresses if the host name corresponds to the local host. - struct ifaddrs *addrs = NULL; result = getifaddrs(&addrs); // If getifaddrs fails, just skip it, the data are no crucial for the result. if (result == 0) { - entry->InterfaceAddressListHandle = addrs; - // Count the number of IP end points. for (struct ifaddrs* ifa = addrs; ifa != NULL; ifa = ifa->ifa_next) { @@ -292,129 +288,81 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) { - entry->InterfaceAddressCount++; + entry->AddressCount++; } } } #endif } - return GetAddrInfoErrorFlags_EAI_SUCCESS; -} + if (entry->AddressCount > 0) + { + entry->AddressList = (IPAddress*)malloc(entry->AddressCount*sizeof(IPAddress)); -static int32_t GetNextIPAddressFromAddrInfo(struct addrinfo** addrInfo, IPAddress* endPoint) -{ - assert(addrInfo != NULL); - assert(endPoint != NULL); + IPAddress* addressList = entry->AddressList; - for (struct addrinfo* ai = *addrInfo; ai != NULL; ai = ai->ai_next) - { - switch (ai->ai_family) + for (struct addrinfo* ai = info; ai != NULL; ai = ai->ai_next) { - case AF_INET: + if (ai->ai_family == AF_INET) { struct sockaddr_in* inetSockAddr = (struct sockaddr_in*)ai->ai_addr; - ConvertInAddrToByteArray(endPoint->Address, NUM_BYTES_IN_IPV4_ADDRESS, &inetSockAddr->sin_addr); - endPoint->IsIPv6 = 0; - break; + ConvertInAddrToByteArray(addressList->Address, NUM_BYTES_IN_IPV4_ADDRESS, &inetSockAddr->sin_addr); + addressList->IsIPv6 = 0; + ++addressList; + continue; } - - case AF_INET6: + if (ai->ai_family == AF_INET6) { struct sockaddr_in6* inet6SockAddr = (struct sockaddr_in6*)ai->ai_addr; - ConvertIn6AddrToByteArray(endPoint->Address, NUM_BYTES_IN_IPV6_ADDRESS, &inet6SockAddr->sin6_addr); - endPoint->IsIPv6 = 1; - endPoint->ScopeId = inet6SockAddr->sin6_scope_id; - break; - } - - default: - // Skip non-IPv4 and non-IPv6 addresses + ConvertIn6AddrToByteArray(addressList->Address, NUM_BYTES_IN_IPV6_ADDRESS, &inet6SockAddr->sin6_addr); + addressList->IsIPv6 = 1; + addressList->ScopeId = inet6SockAddr->sin6_scope_id; + ++addressList; continue; + } } - *addrInfo = ai->ai_next; - return GetAddrInfoErrorFlags_EAI_SUCCESS; - } - - return GetAddrInfoErrorFlags_EAI_NOMORE; -} - -int32_t SystemNative_GetNextIPAddress_AddrInfo(const HostEntry* entry, struct addrinfo** addressInfoListHandle, IPAddress* endPoint) -{ - if (entry == NULL || addressInfoListHandle == NULL || endPoint == NULL) - { - return GetAddrInfoErrorFlags_EAI_BADARG; - } - - return GetNextIPAddressFromAddrInfo(addressInfoListHandle, endPoint); -} - -static int32_t GetNextIPAddressFromIfAddrs(struct ifaddrs** ifAddrs, IPAddress* endPoint) -{ -#if HAVE_GETIFADDRS - assert(ifAddrs != NULL); - assert(endPoint != NULL); - - for (struct ifaddrs* ifa = *ifAddrs; ifa != NULL; ifa = ifa->ifa_next) - { - if (ifa->ifa_addr == NULL) - continue; - - switch (ifa->ifa_addr->sa_family) + if (addrs != NULL) { - case AF_INET: + for (struct ifaddrs* ifa = addrs; ifa != NULL; ifa = ifa->ifa_next) { - struct sockaddr_in* inetSockAddr = (struct sockaddr_in*)ifa->ifa_addr; + if (ifa->ifa_addr == NULL) + continue; - ConvertInAddrToByteArray(endPoint->Address, NUM_BYTES_IN_IPV4_ADDRESS, &inetSockAddr->sin_addr); - endPoint->IsIPv6 = 0; - break; - } + if (ifa->ifa_addr->sa_family == AF_INET) + { + struct sockaddr_in* inetSockAddr = (struct sockaddr_in*)ifa->ifa_addr; - case AF_INET6: - { - struct sockaddr_in6* inet6SockAddr = (struct sockaddr_in6*)ifa->ifa_addr; + ConvertInAddrToByteArray(addressList->Address, NUM_BYTES_IN_IPV4_ADDRESS, &inetSockAddr->sin_addr); + addressList->IsIPv6 = 0; + ++addressList; + continue; + } - ConvertIn6AddrToByteArray(endPoint->Address, NUM_BYTES_IN_IPV6_ADDRESS, &inet6SockAddr->sin6_addr); - endPoint->IsIPv6 = 1; - endPoint->ScopeId = inet6SockAddr->sin6_scope_id; - break; - } + if (ifa->ifa_addr->sa_family == AF_INET6) + { + struct sockaddr_in6* inet6SockAddr = (struct sockaddr_in6*)ifa->ifa_addr; - default: - // Skip non-IPv4 and non-IPv6 addresses - continue; + ConvertIn6AddrToByteArray(addressList->Address, NUM_BYTES_IN_IPV6_ADDRESS, &inet6SockAddr->sin6_addr); + addressList->IsIPv6 = 1; + addressList->ScopeId = inet6SockAddr->sin6_scope_id; + ++addressList; + continue; + } + } } - - *ifAddrs = ifa->ifa_next; - return GetAddrInfoErrorFlags_EAI_SUCCESS; } -#endif - return GetAddrInfoErrorFlags_EAI_NOMORE; -} -int32_t SystemNative_GetNextIPAddress_IfAddrs(const HostEntry* entry, struct ifaddrs** interfaceAddressListHandle, IPAddress* endPoint) -{ - - if (entry == NULL || interfaceAddressListHandle == NULL || endPoint == NULL) - { - return GetAddrInfoErrorFlags_EAI_BADARG; - } - - return GetNextIPAddressFromIfAddrs(interfaceAddressListHandle, endPoint); + return GetAddrInfoErrorFlags_EAI_SUCCESS; } void SystemNative_FreeHostEntry(HostEntry* entry) { if (entry != NULL) - { - freeaddrinfo(entry->AddressInfoListHandle); -#if HAVE_GETIFADDRS - freeifaddrs(entry->InterfaceAddressListHandle); -#endif + { + free(entry->AddressList); } } diff --git a/src/Native/Unix/System.Native/pal_networking.h b/src/Native/Unix/System.Native/pal_networking.h index afbe506e6d75..113ea1dc73ac 100644 --- a/src/Native/Unix/System.Native/pal_networking.h +++ b/src/Native/Unix/System.Native/pal_networking.h @@ -251,10 +251,8 @@ typedef struct { uint8_t* CanonicalName; // Canonical name of the host uint8_t** Aliases; // List of aliases for the host - struct addrinfo* AddressInfoListHandle; // Handle for host socket addresses - int32_t AddressInfoCount; // Number of IP end points in the socket address list - struct ifaddrs* InterfaceAddressListHandle; // Handle for interface addresses - int32_t InterfaceAddressCount; // Number of IP end points in the interaface list + IPAddress* AddressList; // Handle for host socket addresses + uint32_t AddressCount; // Number of IP end points in the socket address list } HostEntry; typedef struct @@ -313,10 +311,6 @@ typedef struct DLLEXPORT int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry, int32_t includeInterfaces); -DLLEXPORT int32_t SystemNative_GetNextIPAddress_AddrInfo(const HostEntry* entry, struct addrinfo** addressInfoListHandle, IPAddress* endPoint); - -DLLEXPORT int32_t SystemNative_GetNextIPAddress_IfAddrs(const HostEntry* entry, struct ifaddrs** interfaceAddressListHandle, IPAddress* endPoint); - DLLEXPORT void SystemNative_FreeHostEntry(HostEntry* entry); diff --git a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs index c86d811f4a1b..0a69945e59da 100644 --- a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs +++ b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs @@ -53,7 +53,7 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool null; IPAddress[] localAddresses; - if (hostEntry.AddressInfoCount == 0 && hostEntry.InterfaceAddressCount == 0) + if (hostEntry.AddressCount == 0) { localAddresses = Array.Empty(); } @@ -70,29 +70,16 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool // is likely to involve extra allocations, hashing, etc., and so will probably be more expensive than // this one in the typical (short list) case. - Interop.Sys.IPAddress* nativeAddresses = stackalloc Interop.Sys.IPAddress[hostEntry.AddressInfoCount + hostEntry.InterfaceAddressCount]; + Interop.Sys.IPAddress* nativeAddresses = stackalloc Interop.Sys.IPAddress[(int)hostEntry.AddressCount]; int nativeAddressCount = 0; - Interop.Sys.addrinfo* addrInfoHandle = hostEntry.AddressInfoListHandle; - for (int i = 0; i < hostEntry.AddressInfoCount; i++) + Interop.Sys.IPAddress* addressHandle = hostEntry.AddressList; + for (int i = 0; i < hostEntry.AddressCount; i++) { - int err = Interop.Sys.GetNextIPAddress_AddrInfo(&hostEntry, &addrInfoHandle, &(nativeAddresses[nativeAddressCount])); - if (new Span(nativeAddresses, nativeAddressCount).IndexOf(nativeAddresses[nativeAddressCount]) == -1) + if (new Span(addressHandle, nativeAddressCount).IndexOf(addressHandle[i]) == -1) { - nativeAddressCount++; + nativeAddresses[nativeAddressCount++] = addressHandle[i]; } - Debug.Assert(err == 0); - } - - Interop.Sys.ifaddrs* ifAddrsHandle = hostEntry.InterfaceAddressListHandle; - for (int i = 0; i < hostEntry.InterfaceAddressCount; i++) - { - int err = Interop.Sys.GetNextIPAddress_IfAddrs(&hostEntry, &ifAddrsHandle, &(nativeAddresses[nativeAddressCount])); - if (new Span(nativeAddresses, nativeAddressCount).IndexOf(nativeAddresses[nativeAddressCount]) == -1) - { - nativeAddressCount++; - } - Debug.Assert(err == 0); } localAddresses = new IPAddress[nativeAddressCount]; From 4a9a7d4393aff11b96f7e7f0767e710ef8de83b5 Mon Sep 17 00:00:00 2001 From: manicka Date: Wed, 9 Oct 2019 11:30:06 +0200 Subject: [PATCH 08/16] GetHostName to C pal, fixed missing free. --- .../Unix/System.Native/Interop.HostEntry.cs | 8 +- .../Unix/System.Native/pal_networking.c | 142 ++++++++++-------- .../Unix/System.Native/pal_networking.h | 2 +- .../src/System/Net/NameResolutionPal.Unix.cs | 5 +- 4 files changed, 86 insertions(+), 71 deletions(-) diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index b68382799a8b..64009c7e88f6 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -44,13 +44,7 @@ internal unsafe struct HostEntry } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostEntryForName")] - internal static extern unsafe int GetHostEntryForName(string address, HostEntry* entrym, int includeInterfaces); - - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNextIPAddress_AddrInfo")] - internal static extern unsafe int GetNextIPAddress_AddrInfo(HostEntry* entry, addrinfo** addressInfoListHandle, IPAddress* endPoint); - - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNextIPAddress_IfAddrs")] - internal static extern unsafe int GetNextIPAddress_IfAddrs(HostEntry* entry, ifaddrs** interfaceAddressListHandle, IPAddress* endPoint); + internal static extern unsafe int GetHostEntryForName(string address, HostEntry* entry); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeHostEntry")] internal static extern unsafe void FreeHostEntry(HostEntry* entry); diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index ede4b03eb3d4..6150d5dc67d8 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -228,7 +228,7 @@ static int32_t ConvertGetAddrInfoAndGetNameInfoErrorsToPal(int32_t error) return -1; } -int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry, int32_t includeInterfaces) +int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry) { if (address == NULL || entry == NULL) { @@ -267,11 +267,12 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr entry->AddressCount++; } } - - struct ifaddrs *addrs = NULL; - if (includeInterfaces != 0) - { #if HAVE_GETIFADDRS + char name[HOST_NAME_MAX]; + result = gethostname((char*)name, HOST_NAME_MAX); + struct ifaddrs* addrs = NULL; + if (result == 0 && strcasecmp((const char*)address, name) == 0) + { // Get all interface addresses if the host name corresponds to the local host. result = getifaddrs(&addrs); @@ -292,12 +293,12 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr } } } -#endif } +#endif if (entry->AddressCount > 0) { - entry->AddressList = (IPAddress*)malloc(entry->AddressCount*sizeof(IPAddress)); + entry->AddressList = (IPAddress*)calloc(entry->AddressCount, sizeof(IPAddress)); IPAddress* addressList = entry->AddressList; @@ -323,7 +324,9 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr continue; } } + freeaddrinfo(info); +#if HAVE_GETIFADDRS if (addrs != NULL) { for (struct ifaddrs* ifa = addrs; ifa != NULL; ifa = ifa->ifa_next) @@ -352,7 +355,9 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr continue; } } + freeifaddrs(addrs); } +#endif } return GetAddrInfoErrorFlags_EAI_SUCCESS; @@ -389,13 +394,13 @@ static inline NativeFlagsType ConvertGetNameInfoFlagsToNative(int32_t flags) } int32_t SystemNative_GetNameInfo(const uint8_t* address, - int32_t addressLength, - int8_t isIPv6, - uint8_t* host, - int32_t hostLength, - uint8_t* service, - int32_t serviceLength, - int32_t flags) + int32_t addressLength, + int8_t isIPv6, + uint8_t* host, + int32_t hostLength, + uint8_t* service, + int32_t serviceLength, + int32_t flags) { assert(address != NULL); assert(addressLength > 0); @@ -452,7 +457,7 @@ int32_t SystemNative_GetDomainName(uint8_t* name, int32_t nameLength) // On Android, there's no getdomainname but we can use uname to fetch the domain name // of the current device size_t namelen = (uint32_t)nameLength; - utsname uts; + utsname uts; // If uname returns an error, bail out. if (uname(&uts) == -1) @@ -810,8 +815,7 @@ static int8_t IsStreamSocket(int socket) { int type; socklen_t length = sizeof(int); - return getsockopt(socket, SOL_SOCKET, SO_TYPE, &type, &length) == 0 - && type == SOCK_STREAM; + return getsockopt(socket, SOL_SOCKET, SO_TYPE, &type, &length) == 0 && type == SOCK_STREAM; } static void ConvertMessageHeaderToMsghdr(struct msghdr* header, const MessageHeader* messageHeader, int socket) @@ -838,7 +842,8 @@ int32_t SystemNative_GetControlMessageBufferSize(int32_t isIPv4, int32_t isIPv6) // Note: it is possible that the address family of the socket is neither // AF_INET nor AF_INET6. In this case both inputs will be 0 and // the controll message buffer size should be zero. - return (isIPv4 != 0 ? CMSG_SPACE(sizeof(struct in_pktinfo)) : 0) + (isIPv6 != 0 ? CMSG_SPACE(sizeof(struct in6_pktinfo)) : 0); + return (isIPv4 != 0 ? CMSG_SPACE(sizeof(struct in_pktinfo)) : 0) + + (isIPv6 != 0 ? CMSG_SPACE(sizeof(struct in6_pktinfo)) : 0); } static int32_t GetIPv4PacketInformation(struct cmsghdr* controlMessage, IPPacketInformation* packetInfo) @@ -1280,7 +1285,8 @@ int32_t SystemNative_ReceiveMessage(intptr_t socket, MessageHeader* messageHeade ConvertMessageHeaderToMsghdr(&header, messageHeader, fd); ssize_t res; - while ((res = recvmsg(fd, &header, socketFlags)) < 0 && errno == EINTR); + while ((res = recvmsg(fd, &header, socketFlags)) < 0 && errno == EINTR) + ; assert(header.msg_name == messageHeader->SocketAddress); // should still be the same location as set in ConvertMessageHeaderToMsghdr assert(header.msg_control == messageHeader->ControlBuffer); @@ -1325,9 +1331,11 @@ int32_t SystemNative_SendMessage(intptr_t socket, MessageHeader* messageHeader, ssize_t res; #if defined(__APPLE__) && __APPLE__ // possible OSX kernel bug: #31927 - while ((res = sendmsg(fd, &header, socketFlags)) < 0 && (errno == EINTR || errno == EPROTOTYPE)); + while ((res = sendmsg(fd, &header, socketFlags)) < 0 && (errno == EINTR || errno == EPROTOTYPE)) + ; #else - while ((res = sendmsg(fd, &header, socketFlags)) < 0 && errno == EINTR); + while ((res = sendmsg(fd, &header, socketFlags)) < 0 && errno == EINTR) + ; #endif if (res != -1) { @@ -1339,7 +1347,8 @@ int32_t SystemNative_SendMessage(intptr_t socket, MessageHeader* messageHeader, return SystemNative_ConvertErrorPlatformToPal(errno); } -int32_t SystemNative_Accept(intptr_t socket, uint8_t* socketAddress, int32_t* socketAddressLen, intptr_t* acceptedSocket) +int32_t +SystemNative_Accept(intptr_t socket, uint8_t* socketAddress, int32_t* socketAddressLen, intptr_t* acceptedSocket) { if (socketAddress == NULL || socketAddressLen == NULL || acceptedSocket == NULL || *socketAddressLen < 0) { @@ -1351,9 +1360,11 @@ int32_t SystemNative_Accept(intptr_t socket, uint8_t* socketAddress, int32_t* so socklen_t addrLen = (socklen_t)*socketAddressLen; int accepted; #if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) - while ((accepted = accept4(fd, (struct sockaddr*)socketAddress, &addrLen, SOCK_CLOEXEC)) < 0 && errno == EINTR); + while ((accepted = accept4(fd, (struct sockaddr*)socketAddress, &addrLen, SOCK_CLOEXEC)) < 0 && errno == EINTR) + ; #else - while ((accepted = accept(fd, (struct sockaddr*)socketAddress, &addrLen)) < 0 && errno == EINTR); + while ((accepted = accept(fd, (struct sockaddr*)socketAddress, &addrLen)) < 0 && errno == EINTR) + ; #if defined(FD_CLOEXEC) // macOS does not have accept4 but it can set _CLOEXEC on descriptor. // Unlike accept4 it is not atomic and the fd can leak child process. @@ -1395,7 +1406,7 @@ int32_t SystemNative_Bind(intptr_t socket, int32_t protocolType, uint8_t* socket if (socketAddress == NULL || socketAddressLen < 0) { return Error_EFAULT; - } + } int fd = ToFileDescriptor(socket); @@ -1429,7 +1440,8 @@ int32_t SystemNative_Connect(intptr_t socket, uint8_t* socketAddress, int32_t so int fd = ToFileDescriptor(socket); int err; - while ((err = connect(fd, (struct sockaddr*)socketAddress, (socklen_t)socketAddressLen)) < 0 && errno == EINTR); + while ((err = connect(fd, (struct sockaddr*)socketAddress, (socklen_t)socketAddressLen)) < 0 && errno == EINTR) + ; return err == 0 ? Error_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno); } @@ -1564,7 +1576,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO *optName = SO_BROADCAST; return true; - // case SocketOptionName_SO_USELOOPBACK: + // case SocketOptionName_SO_USELOOPBACK: case SocketOptionName_SO_LINGER: *optName = SO_LINGER; @@ -1574,9 +1586,9 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO *optName = SO_OOBINLINE; return true; - // case SocketOptionName_SO_DONTLINGER: + // case SocketOptionName_SO_DONTLINGER: - // case SocketOptionName_SO_EXCLUSIVEADDRUSE: + // case SocketOptionName_SO_EXCLUSIVEADDRUSE: case SocketOptionName_SO_SNDBUF: *optName = SO_SNDBUF; @@ -1610,7 +1622,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO *optName = SO_TYPE; return true; - // case SocketOptionName_SO_MAXCONN: + // case SocketOptionName_SO_MAXCONN: default: return false; @@ -1704,7 +1716,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO *optName = IPV6_HOPLIMIT; return true; - // case SocketOptionName_SO_IPV6_PROTECTION_LEVEL: + // case SocketOptionName_SO_IPV6_PROTECTION_LEVEL: case SocketOptionName_SO_IPV6_V6ONLY: *optName = IPV6_V6ONLY; @@ -1738,7 +1750,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO *optName = TCP_NODELAY; return true; - // case SocketOptionName_SO_TCP_BSDURGENT: + // case SocketOptionName_SO_TCP_BSDURGENT: case SocketOptionName_SO_TCP_KEEPALIVE_RETRYCOUNT: *optName = TCP_KEEPCNT; @@ -1746,11 +1758,11 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO case SocketOptionName_SO_TCP_KEEPALIVE_TIME: *optName = - #if HAVE_TCP_H_TCP_KEEPALIVE +#if HAVE_TCP_H_TCP_KEEPALIVE TCP_KEEPALIVE; - #else +#else TCP_KEEPIDLE; - #endif +#endif return true; case SocketOptionName_SO_TCP_KEEPALIVE_INTERVAL: @@ -1766,13 +1778,13 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO switch (socketOptionLevel) { - // case SocketOptionName_SO_UDP_NOCHECKSUM: + // case SocketOptionName_SO_UDP_NOCHECKSUM: - // case SocketOptionName_SO_UDP_CHECKSUM_COVERAGE: + // case SocketOptionName_SO_UDP_CHECKSUM_COVERAGE: - // case SocketOptionName_SO_UDP_UPDATEACCEPTCONTEXT: + // case SocketOptionName_SO_UDP_UPDATEACCEPTCONTEXT: - // case SocketOptionName_SO_UDP_UPDATECONNECTCONTEXT: + // case SocketOptionName_SO_UDP_UPDATECONNECTCONTEXT: default: return false; @@ -2028,7 +2040,7 @@ static bool TryConvertProtocolTypePalToPlatform(int32_t palAddressFamily, int32_ { assert(platformProtocolType != NULL); - switch(palAddressFamily) + switch (palAddressFamily) { #ifdef AF_PACKET case AddressFamily_AF_PACKET: @@ -2083,7 +2095,7 @@ static bool TryConvertProtocolTypePalToPlatform(int32_t palAddressFamily, int32_ default: *platformProtocolType = (int)palProtocolType; return false; - } + } case AddressFamily_AF_INET6: switch (palProtocolType) @@ -2201,7 +2213,8 @@ int32_t SystemNative_GetAtOutOfBandMark(intptr_t socket, int32_t* atMark) int result; int err; - while ((err = ioctl(fd, SIOCATMARK, &result)) < 0 && errno == EINTR); + while ((err = ioctl(fd, SIOCATMARK, &result)) < 0 && errno == EINTR) + ; if (err == -1) { *atMark = 0; @@ -2223,7 +2236,8 @@ int32_t SystemNative_GetBytesAvailable(intptr_t socket, int32_t* available) int result; int err; - while ((err = ioctl(fd, FIONREAD, &result)) < 0 && errno == EINTR); + while ((err = ioctl(fd, FIONREAD, &result)) < 0 && errno == EINTR) + ; if (err == -1) { *available = 0; @@ -2240,17 +2254,21 @@ static const size_t SocketEventBufferElementSize = sizeof(struct epoll_event) > static int GetSocketEvents(uint32_t events) { - int asyncEvents = (((events & EPOLLIN) != 0) ? SocketEvents_SA_READ : 0) | (((events & EPOLLOUT) != 0) ? SocketEvents_SA_WRITE : 0) | + int asyncEvents = (((events & EPOLLIN) != 0) ? SocketEvents_SA_READ : 0) | + (((events & EPOLLOUT) != 0) ? SocketEvents_SA_WRITE : 0) | (((events & EPOLLRDHUP) != 0) ? SocketEvents_SA_READCLOSE : 0) | - (((events & EPOLLHUP) != 0) ? SocketEvents_SA_CLOSE : 0) | (((events & EPOLLERR) != 0) ? SocketEvents_SA_ERROR : 0); + (((events & EPOLLHUP) != 0) ? SocketEvents_SA_CLOSE : 0) | + (((events & EPOLLERR) != 0) ? SocketEvents_SA_ERROR : 0); return asyncEvents; } static uint32_t GetEPollEvents(SocketEvents events) { - return (((events & SocketEvents_SA_READ) != 0) ? EPOLLIN : 0) | (((events & SocketEvents_SA_WRITE) != 0) ? EPOLLOUT : 0) | - (((events & SocketEvents_SA_READCLOSE) != 0) ? EPOLLRDHUP : 0) | (((events & SocketEvents_SA_CLOSE) != 0) ? EPOLLHUP : 0) | + return (((events & SocketEvents_SA_READ) != 0) ? EPOLLIN : 0) | + (((events & SocketEvents_SA_WRITE) != 0) ? EPOLLOUT : 0) | + (((events & SocketEvents_SA_READCLOSE) != 0) ? EPOLLRDHUP : 0) | + (((events & SocketEvents_SA_CLOSE) != 0) ? EPOLLHUP : 0) | (((events & SocketEvents_SA_ERROR) != 0) ? EPOLLERR : 0); } @@ -2326,7 +2344,8 @@ static int32_t WaitForSocketEventsInner(int32_t port, SocketEvent* buffer, int32 struct epoll_event* events = (struct epoll_event*)buffer; int numEvents; - while ((numEvents = epoll_wait(port, events, *count, -1)) < 0 && errno == EINTR); + while ((numEvents = epoll_wait(port, events, *count, -1)) < 0 && errno == EINTR) + ; if (numEvents == -1) { *count = 0; @@ -2466,7 +2485,8 @@ static int32_t TryChangeSocketEventRegistrationInner( // As a workaround use separate kevent() calls. if (writeChanged) { - while ((err = kevent(port, events, GetKeventNchanges(i), NULL, 0, NULL)) < 0 && errno == EINTR); + while ((err = kevent(port, events, GetKeventNchanges(i), NULL, 0, NULL)) < 0 && errno == EINTR) + ; if (err != 0) { return SystemNative_ConvertErrorPlatformToPal(errno); @@ -2487,7 +2507,8 @@ static int32_t TryChangeSocketEventRegistrationInner( GetKeventUdata(data)); } - while ((err = kevent(port, events, GetKeventNchanges(i), NULL, 0, NULL)) < 0 && errno == EINTR); + while ((err = kevent(port, events, GetKeventNchanges(i), NULL, 0, NULL)) < 0 && errno == EINTR) + ; return err == 0 ? Error_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno); } @@ -2499,7 +2520,8 @@ static int32_t WaitForSocketEventsInner(int32_t port, SocketEvent* buffer, int32 struct kevent* events = (struct kevent*)buffer; int numEvents; - while ((numEvents = kevent(port, NULL, 0, events, GetKeventNchanges(*count), NULL)) < 0 && errno == EINTR); + while ((numEvents = kevent(port, NULL, 0, events, GetKeventNchanges(*count), NULL)) < 0 && errno == EINTR) + ; if (numEvents == -1) { *count = -1; @@ -2543,8 +2565,7 @@ static int32_t CreateSocketEventPortInner(int32_t* port) return Error_ENOSYS; } static int32_t TryChangeSocketEventRegistrationInner( - int32_t port, int32_t socket, SocketEvents currentEvents, SocketEvents newEvents, -uintptr_t data) + int32_t port, int32_t socket, SocketEvents currentEvents, SocketEvents newEvents, uintptr_t data) { return Error_ENOSYS; } @@ -2644,7 +2665,7 @@ static char* GetNameFromUid(uid_t uid) size_t bufferLength = 512; while (1) { - char *buffer = (char*)malloc(bufferLength); + char* buffer = (char*)malloc(bufferLength); if (buffer == NULL) return NULL; @@ -2679,9 +2700,7 @@ static char* GetNameFromUid(uid_t uid) char* SystemNative_GetPeerUserName(intptr_t socket) { uid_t euid; - return SystemNative_GetPeerID(socket, &euid) == 0 ? - GetNameFromUid(euid) : - NULL; + return SystemNative_GetPeerID(socket, &euid) == 0 ? GetNameFromUid(euid) : NULL; } void SystemNative_GetDomainSocketSizes(int32_t* pathOffset, int32_t* pathSize, int32_t* addressSize) @@ -2733,7 +2752,8 @@ int32_t SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, i off_t offtOffset = (off_t)offset; ssize_t res; - while ((res = sendfile(outfd, infd, &offtOffset, (size_t)count)) < 0 && errno == EINTR); + while ((res = sendfile(outfd, infd, &offtOffset, (size_t)count)) < 0 && errno == EINTR) + ; if (res != -1) { *sent = res; @@ -2770,10 +2790,12 @@ int32_t SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, i // If we actually transferred everything in spite of the error, return success. assert(count >= 0); - if (count == 0) return Error_SUCCESS; + if (count == 0) + return Error_SUCCESS; // For EINTR, loop around and go again. - if (errno == EINTR) continue; + if (errno == EINTR) + continue; } // For everything other than EINTR, bail. diff --git a/src/Native/Unix/System.Native/pal_networking.h b/src/Native/Unix/System.Native/pal_networking.h index 113ea1dc73ac..74c1d6b8bd71 100644 --- a/src/Native/Unix/System.Native/pal_networking.h +++ b/src/Native/Unix/System.Native/pal_networking.h @@ -309,7 +309,7 @@ typedef struct uint32_t Padding; // Pad out to 8-byte alignment } SocketEvent; -DLLEXPORT int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry, int32_t includeInterfaces); +DLLEXPORT int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry); DLLEXPORT void SystemNative_FreeHostEntry(HostEntry* entry); diff --git a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs index 0a69945e59da..a0c11baee28d 100644 --- a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs +++ b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs @@ -119,15 +119,14 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool public static unsafe SocketError TryGetAddrInfo(string name, bool justAddresses, out string hostName, out string[] aliases, out IPAddress[] addresses, out int nativeErrorCode) { - string localHostName = Dns.GetHostName(); if (name == "") { // To match documented behavior on Windows, if an empty string is passed in, use the local host's name. - name = localHostName; + name = Dns.GetHostName(); } Interop.Sys.HostEntry entry; - int result = Interop.Sys.GetHostEntryForName(name, &entry, name == localHostName ? 1 : 0); + int result = Interop.Sys.GetHostEntryForName(name, &entry); if (result != 0) { nativeErrorCode = result; From 6698096cf767a143e5f4ab862585595871a497e8 Mon Sep 17 00:00:00 2001 From: manicka Date: Thu, 10 Oct 2019 16:39:16 +0200 Subject: [PATCH 09/16] Reverted accidental formatting change, clean up. --- .../Unix/System.Native/Interop.HostEntry.cs | 11 -- .../Unix/System.Native/pal_networking.c | 127 ++++++++---------- 2 files changed, 55 insertions(+), 83 deletions(-) diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index 64009c7e88f6..de34d945597b 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -23,17 +23,6 @@ internal enum GetAddrInfoErrorFlags : int EAI_NOMORE = 7, // No more entries are present in the list. } - //opaque structure to maintain consistency with native function signature - internal unsafe struct addrinfo - { - - } - //opaque structure to maintain consistency with native function signature - internal unsafe struct ifaddrs - { - - } - [StructLayout(LayoutKind.Sequential)] internal unsafe struct HostEntry { diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index 6150d5dc67d8..35b4dbc01ab8 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -324,7 +324,7 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr continue; } } - freeaddrinfo(info); + freeaddrinfo(info); #if HAVE_GETIFADDRS if (addrs != NULL) @@ -355,7 +355,7 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr continue; } } - freeifaddrs(addrs); + freeifaddrs(addrs); } #endif } @@ -394,13 +394,13 @@ static inline NativeFlagsType ConvertGetNameInfoFlagsToNative(int32_t flags) } int32_t SystemNative_GetNameInfo(const uint8_t* address, - int32_t addressLength, - int8_t isIPv6, - uint8_t* host, - int32_t hostLength, - uint8_t* service, - int32_t serviceLength, - int32_t flags) + int32_t addressLength, + int8_t isIPv6, + uint8_t* host, + int32_t hostLength, + uint8_t* service, + int32_t serviceLength, + int32_t flags) { assert(address != NULL); assert(addressLength > 0); @@ -457,7 +457,7 @@ int32_t SystemNative_GetDomainName(uint8_t* name, int32_t nameLength) // On Android, there's no getdomainname but we can use uname to fetch the domain name // of the current device size_t namelen = (uint32_t)nameLength; - utsname uts; + utsname uts; // If uname returns an error, bail out. if (uname(&uts) == -1) @@ -815,7 +815,8 @@ static int8_t IsStreamSocket(int socket) { int type; socklen_t length = sizeof(int); - return getsockopt(socket, SOL_SOCKET, SO_TYPE, &type, &length) == 0 && type == SOCK_STREAM; + return getsockopt(socket, SOL_SOCKET, SO_TYPE, &type, &length) == 0 + && type == SOCK_STREAM; } static void ConvertMessageHeaderToMsghdr(struct msghdr* header, const MessageHeader* messageHeader, int socket) @@ -842,8 +843,7 @@ int32_t SystemNative_GetControlMessageBufferSize(int32_t isIPv4, int32_t isIPv6) // Note: it is possible that the address family of the socket is neither // AF_INET nor AF_INET6. In this case both inputs will be 0 and // the controll message buffer size should be zero. - return (isIPv4 != 0 ? CMSG_SPACE(sizeof(struct in_pktinfo)) : 0) + - (isIPv6 != 0 ? CMSG_SPACE(sizeof(struct in6_pktinfo)) : 0); + return (isIPv4 != 0 ? CMSG_SPACE(sizeof(struct in_pktinfo)) : 0) + (isIPv6 != 0 ? CMSG_SPACE(sizeof(struct in6_pktinfo)) : 0); } static int32_t GetIPv4PacketInformation(struct cmsghdr* controlMessage, IPPacketInformation* packetInfo) @@ -1285,8 +1285,7 @@ int32_t SystemNative_ReceiveMessage(intptr_t socket, MessageHeader* messageHeade ConvertMessageHeaderToMsghdr(&header, messageHeader, fd); ssize_t res; - while ((res = recvmsg(fd, &header, socketFlags)) < 0 && errno == EINTR) - ; + while ((res = recvmsg(fd, &header, socketFlags)) < 0 && errno == EINTR); assert(header.msg_name == messageHeader->SocketAddress); // should still be the same location as set in ConvertMessageHeaderToMsghdr assert(header.msg_control == messageHeader->ControlBuffer); @@ -1331,11 +1330,9 @@ int32_t SystemNative_SendMessage(intptr_t socket, MessageHeader* messageHeader, ssize_t res; #if defined(__APPLE__) && __APPLE__ // possible OSX kernel bug: #31927 - while ((res = sendmsg(fd, &header, socketFlags)) < 0 && (errno == EINTR || errno == EPROTOTYPE)) - ; + while ((res = sendmsg(fd, &header, socketFlags)) < 0 && (errno == EINTR || errno == EPROTOTYPE)); #else - while ((res = sendmsg(fd, &header, socketFlags)) < 0 && errno == EINTR) - ; + while ((res = sendmsg(fd, &header, socketFlags)) < 0 && errno == EINTR); #endif if (res != -1) { @@ -1347,8 +1344,7 @@ int32_t SystemNative_SendMessage(intptr_t socket, MessageHeader* messageHeader, return SystemNative_ConvertErrorPlatformToPal(errno); } -int32_t -SystemNative_Accept(intptr_t socket, uint8_t* socketAddress, int32_t* socketAddressLen, intptr_t* acceptedSocket) +int32_t SystemNative_Accept(intptr_t socket, uint8_t* socketAddress, int32_t* socketAddressLen, intptr_t* acceptedSocket) { if (socketAddress == NULL || socketAddressLen == NULL || acceptedSocket == NULL || *socketAddressLen < 0) { @@ -1360,11 +1356,9 @@ SystemNative_Accept(intptr_t socket, uint8_t* socketAddress, int32_t* socketAddr socklen_t addrLen = (socklen_t)*socketAddressLen; int accepted; #if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) - while ((accepted = accept4(fd, (struct sockaddr*)socketAddress, &addrLen, SOCK_CLOEXEC)) < 0 && errno == EINTR) - ; + while ((accepted = accept4(fd, (struct sockaddr*)socketAddress, &addrLen, SOCK_CLOEXEC)) < 0 && errno == EINTR); #else - while ((accepted = accept(fd, (struct sockaddr*)socketAddress, &addrLen)) < 0 && errno == EINTR) - ; + while ((accepted = accept(fd, (struct sockaddr*)socketAddress, &addrLen)) < 0 && errno == EINTR); #if defined(FD_CLOEXEC) // macOS does not have accept4 but it can set _CLOEXEC on descriptor. // Unlike accept4 it is not atomic and the fd can leak child process. @@ -1406,7 +1400,7 @@ int32_t SystemNative_Bind(intptr_t socket, int32_t protocolType, uint8_t* socket if (socketAddress == NULL || socketAddressLen < 0) { return Error_EFAULT; - } + } int fd = ToFileDescriptor(socket); @@ -1440,8 +1434,7 @@ int32_t SystemNative_Connect(intptr_t socket, uint8_t* socketAddress, int32_t so int fd = ToFileDescriptor(socket); int err; - while ((err = connect(fd, (struct sockaddr*)socketAddress, (socklen_t)socketAddressLen)) < 0 && errno == EINTR) - ; + while ((err = connect(fd, (struct sockaddr*)socketAddress, (socklen_t)socketAddressLen)) < 0 && errno == EINTR); return err == 0 ? Error_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno); } @@ -1576,7 +1569,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO *optName = SO_BROADCAST; return true; - // case SocketOptionName_SO_USELOOPBACK: + // case SocketOptionName_SO_USELOOPBACK: case SocketOptionName_SO_LINGER: *optName = SO_LINGER; @@ -1586,9 +1579,9 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO *optName = SO_OOBINLINE; return true; - // case SocketOptionName_SO_DONTLINGER: + // case SocketOptionName_SO_DONTLINGER: - // case SocketOptionName_SO_EXCLUSIVEADDRUSE: + // case SocketOptionName_SO_EXCLUSIVEADDRUSE: case SocketOptionName_SO_SNDBUF: *optName = SO_SNDBUF; @@ -1622,7 +1615,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO *optName = SO_TYPE; return true; - // case SocketOptionName_SO_MAXCONN: + // case SocketOptionName_SO_MAXCONN: default: return false; @@ -1716,7 +1709,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO *optName = IPV6_HOPLIMIT; return true; - // case SocketOptionName_SO_IPV6_PROTECTION_LEVEL: + // case SocketOptionName_SO_IPV6_PROTECTION_LEVEL: case SocketOptionName_SO_IPV6_V6ONLY: *optName = IPV6_V6ONLY; @@ -1750,7 +1743,7 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO *optName = TCP_NODELAY; return true; - // case SocketOptionName_SO_TCP_BSDURGENT: + // case SocketOptionName_SO_TCP_BSDURGENT: case SocketOptionName_SO_TCP_KEEPALIVE_RETRYCOUNT: *optName = TCP_KEEPCNT; @@ -1758,11 +1751,11 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO case SocketOptionName_SO_TCP_KEEPALIVE_TIME: *optName = -#if HAVE_TCP_H_TCP_KEEPALIVE + #if HAVE_TCP_H_TCP_KEEPALIVE TCP_KEEPALIVE; -#else + #else TCP_KEEPIDLE; -#endif + #endif return true; case SocketOptionName_SO_TCP_KEEPALIVE_INTERVAL: @@ -1778,13 +1771,13 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO switch (socketOptionLevel) { - // case SocketOptionName_SO_UDP_NOCHECKSUM: + // case SocketOptionName_SO_UDP_NOCHECKSUM: - // case SocketOptionName_SO_UDP_CHECKSUM_COVERAGE: + // case SocketOptionName_SO_UDP_CHECKSUM_COVERAGE: - // case SocketOptionName_SO_UDP_UPDATEACCEPTCONTEXT: + // case SocketOptionName_SO_UDP_UPDATEACCEPTCONTEXT: - // case SocketOptionName_SO_UDP_UPDATECONNECTCONTEXT: + // case SocketOptionName_SO_UDP_UPDATECONNECTCONTEXT: default: return false; @@ -2040,7 +2033,7 @@ static bool TryConvertProtocolTypePalToPlatform(int32_t palAddressFamily, int32_ { assert(platformProtocolType != NULL); - switch (palAddressFamily) + switch(palAddressFamily) { #ifdef AF_PACKET case AddressFamily_AF_PACKET: @@ -2095,7 +2088,7 @@ static bool TryConvertProtocolTypePalToPlatform(int32_t palAddressFamily, int32_ default: *platformProtocolType = (int)palProtocolType; return false; - } + } case AddressFamily_AF_INET6: switch (palProtocolType) @@ -2213,8 +2206,7 @@ int32_t SystemNative_GetAtOutOfBandMark(intptr_t socket, int32_t* atMark) int result; int err; - while ((err = ioctl(fd, SIOCATMARK, &result)) < 0 && errno == EINTR) - ; + while ((err = ioctl(fd, SIOCATMARK, &result)) < 0 && errno == EINTR); if (err == -1) { *atMark = 0; @@ -2236,8 +2228,7 @@ int32_t SystemNative_GetBytesAvailable(intptr_t socket, int32_t* available) int result; int err; - while ((err = ioctl(fd, FIONREAD, &result)) < 0 && errno == EINTR) - ; + while ((err = ioctl(fd, FIONREAD, &result)) < 0 && errno == EINTR); if (err == -1) { *available = 0; @@ -2254,21 +2245,17 @@ static const size_t SocketEventBufferElementSize = sizeof(struct epoll_event) > static int GetSocketEvents(uint32_t events) { - int asyncEvents = (((events & EPOLLIN) != 0) ? SocketEvents_SA_READ : 0) | - (((events & EPOLLOUT) != 0) ? SocketEvents_SA_WRITE : 0) | + int asyncEvents = (((events & EPOLLIN) != 0) ? SocketEvents_SA_READ : 0) | (((events & EPOLLOUT) != 0) ? SocketEvents_SA_WRITE : 0) | (((events & EPOLLRDHUP) != 0) ? SocketEvents_SA_READCLOSE : 0) | - (((events & EPOLLHUP) != 0) ? SocketEvents_SA_CLOSE : 0) | - (((events & EPOLLERR) != 0) ? SocketEvents_SA_ERROR : 0); + (((events & EPOLLHUP) != 0) ? SocketEvents_SA_CLOSE : 0) | (((events & EPOLLERR) != 0) ? SocketEvents_SA_ERROR : 0); return asyncEvents; } static uint32_t GetEPollEvents(SocketEvents events) { - return (((events & SocketEvents_SA_READ) != 0) ? EPOLLIN : 0) | - (((events & SocketEvents_SA_WRITE) != 0) ? EPOLLOUT : 0) | - (((events & SocketEvents_SA_READCLOSE) != 0) ? EPOLLRDHUP : 0) | - (((events & SocketEvents_SA_CLOSE) != 0) ? EPOLLHUP : 0) | + return (((events & SocketEvents_SA_READ) != 0) ? EPOLLIN : 0) | (((events & SocketEvents_SA_WRITE) != 0) ? EPOLLOUT : 0) | + (((events & SocketEvents_SA_READCLOSE) != 0) ? EPOLLRDHUP : 0) | (((events & SocketEvents_SA_CLOSE) != 0) ? EPOLLHUP : 0) | (((events & SocketEvents_SA_ERROR) != 0) ? EPOLLERR : 0); } @@ -2344,8 +2331,7 @@ static int32_t WaitForSocketEventsInner(int32_t port, SocketEvent* buffer, int32 struct epoll_event* events = (struct epoll_event*)buffer; int numEvents; - while ((numEvents = epoll_wait(port, events, *count, -1)) < 0 && errno == EINTR) - ; + while ((numEvents = epoll_wait(port, events, *count, -1)) < 0 && errno == EINTR); if (numEvents == -1) { *count = 0; @@ -2485,8 +2471,7 @@ static int32_t TryChangeSocketEventRegistrationInner( // As a workaround use separate kevent() calls. if (writeChanged) { - while ((err = kevent(port, events, GetKeventNchanges(i), NULL, 0, NULL)) < 0 && errno == EINTR) - ; + while ((err = kevent(port, events, GetKeventNchanges(i), NULL, 0, NULL)) < 0 && errno == EINTR); if (err != 0) { return SystemNative_ConvertErrorPlatformToPal(errno); @@ -2507,8 +2492,7 @@ static int32_t TryChangeSocketEventRegistrationInner( GetKeventUdata(data)); } - while ((err = kevent(port, events, GetKeventNchanges(i), NULL, 0, NULL)) < 0 && errno == EINTR) - ; + while ((err = kevent(port, events, GetKeventNchanges(i), NULL, 0, NULL)) < 0 && errno == EINTR); return err == 0 ? Error_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno); } @@ -2520,8 +2504,7 @@ static int32_t WaitForSocketEventsInner(int32_t port, SocketEvent* buffer, int32 struct kevent* events = (struct kevent*)buffer; int numEvents; - while ((numEvents = kevent(port, NULL, 0, events, GetKeventNchanges(*count), NULL)) < 0 && errno == EINTR) - ; + while ((numEvents = kevent(port, NULL, 0, events, GetKeventNchanges(*count), NULL)) < 0 && errno == EINTR); if (numEvents == -1) { *count = -1; @@ -2565,7 +2548,8 @@ static int32_t CreateSocketEventPortInner(int32_t* port) return Error_ENOSYS; } static int32_t TryChangeSocketEventRegistrationInner( - int32_t port, int32_t socket, SocketEvents currentEvents, SocketEvents newEvents, uintptr_t data) + int32_t port, int32_t socket, SocketEvents currentEvents, SocketEvents newEvents, +uintptr_t data) { return Error_ENOSYS; } @@ -2665,7 +2649,7 @@ static char* GetNameFromUid(uid_t uid) size_t bufferLength = 512; while (1) { - char* buffer = (char*)malloc(bufferLength); + char *buffer = (char*)malloc(bufferLength); if (buffer == NULL) return NULL; @@ -2700,7 +2684,9 @@ static char* GetNameFromUid(uid_t uid) char* SystemNative_GetPeerUserName(intptr_t socket) { uid_t euid; - return SystemNative_GetPeerID(socket, &euid) == 0 ? GetNameFromUid(euid) : NULL; + return SystemNative_GetPeerID(socket, &euid) == 0 ? + GetNameFromUid(euid) : + NULL; } void SystemNative_GetDomainSocketSizes(int32_t* pathOffset, int32_t* pathSize, int32_t* addressSize) @@ -2752,8 +2738,7 @@ int32_t SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, i off_t offtOffset = (off_t)offset; ssize_t res; - while ((res = sendfile(outfd, infd, &offtOffset, (size_t)count)) < 0 && errno == EINTR) - ; + while ((res = sendfile(outfd, infd, &offtOffset, (size_t)count)) < 0 && errno == EINTR); if (res != -1) { *sent = res; @@ -2790,12 +2775,10 @@ int32_t SystemNative_SendFile(intptr_t out_fd, intptr_t in_fd, int64_t offset, i // If we actually transferred everything in spite of the error, return success. assert(count >= 0); - if (count == 0) - return Error_SUCCESS; + if (count == 0) return Error_SUCCESS; // For EINTR, loop around and go again. - if (errno == EINTR) - continue; + if (errno == EINTR) continue; } // For everything other than EINTR, bail. From a9719afdea38f431517d53a3b8138a8f98ddcbc3 Mon Sep 17 00:00:00 2001 From: manicka Date: Sun, 13 Oct 2019 15:55:18 +0200 Subject: [PATCH 10/16] Formatting --- src/Native/Unix/System.Native/pal_networking.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Native/Unix/System.Native/pal_networking.h b/src/Native/Unix/System.Native/pal_networking.h index 74c1d6b8bd71..2dcb1921fc6c 100644 --- a/src/Native/Unix/System.Native/pal_networking.h +++ b/src/Native/Unix/System.Native/pal_networking.h @@ -251,8 +251,8 @@ typedef struct { uint8_t* CanonicalName; // Canonical name of the host uint8_t** Aliases; // List of aliases for the host - IPAddress* AddressList; // Handle for host socket addresses - uint32_t AddressCount; // Number of IP end points in the socket address list + IPAddress* AddressList; // Handle for host socket addresses + uint32_t AddressCount; // Number of IP end points in the socket address list } HostEntry; typedef struct From 21eb28480152d8df9249f61eb700b0be0a69acf3 Mon Sep 17 00:00:00 2001 From: manicka Date: Mon, 14 Oct 2019 15:57:55 +0200 Subject: [PATCH 11/16] Fixed NameResolution tests. --- .../src/Interop/Unix/System.Native/Interop.HostEntry.cs | 4 ++-- src/Native/Unix/System.Native/pal_networking.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index de34d945597b..56090a4dcf90 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -26,8 +26,8 @@ internal enum GetAddrInfoErrorFlags : int [StructLayout(LayoutKind.Sequential)] internal unsafe struct HostEntry { - internal byte* CanonicalName; // Canonical Name of the Host - internal byte** Aliases; // List of aliases for the host + internal byte* CanonicalName; // Canonical Name of the Host + internal byte** Aliases; // List of aliases for the host internal IPAddress* AddressList; // Handle for socket address list internal uint AddressCount; // Number of IP addresses in the list } diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index 35b4dbc01ab8..e37d53a2a6cb 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -259,7 +259,7 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr // If we haven't found a canonical name yet and this addrinfo has one, copy it if ((entry->CanonicalName == NULL) && (ai->ai_canonname != NULL)) { - entry->CanonicalName = (uint8_t*)ai->ai_canonname; + entry->CanonicalName = (uint8_t*)strdup(ai->ai_canonname); } if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) @@ -368,6 +368,7 @@ void SystemNative_FreeHostEntry(HostEntry* entry) if (entry != NULL) { free(entry->AddressList); + free(entry->CanonicalName); } } From cdc83f3f4b049d6ddb5a3cbda149c824aebb4790 Mon Sep 17 00:00:00 2001 From: manicka Date: Mon, 14 Oct 2019 17:31:01 +0200 Subject: [PATCH 12/16] Fixed OSX compilation --- src/Native/Unix/System.Native/pal_networking.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index e37d53a2a6cb..10c5f1f5dbb8 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -138,6 +138,8 @@ enum INET6_ADDRSTRLEN_MANAGED = 65 // Managed code has a longer max IPv6 string length }; +#define MAX_HOST_NAME 255 + c_static_assert(GetHostErrorCodes_HOST_NOT_FOUND == HOST_NOT_FOUND); c_static_assert(GetHostErrorCodes_TRY_AGAIN == TRY_AGAIN); c_static_assert(GetHostErrorCodes_NO_RECOVERY == NO_RECOVERY); @@ -267,9 +269,10 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr entry->AddressCount++; } } + #if HAVE_GETIFADDRS - char name[HOST_NAME_MAX]; - result = gethostname((char*)name, HOST_NAME_MAX); + char name[MAX_HOST_NAME + 1]; + result = gethostname((char*)name, MAX_HOST_NAME); struct ifaddrs* addrs = NULL; if (result == 0 && strcasecmp((const char*)address, name) == 0) { From 4d1682f5f4af650ebb9b925b55cd763dd438a99c Mon Sep 17 00:00:00 2001 From: manicka Date: Wed, 16 Oct 2019 08:58:09 +0200 Subject: [PATCH 13/16] Addressing PR comments --- .../Interop/Unix/System.Native/Interop.HostEntry.cs | 1 + src/Native/Unix/System.Native/pal_networking.c | 13 +++++++++++-- src/Native/Unix/System.Native/pal_networking.h | 1 + .../src/System/Net/NameResolutionPal.Unix.cs | 6 ++++-- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index 56090a4dcf90..946a610cc6ef 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -21,6 +21,7 @@ internal enum GetAddrInfoErrorFlags : int EAI_NONAME = 5, // NAME or SERVICE is unknown. EAI_BADARG = 6, // One or more input arguments were invalid. EAI_NOMORE = 7, // No more entries are present in the list. + EAI_MEMORY = 8, // Out of memory. } [StructLayout(LayoutKind.Sequential)] diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index 10c5f1f5dbb8..954443ec231f 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -219,6 +219,8 @@ static int32_t ConvertGetAddrInfoAndGetNameInfoErrorsToPal(int32_t error) #endif case EAI_FAMILY: return GetAddrInfoErrorFlags_EAI_FAMILY; + case EAI_MEMORY: + return GetAddrInfoErrorFlags_EAI_MEMORY; case EAI_NONAME: #ifdef EAI_NODATA case EAI_NODATA: @@ -262,6 +264,10 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr if ((entry->CanonicalName == NULL) && (ai->ai_canonname != NULL)) { entry->CanonicalName = (uint8_t*)strdup(ai->ai_canonname); + if (entry->CanonicalName == NULL) + { + ConvertGetAddrInfoAndGetNameInfoErrorsToPal(EAI_MEMORY); + } } if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) @@ -279,7 +285,7 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr // Get all interface addresses if the host name corresponds to the local host. result = getifaddrs(&addrs); - // If getifaddrs fails, just skip it, the data are no crucial for the result. + // If getifaddrs fails, just skip it, the data are not crucial for the result. if (result == 0) { // Count the number of IP end points. @@ -302,6 +308,10 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr if (entry->AddressCount > 0) { entry->AddressList = (IPAddress*)calloc(entry->AddressCount, sizeof(IPAddress)); + if (entry->AddressList == NULL) + { + ConvertGetAddrInfoAndGetNameInfoErrorsToPal(EAI_MEMORY); + } IPAddress* addressList = entry->AddressList; @@ -346,7 +356,6 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr ++addressList; continue; } - if (ifa->ifa_addr->sa_family == AF_INET6) { struct sockaddr_in6* inet6SockAddr = (struct sockaddr_in6*)ifa->ifa_addr; diff --git a/src/Native/Unix/System.Native/pal_networking.h b/src/Native/Unix/System.Native/pal_networking.h index 2dcb1921fc6c..c33adc3a1be0 100644 --- a/src/Native/Unix/System.Native/pal_networking.h +++ b/src/Native/Unix/System.Native/pal_networking.h @@ -22,6 +22,7 @@ typedef enum GetAddrInfoErrorFlags_EAI_NONAME = 5, // NAME or SERVICE is unknown. GetAddrInfoErrorFlags_EAI_BADARG = 6, // One or more input arguments were invalid. GetAddrInfoErrorFlags_EAI_NOMORE = 7, // No more entries are present in the list. + GetAddrInfoErrorFlags_EAI_MEMORY = 8, // Out of memory. } GetAddrInfoErrorFlags; /** diff --git a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs index a0c11baee28d..0d76488d348b 100644 --- a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs +++ b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs @@ -38,6 +38,8 @@ private static SocketError GetSocketErrorForNativeError(int error) return SocketError.AddressFamilyNotSupported; case (int)Interop.Sys.GetAddrInfoErrorFlags.EAI_NONAME: return SocketError.HostNotFound; + case (int)Interop.Sys.GetAddrInfoErrorFlags.EAI_MEMORY: + throw new OutOfMemoryException(); default: Debug.Fail("Unexpected error: " + error.ToString()); return SocketError.SocketError; @@ -70,13 +72,13 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool // is likely to involve extra allocations, hashing, etc., and so will probably be more expensive than // this one in the typical (short list) case. - Interop.Sys.IPAddress* nativeAddresses = stackalloc Interop.Sys.IPAddress[(int)hostEntry.AddressCount]; + Interop.Sys.IPAddress[] nativeAddresses = new Interop.Sys.IPAddress[(int)hostEntry.AddressCount]; int nativeAddressCount = 0; Interop.Sys.IPAddress* addressHandle = hostEntry.AddressList; for (int i = 0; i < hostEntry.AddressCount; i++) { - if (new Span(addressHandle, nativeAddressCount).IndexOf(addressHandle[i]) == -1) + if (Array.IndexOf(nativeAddresses, addressHandle[i], 0, nativeAddressCount) == -1) { nativeAddresses[nativeAddressCount++] = addressHandle[i]; } From 110a24e07b30b5ced215e58e017b969bddf54b60 Mon Sep 17 00:00:00 2001 From: manicka Date: Thu, 17 Oct 2019 15:50:58 +0200 Subject: [PATCH 14/16] Addressed PR comments --- .../Unix/System.Native/Interop.HostEntry.cs | 8 +- .../Unix/System.Native/pal_networking.c | 88 +++++++++---------- .../Unix/System.Native/pal_networking.h | 8 +- .../src/System/Net/NameResolutionPal.Unix.cs | 8 +- 4 files changed, 52 insertions(+), 60 deletions(-) diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index 946a610cc6ef..4f36e43edb17 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -27,10 +27,10 @@ internal enum GetAddrInfoErrorFlags : int [StructLayout(LayoutKind.Sequential)] internal unsafe struct HostEntry { - internal byte* CanonicalName; // Canonical Name of the Host - internal byte** Aliases; // List of aliases for the host - internal IPAddress* AddressList; // Handle for socket address list - internal uint AddressCount; // Number of IP addresses in the list + internal byte* CanonicalName; // Canonical Name of the Host + internal byte** Aliases; // List of aliases for the host + internal IPAddress* IPAddressList; // Handle for socket address list + internal int IPAddressCount; // Number of IP addresses in the list } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostEntryForName")] diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index 954443ec231f..493c83b64830 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -138,8 +138,6 @@ enum INET6_ADDRSTRLEN_MANAGED = 65 // Managed code has a longer max IPv6 string length }; -#define MAX_HOST_NAME 255 - c_static_assert(GetHostErrorCodes_HOST_NOT_FOUND == HOST_NOT_FOUND); c_static_assert(GetHostErrorCodes_TRY_AGAIN == TRY_AGAIN); c_static_assert(GetHostErrorCodes_NO_RECOVERY == NO_RECOVERY); @@ -232,13 +230,36 @@ static int32_t ConvertGetAddrInfoAndGetNameInfoErrorsToPal(int32_t error) return -1; } +static int32_t CopySockAddrToIPAddress(sockaddr* addr, sa_family_t family, IPAddress* ipAddress) +{ + if (family == AF_INET) + { + struct sockaddr_in* inetSockAddr = (struct sockaddr_in*)addr; + + ConvertInAddrToByteArray(ipAddress->Address, NUM_BYTES_IN_IPV4_ADDRESS, &inetSockAddr->sin_addr); + ipAddress->IsIPv6 = 0; + return 0; + } + else if (family == AF_INET6) + { + struct sockaddr_in6* inet6SockAddr = (struct sockaddr_in6*)addr; + + ConvertIn6AddrToByteArray(ipAddress->Address, NUM_BYTES_IN_IPV6_ADDRESS, &inet6SockAddr->sin6_addr); + ipAddress->IsIPv6 = 1; + ipAddress->ScopeId = inet6SockAddr->sin6_scope_id; + return 0; + } + + return -1; +} + int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entry) { if (address == NULL || entry == NULL) { return GetAddrInfoErrorFlags_EAI_BADARG; } - + // Get all address families and the canonical name struct addrinfo hint; memset(&hint, 0, sizeof(struct addrinfo)); @@ -254,8 +275,8 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr entry->CanonicalName = NULL; entry->Aliases = NULL; - entry->AddressList = NULL; - entry->AddressCount = 0; + entry->IPAddressList = NULL; + entry->IPAddressCount = 0; // Find the canonical name for this host (if any) and count the number of IP end points. for (struct addrinfo* ai = info; ai != NULL; ai = ai->ai_next) @@ -272,13 +293,14 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { - entry->AddressCount++; + entry->IPAddressCount++; } } #if HAVE_GETIFADDRS - char name[MAX_HOST_NAME + 1]; - result = gethostname((char*)name, MAX_HOST_NAME); + char name[_POSIX_HOST_NAME_MAX]; + result = gethostname((char*)name, _POSIX_HOST_NAME_MAX); + struct ifaddrs* addrs = NULL; if (result == 0 && strcasecmp((const char*)address, name) == 0) { @@ -298,43 +320,28 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) { - entry->AddressCount++; + entry->IPAddressCount++; } } } } #endif - if (entry->AddressCount > 0) + if (entry->IPAddressCount > 0) { - entry->AddressList = (IPAddress*)calloc(entry->AddressCount, sizeof(IPAddress)); - if (entry->AddressList == NULL) + entry->IPAddressList = (IPAddress*)calloc((size_t)entry->IPAddressCount, sizeof(IPAddress)); + if (entry->IPAddressList == NULL) { ConvertGetAddrInfoAndGetNameInfoErrorsToPal(EAI_MEMORY); } - IPAddress* addressList = entry->AddressList; + IPAddress* ipAddressList = entry->IPAddressList; for (struct addrinfo* ai = info; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family == AF_INET) + if (CopySockAddrToIPAddress(ai->ai_addr, (sa_family_t)ai->ai_family, ipAddressList) == 0) { - struct sockaddr_in* inetSockAddr = (struct sockaddr_in*)ai->ai_addr; - - ConvertInAddrToByteArray(addressList->Address, NUM_BYTES_IN_IPV4_ADDRESS, &inetSockAddr->sin_addr); - addressList->IsIPv6 = 0; - ++addressList; - continue; - } - if (ai->ai_family == AF_INET6) - { - struct sockaddr_in6* inet6SockAddr = (struct sockaddr_in6*)ai->ai_addr; - - ConvertIn6AddrToByteArray(addressList->Address, NUM_BYTES_IN_IPV6_ADDRESS, &inet6SockAddr->sin6_addr); - addressList->IsIPv6 = 1; - addressList->ScopeId = inet6SockAddr->sin6_scope_id; - ++addressList; - continue; + ++ipAddressList; } } freeaddrinfo(info); @@ -347,24 +354,9 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr if (ifa->ifa_addr == NULL) continue; - if (ifa->ifa_addr->sa_family == AF_INET) + if (CopySockAddrToIPAddress(ifa->ifa_addr, ifa->ifa_addr->sa_family, ipAddressList) == 0) { - struct sockaddr_in* inetSockAddr = (struct sockaddr_in*)ifa->ifa_addr; - - ConvertInAddrToByteArray(addressList->Address, NUM_BYTES_IN_IPV4_ADDRESS, &inetSockAddr->sin_addr); - addressList->IsIPv6 = 0; - ++addressList; - continue; - } - if (ifa->ifa_addr->sa_family == AF_INET6) - { - struct sockaddr_in6* inet6SockAddr = (struct sockaddr_in6*)ifa->ifa_addr; - - ConvertIn6AddrToByteArray(addressList->Address, NUM_BYTES_IN_IPV6_ADDRESS, &inet6SockAddr->sin6_addr); - addressList->IsIPv6 = 1; - addressList->ScopeId = inet6SockAddr->sin6_scope_id; - ++addressList; - continue; + ++ipAddressList; } } freeifaddrs(addrs); @@ -379,7 +371,7 @@ void SystemNative_FreeHostEntry(HostEntry* entry) { if (entry != NULL) { - free(entry->AddressList); + free(entry->IPAddressList); free(entry->CanonicalName); } } diff --git a/src/Native/Unix/System.Native/pal_networking.h b/src/Native/Unix/System.Native/pal_networking.h index c33adc3a1be0..e92f39a0f07f 100644 --- a/src/Native/Unix/System.Native/pal_networking.h +++ b/src/Native/Unix/System.Native/pal_networking.h @@ -250,10 +250,10 @@ typedef struct typedef struct { - uint8_t* CanonicalName; // Canonical name of the host - uint8_t** Aliases; // List of aliases for the host - IPAddress* AddressList; // Handle for host socket addresses - uint32_t AddressCount; // Number of IP end points in the socket address list + uint8_t* CanonicalName; // Canonical name of the host + uint8_t** Aliases; // List of aliases for the host + IPAddress* IPAddressList; // Handle for host socket addresses + int32_t IPAddressCount; // Number of IP end points in the socket address list } HostEntry; typedef struct diff --git a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs index 0d76488d348b..437d87586caf 100644 --- a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs +++ b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs @@ -55,7 +55,7 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool null; IPAddress[] localAddresses; - if (hostEntry.AddressCount == 0) + if (hostEntry.IPAddressCount == 0) { localAddresses = Array.Empty(); } @@ -72,11 +72,11 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool // is likely to involve extra allocations, hashing, etc., and so will probably be more expensive than // this one in the typical (short list) case. - Interop.Sys.IPAddress[] nativeAddresses = new Interop.Sys.IPAddress[(int)hostEntry.AddressCount]; + Interop.Sys.IPAddress[] nativeAddresses = new Interop.Sys.IPAddress[hostEntry.IPAddressCount]; int nativeAddressCount = 0; - Interop.Sys.IPAddress* addressHandle = hostEntry.AddressList; - for (int i = 0; i < hostEntry.AddressCount; i++) + Interop.Sys.IPAddress* addressHandle = hostEntry.IPAddressList; + for (int i = 0; i < hostEntry.IPAddressCount; i++) { if (Array.IndexOf(nativeAddresses, addressHandle[i], 0, nativeAddressCount) == -1) { From f06697e916971119bcba7a1c972e2d622ee234f9 Mon Sep 17 00:00:00 2001 From: manicka Date: Mon, 21 Oct 2019 17:32:52 +0200 Subject: [PATCH 15/16] Try to mimic mono behavior. --- .../Unix/System.Native/pal_networking.c | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index 493c83b64830..950b2294e6d8 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -300,6 +300,8 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr #if HAVE_GETIFADDRS char name[_POSIX_HOST_NAME_MAX]; result = gethostname((char*)name, _POSIX_HOST_NAME_MAX); + bool includeIPv4Loopback = true; + bool includeIPv6Loopback = true; struct ifaddrs* addrs = NULL; if (result == 0 && strcasecmp((const char*)address, name) == 0) @@ -318,8 +320,31 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr continue; } - if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) + // Skip the interface if it isn't UP. + if ((ifa->ifa_flags & IFF_UP) == 0) { + continue; + } + + if (ifa->ifa_addr->sa_family == AF_INET) + { + // Remember if there's at least one non-loopback address for IPv4, so that they will be skipped. + if ((ifa->ifa_flags & IFF_LOOPBACK) == 0) + { + includeIPv4Loopback = false; + } + + entry->IPAddressCount++; + } + + if (ifa->ifa_addr->sa_family == AF_INET6) + { + // Remember if there's at least one non-loopback address for IPv6, so that they will be skipped. + if ((ifa->ifa_flags & IFF_LOOPBACK) == 0) + { + includeIPv6Loopback = false; + } + entry->IPAddressCount++; } } @@ -352,7 +377,23 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr for (struct ifaddrs* ifa = addrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) + { + continue; + } + + // Skip the interface if it isn't UP. + if ((ifa->ifa_flags & IFF_UP) == 0) + { continue; + } + + // Skip loopback addresses if at least one interface has non-loopback one. + if ((!includeIPv4Loopback && ifa->ifa_addr->sa_family == AF_INET && (ifa->ifa_flags & IFF_LOOPBACK) != 0) || + (!includeIPv6Loopback && ifa->ifa_addr->sa_family == AF_INET6 && (ifa->ifa_flags & IFF_LOOPBACK) != 0)) + { + --entry->IPAddressCount; + continue; + } if (CopySockAddrToIPAddress(ifa->ifa_addr, ifa->ifa_addr->sa_family, ipAddressList) == 0) { From 4b411c54f4820b24b5c7025e6a8afb10e9f36469 Mon Sep 17 00:00:00 2001 From: manicka Date: Thu, 31 Oct 2019 11:27:34 +0100 Subject: [PATCH 16/16] Addressed PR comments --- .../Unix/System.Native/pal_networking.c | 52 ++++++++++++++----- .../src/System/Net/NameResolutionPal.Unix.cs | 2 +- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index 2ca9450576d1..60aac3ae5366 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -260,13 +260,19 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr return GetAddrInfoErrorFlags_EAI_BADARG; } + int32_t ret = GetAddrInfoErrorFlags_EAI_SUCCESS; + + struct addrinfo* info = NULL; +#if HAVE_GETIFADDRS + struct ifaddrs* addrs = NULL; +#endif + // Get all address families and the canonical name struct addrinfo hint; memset(&hint, 0, sizeof(struct addrinfo)); hint.ai_family = AF_UNSPEC; hint.ai_flags = AI_CANONNAME; - struct addrinfo* info = NULL; int result = getaddrinfo((const char*)address, NULL, &hint, &info); if (result != 0) { @@ -287,7 +293,8 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr entry->CanonicalName = (uint8_t*)strdup(ai->ai_canonname); if (entry->CanonicalName == NULL) { - ConvertGetAddrInfoAndGetNameInfoErrorsToPal(EAI_MEMORY); + ret = ConvertGetAddrInfoAndGetNameInfoErrorsToPal(EAI_MEMORY); + goto cleanup; } } @@ -300,10 +307,10 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr #if HAVE_GETIFADDRS char name[_POSIX_HOST_NAME_MAX]; result = gethostname((char*)name, _POSIX_HOST_NAME_MAX); + bool includeIPv4Loopback = true; bool includeIPv6Loopback = true; - struct ifaddrs* addrs = NULL; if (result == 0 && strcasecmp((const char*)address, name) == 0) { // Get all interface addresses if the host name corresponds to the local host. @@ -336,8 +343,7 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr entry->IPAddressCount++; } - - if (ifa->ifa_addr->sa_family == AF_INET6) + else if (ifa->ifa_addr->sa_family == AF_INET6) { // Remember if there's at least one non-loopback address for IPv6, so that they will be skipped. if ((ifa->ifa_flags & IFF_LOOPBACK) == 0) @@ -357,7 +363,8 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr entry->IPAddressList = (IPAddress*)calloc((size_t)entry->IPAddressCount, sizeof(IPAddress)); if (entry->IPAddressList == NULL) { - ConvertGetAddrInfoAndGetNameInfoErrorsToPal(EAI_MEMORY); + ret = ConvertGetAddrInfoAndGetNameInfoErrorsToPal(EAI_MEMORY); + goto cleanup; } IPAddress* ipAddressList = entry->IPAddressList; @@ -369,7 +376,6 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr ++ipAddressList; } } - freeaddrinfo(info); #if HAVE_GETIFADDRS if (addrs != NULL) @@ -391,7 +397,7 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr if ((!includeIPv4Loopback && ifa->ifa_addr->sa_family == AF_INET && (ifa->ifa_flags & IFF_LOOPBACK) != 0) || (!includeIPv6Loopback && ifa->ifa_addr->sa_family == AF_INET6 && (ifa->ifa_flags & IFF_LOOPBACK) != 0)) { - --entry->IPAddressCount; + entry->IPAddressCount--; continue; } @@ -400,20 +406,42 @@ int32_t SystemNative_GetHostEntryForName(const uint8_t* address, HostEntry* entr ++ipAddressList; } } - freeifaddrs(addrs); } #endif } - return GetAddrInfoErrorFlags_EAI_SUCCESS; +cleanup: + if (info != NULL) + { + freeaddrinfo(info); + } + +#if HAVE_GETIFADDRS + if (addrs != NULL) + { + freeifaddrs(addrs); + } +#endif + + // If the returned code is not success, the FreeHostEntry will not be called from the managed code. + if (ret != GetAddrInfoErrorFlags_EAI_SUCCESS) + { + SystemNative_FreeHostEntry(entry); + } + + return ret; } void SystemNative_FreeHostEntry(HostEntry* entry) { if (entry != NULL) - { - free(entry->IPAddressList); + { free(entry->CanonicalName); + free(entry->IPAddressList); + + entry->CanonicalName = NULL; + entry->IPAddressList = NULL; + entry->IPAddressCount = 0; } } diff --git a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs index 437d87586caf..ff923551b831 100644 --- a/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs +++ b/src/System.Net.NameResolution/src/System/Net/NameResolutionPal.Unix.cs @@ -72,7 +72,7 @@ private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool // is likely to involve extra allocations, hashing, etc., and so will probably be more expensive than // this one in the typical (short list) case. - Interop.Sys.IPAddress[] nativeAddresses = new Interop.Sys.IPAddress[hostEntry.IPAddressCount]; + var nativeAddresses = new Interop.Sys.IPAddress[hostEntry.IPAddressCount]; int nativeAddressCount = 0; Interop.Sys.IPAddress* addressHandle = hostEntry.IPAddressList;