initial support for new network protocols (dotnet/corefx#37315)
authorTomas Weinfurt <tweinfurt@yahoo.com>
Wed, 22 May 2019 18:31:10 +0000 (11:31 -0700)
committerGitHub <noreply@github.com>
Wed, 22 May 2019 18:31:10 +0000 (11:31 -0700)
* initial support for new network protocols

* feedback from review

* fix compilation of AF_CAN

Commit migrated from https://github.com/dotnet/corefx/commit/6f6790fa8219359f2acbe4b0624a3fa9a0a6943b

src/libraries/Common/src/System/Net/Sockets/ProtocolFamily.cs
src/libraries/Native/Unix/System.Native/pal_networking.c
src/libraries/Native/Unix/System.Native/pal_networking.h
src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs
src/libraries/System.Net.Primitives/src/System/Net/Sockets/AddressFamily.cs
src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs
src/libraries/System.Net.Sockets/tests/FunctionalTests/CreateSocketTests.cs
src/libraries/System.Net.Sockets/tests/FunctionalTests/CreateSocketTests.netcoreapp.cs [new file with mode: 0644]
src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj

index 735a730..513de29 100644 (file)
@@ -42,5 +42,8 @@ namespace System.Net.Internals
         Irda = AddressFamily.Irda,
         NetworkDesigners = AddressFamily.NetworkDesigners,
         Max = 29, //AddressFamily.Max
+        Netlink = AddressFamily.Netlink,
+        Packet = AddressFamily.Packet,
+        ControllerAreaNetwork = AddressFamily.ControllerAreaNetwork,
     }
 }
index 0412144..273f344 100644 (file)
@@ -55,7 +55,9 @@
 #include <ifaddrs.h>
 #endif
 #endif
-
+#ifdef AF_CAN
+#include <linux/can.h>
+#endif
 #if HAVE_KQUEUE
 #if KEVENT_HAS_VOID_UDATA
 static void* GetKeventUdata(uintptr_t udata)
@@ -490,7 +492,21 @@ static bool TryConvertAddressFamilyPlatformToPal(sa_family_t platformAddressFami
         case AF_INET6:
             *palAddressFamily = AddressFamily_AF_INET6;
             return true;
-
+#ifdef AF_NETLINK
+        case AF_NETLINK:
+            *palAddressFamily = AddressFamily_AF_NETLINK;
+            return true;
+#endif
+#ifdef AF_PACKET
+        case AF_PACKET:
+            *palAddressFamily = AddressFamily_AF_PACKET;
+            return true;
+#endif
+#ifdef AF_CAN
+        case AF_CAN:
+            *palAddressFamily = AddressFamily_AF_CAN;
+            return true;
+#endif
         default:
             *palAddressFamily = platformAddressFamily;
             return false;
@@ -518,7 +534,16 @@ static bool TryConvertAddressFamilyPalToPlatform(int32_t palAddressFamily, sa_fa
         case AddressFamily_AF_INET6:
             *platformAddressFamily = AF_INET6;
             return true;
-
+#ifdef AF_PACKET
+        case AddressFamily_AF_PACKET:
+            *platformAddressFamily = AF_PACKET;
+            return true;
+#endif
+#ifdef AF_CAN
+        case AddressFamily_AF_CAN:
+            *platformAddressFamily = AF_CAN;
+            return true;
+#endif
         default:
             *platformAddressFamily = (sa_family_t)palAddressFamily;
             return false;
@@ -1920,35 +1945,126 @@ static bool TryConvertSocketTypePalToPlatform(int32_t palSocketType, int* platfo
     }
 }
 
-static bool TryConvertProtocolTypePalToPlatform(int32_t palProtocolType, int* platformProtocolType)
+static bool TryConvertProtocolTypePalToPlatform(int32_t palAddressFamily, int32_t palProtocolType, int* platformProtocolType)
 {
     assert(platformProtocolType != NULL);
 
-    switch (palProtocolType)
+    switch(palAddressFamily)
     {
-        case ProtocolType_PT_UNSPECIFIED:
-            *platformProtocolType = 0;
+#ifdef AF_PACKET
+        case AddressFamily_AF_PACKET:
+            // protocol is the IEEE 802.3 protocol number in network order.
+            *platformProtocolType = palProtocolType;
             return true;
+#endif
+#ifdef AF_CAN
+        case AddressFamily_AF_CAN:
+            switch (palProtocolType)
+            {
+                case ProtocolType_PT_UNSPECIFIED:
+                    *platformProtocolType = 0;
+                    return true;
 
-        case ProtocolType_PT_ICMP:
-            *platformProtocolType = IPPROTO_ICMP;
-            return true;
+                case ProtocolType_PT_RAW:
+                    *platformProtocolType = CAN_RAW;
+                    return true;
 
-        case ProtocolType_PT_TCP:
-            *platformProtocolType = IPPROTO_TCP;
-            return true;
+                default:
+                    *platformProtocolType = (int)palProtocolType;
+                    return false;
+            }
+#endif
+        case AddressFamily_AF_INET:
+            switch (palProtocolType)
+            {
+                case ProtocolType_PT_UNSPECIFIED:
+                    *platformProtocolType = 0;
+                    return true;
 
-        case ProtocolType_PT_UDP:
-            *platformProtocolType = IPPROTO_UDP;
-            return true;
+                case ProtocolType_PT_ICMP:
+                    *platformProtocolType = IPPROTO_ICMP;
+                    return true;
 
-        case ProtocolType_PT_ICMPV6:
-            *platformProtocolType = IPPROTO_ICMPV6;
-            return true;
+                case ProtocolType_PT_TCP:
+                    *platformProtocolType = IPPROTO_TCP;
+                    return true;
+
+                case ProtocolType_PT_UDP:
+                    *platformProtocolType = IPPROTO_UDP;
+                    return true;
+
+                case ProtocolType_PT_IGMP:
+                    *platformProtocolType = IPPROTO_IGMP;
+                    return true;
+
+                case ProtocolType_PT_RAW:
+                    *platformProtocolType = IPPROTO_RAW;
+                    return true;
+
+                default:
+                    *platformProtocolType = (int)palProtocolType;
+                    return false;
+                }
+
+        case AddressFamily_AF_INET6:
+            switch (palProtocolType)
+            {
+                case ProtocolType_PT_UNSPECIFIED:
+                    *platformProtocolType = 0;
+                    return true;
+
+                case ProtocolType_PT_ICMPV6:
+                case ProtocolType_PT_ICMP:
+                    *platformProtocolType = IPPROTO_ICMPV6;
+                    return true;
+
+                case ProtocolType_PT_TCP:
+                    *platformProtocolType = IPPROTO_TCP;
+                    return true;
+
+                case ProtocolType_PT_UDP:
+                    *platformProtocolType = IPPROTO_UDP;
+                    return true;
+
+                case ProtocolType_PT_IGMP:
+                    *platformProtocolType = IPPROTO_IGMP;
+                    return true;
+
+                case ProtocolType_PT_RAW:
+                    *platformProtocolType = IPPROTO_RAW;
+                    return true;
+
+                case ProtocolType_PT_DSTOPTS:
+                    *platformProtocolType = IPPROTO_DSTOPTS;
+                    return true;
+
+                case ProtocolType_PT_NONE:
+                    *platformProtocolType = IPPROTO_NONE;
+                    return true;
+
+                case ProtocolType_PT_ROUTING:
+                    *platformProtocolType = IPPROTO_ROUTING;
+                    return true;
+
+                case ProtocolType_PT_FRAGMENT:
+                    *platformProtocolType = IPPROTO_FRAGMENT;
+                    return true;
+
+                default:
+                    *platformProtocolType = (int)palProtocolType;
+                    return false;
+            }
 
         default:
-            *platformProtocolType = (int)palProtocolType;
-            return false;
+            switch (palProtocolType)
+            {
+                case ProtocolType_PT_UNSPECIFIED:
+                    *platformProtocolType = 0;
+                    return true;
+                default:
+                    *platformProtocolType = (int)palProtocolType;
+                    return false;
+            }
     }
 }
 
@@ -1974,7 +2090,7 @@ int32_t SystemNative_Socket(int32_t addressFamily, int32_t socketType, int32_t p
         return Error_EPROTOTYPE;
     }
 
-    if (!TryConvertProtocolTypePalToPlatform(protocolType, &platformProtocolType))
+    if (!TryConvertProtocolTypePalToPlatform(addressFamily, protocolType, &platformProtocolType))
     {
         *createdSocket = -1;
         return Error_EPROTONOSUPPORT;
index 9bb8072..e739dd1 100644 (file)
@@ -56,10 +56,13 @@ typedef enum
  */
 typedef enum
 {
-    AddressFamily_AF_UNSPEC = 0, // System.Net.AddressFamily.Unspecified
-    AddressFamily_AF_UNIX = 1,   // System.Net.AddressFamily.Unix
-    AddressFamily_AF_INET = 2,   // System.Net.AddressFamily.InterNetwork
-    AddressFamily_AF_INET6 = 23, // System.Net.AddressFamily.InterNetworkV6
+    AddressFamily_AF_UNSPEC = 0,   // System.Net.AddressFamily.Unspecified
+    AddressFamily_AF_UNIX = 1,     // System.Net.AddressFamily.Unix
+    AddressFamily_AF_INET = 2,     // System.Net.AddressFamily.InterNetwork
+    AddressFamily_AF_INET6 = 23,   // System.Net.AddressFamily.InterNetworkV6
+    AddressFamily_AF_NETLINK = 30, // System.Net.AddressFamily.Netlink
+    AddressFamily_AF_PACKET = 31,  // System.Net.AddressFamily.Packet
+    AddressFamily_AF_CAN = 32,     // System.Net.AddressFamily.ControllerAreaNetwork
 } AddressFamily;
 
 /*
@@ -88,6 +91,12 @@ typedef enum
     ProtocolType_PT_TCP = 6,         // System.Net.ProtocolType.Tcp
     ProtocolType_PT_UDP = 17,        // System.Net.ProtocolType.Udp
     ProtocolType_PT_ICMPV6 = 58,     // System.Net.ProtocolType.IcmpV6
+    ProtocolType_PT_RAW = 255,       // System.Net.ProtocolType.Raw
+    ProtocolType_PT_IGMP = 2,        // System.Net.ProtocolType.Igmp
+    ProtocolType_PT_NONE = 59,       // System.Net.ProtocolType.IPv6NoNextHeader
+    ProtocolType_PT_DSTOPTS = 60,    // System.Net.ProtocolType.IPv6DestinationOptions
+    ProtocolType_PT_ROUTING = 43,    // System.Net.ProtocolType.IPv6RoutingHeader
+    ProtocolType_PT_FRAGMENT = 44,   // System.Net.ProtocolType.IPv6FragmentHeader
 } ProtocolType;
 
 typedef enum
index 9df357f..d2eda86 100644 (file)
@@ -403,6 +403,9 @@ namespace System.Net.Sockets
         Irda = 26,
         NetworkDesigners = 28,
         Max = 29,
+        Netlink = 30,
+        Packet = 31,
+        ControllerAreaNetwork = 32,
     }
     public enum SocketError
     {
index e3719f4..1576559 100644 (file)
@@ -43,5 +43,8 @@ namespace System.Net.Sockets
         Irda = 26,              // IrDA
         NetworkDesigners = 28,  // Network Designers OSI & gateway enabled protocols
         Max = 29,               // Max
+        Netlink = 30,           // Netlink protocol
+        Packet = 31,            // Linux Packet
+        ControllerAreaNetwork = 32, // Controller Area Network automotive bus protocol
     }
 }
index b9e09c5..cd011f0 100644 (file)
@@ -156,6 +156,9 @@ namespace System.Net.Sockets
         Irda = 26,
         NetworkDesigners = 28,
         Max = 29,
+        Netlink = 30,
+        Packet = 31,
+        ControllerAreaNetwork = 32,
     }
     public enum ProtocolType
     {
index 819344d..a4aa95b 100644 (file)
@@ -11,7 +11,7 @@ using Xunit;
 
 namespace System.Net.Sockets.Tests
 {
-    public class CreateSocket
+    public partial class CreateSocket
     {
         public static object[][] DualModeSuccessInputs = {
             new object[] { SocketType.Stream, ProtocolType.Tcp },
diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/CreateSocketTests.netcoreapp.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/CreateSocketTests.netcoreapp.cs
new file mode 100644 (file)
index 0000000..2aef051
--- /dev/null
@@ -0,0 +1,49 @@
+// 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.Diagnostics;
+using System.IO;
+using System.IO.Pipes;
+using System.Threading.Tasks;
+using Microsoft.DotNet.RemoteExecutor;
+using Xunit;
+
+namespace System.Net.Sockets.Tests
+{
+    public partial class CreateSocket
+    {
+        [Theory]
+        [InlineData(AddressFamily.Netlink)]
+        [InlineData(AddressFamily.Packet)]
+        [InlineData(AddressFamily.ControllerAreaNetwork)]
+        [PlatformSpecific(~TestPlatforms.Linux)]
+        public void Ctor_Netcoreapp_Throws(AddressFamily addressFamily)
+        {
+            // All protocols are Linux specific and throw on other platforms
+            Assert.Throws<SocketException>(() => new Socket(addressFamily, SocketType.Raw, 0));
+        }
+
+        [Theory]
+        [InlineData(AddressFamily.Netlink)]
+        [InlineData(AddressFamily.Packet)]
+        [InlineData(AddressFamily.ControllerAreaNetwork)]
+        [PlatformSpecific(TestPlatforms.Linux)]
+        public void Ctor_Netcoreapp_Success(AddressFamily addressFamily)
+        {
+            Socket s = null;
+            try
+            {
+                s = new Socket(addressFamily, SocketType.Raw, ProtocolType.Raw);
+            }
+            catch (SocketException e) when (e.SocketErrorCode == SocketError.AccessDenied ||
+                                            e.SocketErrorCode == SocketError.ProtocolNotSupported ||
+                                            e.SocketErrorCode == SocketError.AddressFamilyNotSupported)
+            {
+                // Ignore. We may not have privilege or protocol modules are not loaded.
+                return;
+            }
+            s.Close();
+        }
+    }
+}
index cac7453..dcb4cf8 100644 (file)
@@ -14,6 +14,7 @@
     <Compile Include="Connect.cs" />
     <Compile Include="Close.cs" />
     <Compile Include="CreateSocketTests.cs" />
+    <Compile Include="CreateSocketTests.netcoreapp.cs" Condition="'$(TargetGroup)' != 'netstandard'" />
     <Compile Include="DisposedSocketTests.cs" />
     <Compile Include="DnsEndPointTest.cs" />
     <Compile Include="DualModeSocketTest.cs" />
   <ItemGroup>
     <EmbeddedResource Include="Resources\$(AssemblyName).rd.xml" />
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>