Skip to content

Commit bf03034

Browse files
authored
Add Socket.Get/SetRawSocketOption (#33261)
1 parent 820cc14 commit bf03034

File tree

17 files changed

+230
-61
lines changed

17 files changed

+230
-61
lines changed

src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSockOpt.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@ internal static partial class Sys
1515

1616
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSockOpt")]
1717
internal static extern unsafe Error GetSockOpt(IntPtr socket, SocketOptionLevel optionLevel, SocketOptionName optionName, byte* optionValue, int* optionLen);
18+
19+
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetRawSockOpt")]
20+
internal static extern unsafe Error GetRawSockOpt(SafeHandle socket, int optionLevel, int optionName, byte* optionValue, int* optionLen);
1821
}
1922
}

src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetSockOpt.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@ internal static partial class Sys
1515

1616
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetSockOpt")]
1717
internal static extern unsafe Error SetSockOpt(IntPtr socket, SocketOptionLevel optionLevel, SocketOptionName optionName, byte* optionValue, int optionLen);
18+
19+
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetRawSockOpt")]
20+
internal static extern unsafe Error SetRawSockOpt(SafeHandle socket, int optionLevel, int optionName, byte* optionValue, int optionLen);
1821
}
1922
}

src/libraries/Common/src/Interop/Windows/WinSock/Interop.getsockopt.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,11 @@ internal static partial class Interop
1010
internal static partial class Winsock
1111
{
1212
[DllImport(Interop.Libraries.Ws2_32, SetLastError = true)]
13-
internal static extern SocketError getsockopt(
14-
[In] SafeSocketHandle socketHandle,
15-
[In] SocketOptionLevel optionLevel,
16-
[In] SocketOptionName optionName,
17-
[Out] out int optionValue,
18-
[In, Out] ref int optionLength);
19-
20-
[DllImport(Interop.Libraries.Ws2_32, SetLastError = true)]
21-
internal static extern SocketError getsockopt(
13+
internal static unsafe extern SocketError getsockopt(
2214
[In] SafeSocketHandle socketHandle,
2315
[In] SocketOptionLevel optionLevel,
2416
[In] SocketOptionName optionName,
25-
[Out] byte[] optionValue,
17+
[Out] byte* optionValue,
2618
[In, Out] ref int optionLength);
2719

2820
[DllImport(Interop.Libraries.Ws2_32, SetLastError = true)]

src/libraries/Common/src/Interop/Windows/WinSock/Interop.setsockopt.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ internal static extern SocketError setsockopt(
2828
[In] int optionLength);
2929

3030
[DllImport(Interop.Libraries.Ws2_32, SetLastError = true)]
31-
internal static extern SocketError setsockopt(
31+
internal static unsafe extern SocketError setsockopt(
3232
[In] SafeSocketHandle socketHandle,
3333
[In] SocketOptionLevel optionLevel,
3434
[In] SocketOptionName optionName,
35-
[In] byte[]? optionValue,
35+
[In] byte* optionValue,
3636
[In] int optionLength);
3737

3838
[DllImport(Interop.Libraries.Ws2_32, SetLastError = true)]

src/libraries/Native/Unix/System.Native/pal_networking.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,6 +1986,26 @@ int32_t SystemNative_GetSockOpt(
19861986
return Error_SUCCESS;
19871987
}
19881988

1989+
int32_t SystemNative_GetRawSockOpt(
1990+
intptr_t socket, int32_t socketOptionLevel, int32_t socketOptionName, uint8_t* optionValue, int32_t* optionLen)
1991+
{
1992+
if (optionLen == NULL || *optionLen < 0)
1993+
{
1994+
return Error_EFAULT;
1995+
}
1996+
1997+
socklen_t optLen = (socklen_t)*optionLen;
1998+
int err = getsockopt(ToFileDescriptor(socket), socketOptionLevel, socketOptionName, optionValue, &optLen);
1999+
if (err != 0)
2000+
{
2001+
return SystemNative_ConvertErrorPlatformToPal(errno);
2002+
}
2003+
2004+
assert(optLen <= (socklen_t)*optionLen);
2005+
*optionLen = (int32_t)optLen;
2006+
return Error_SUCCESS;
2007+
}
2008+
19892009
int32_t
19902010
SystemNative_SetSockOpt(intptr_t socket, int32_t socketOptionLevel, int32_t socketOptionName, uint8_t* optionValue, int32_t optionLen)
19912011
{
@@ -2065,6 +2085,18 @@ SystemNative_SetSockOpt(intptr_t socket, int32_t socketOptionLevel, int32_t sock
20652085
return err == 0 ? Error_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno);
20662086
}
20672087

2088+
int32_t SystemNative_SetRawSockOpt(
2089+
intptr_t socket, int32_t socketOptionLevel, int32_t socketOptionName, uint8_t* optionValue, int32_t optionLen)
2090+
{
2091+
if (optionLen < 0 || optionValue == NULL)
2092+
{
2093+
return Error_EFAULT;
2094+
}
2095+
2096+
int err = setsockopt(ToFileDescriptor(socket), socketOptionLevel, socketOptionName, optionValue, (socklen_t)optionLen);
2097+
return err == 0 ? Error_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno);
2098+
}
2099+
20682100
static bool TryConvertSocketTypePalToPlatform(int32_t palSocketType, int* platformSocketType)
20692101
{
20702102
assert(platformSocketType != NULL);

src/libraries/Native/Unix/System.Native/pal_networking.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,15 @@ PALEXPORT int32_t SystemNative_GetSocketErrorOption(intptr_t socket, int32_t* er
391391
PALEXPORT int32_t SystemNative_GetSockOpt(
392392
intptr_t socket, int32_t socketOptionLevel, int32_t socketOptionName, uint8_t* optionValue, int32_t* optionLen);
393393

394+
PALEXPORT int32_t SystemNative_GetRawSockOpt(
395+
intptr_t socket, int32_t socketOptionLevel, int32_t socketOptionName, uint8_t* optionValue, int32_t* optionLen);
396+
394397
PALEXPORT int32_t SystemNative_SetSockOpt(
395398
intptr_t socket, int32_t socketOptionLevel, int32_t socketOptionName, uint8_t* optionValue, int32_t optionLen);
396399

400+
PALEXPORT int32_t SystemNative_SetRawSockOpt(
401+
intptr_t socket, int32_t socketOptionLevel, int32_t socketOptionName, uint8_t* optionValue, int32_t optionLen);
402+
397403
PALEXPORT int32_t SystemNative_Socket(int32_t addressFamily, int32_t socketType, int32_t protocolType, intptr_t* createdSocket);
398404

399405
PALEXPORT int32_t SystemNative_GetAtOutOfBandMark(intptr_t socket, int32_t* available);

src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ public void EndDisconnect(System.IAsyncResult asyncResult) { }
309309
public void EndSendFile(System.IAsyncResult asyncResult) { }
310310
public int EndSendTo(System.IAsyncResult asyncResult) { throw null; }
311311
~Socket() { }
312+
public int GetRawSocketOption(int optionLevel, int optionName, System.Span<byte> optionValue) { throw null; }
312313
public object? GetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName) { throw null; }
313314
public void GetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, byte[] optionValue) { }
314315
public byte[] GetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, int optionLength) { throw null; }
@@ -358,6 +359,7 @@ public void SendFile(string? fileName, byte[]? preBuffer, byte[]? postBuffer, Sy
358359
public int SendTo(byte[] buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) { throw null; }
359360
public bool SendToAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; }
360361
public void SetIPProtectionLevel(System.Net.Sockets.IPProtectionLevel level) { }
362+
public void SetRawSocketOption(int optionLevel, int optionName, System.ReadOnlySpan<byte> optionValue) { }
361363
public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, bool optionValue) { }
362364
public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, byte[] optionValue) { }
363365
public void SetSocketOption(System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, int optionValue) { }

src/libraries/System.Net.Sockets/src/System/Net/Sockets/ConnectOverlappedAsyncResult.Windows.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace System.Net.Sockets
88
internal sealed partial class ConnectOverlappedAsyncResult : BaseOverlappedAsyncResult
99
{
1010
// This method is called by base.CompletionPortCallback base.OverlappedCallback as part of IO completion
11-
internal override object? PostCompletion(int numBytes)
11+
internal override unsafe object? PostCompletion(int numBytes)
1212
{
1313
SocketError errorCode = (SocketError)ErrorCode;
1414
Socket socket = (Socket)AsyncObject;

src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1818,6 +1818,20 @@ public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName opti
18181818
}
18191819
}
18201820

1821+
public void SetRawSocketOption(int optionLevel, int optionName, ReadOnlySpan<byte> optionValue)
1822+
{
1823+
ThrowIfDisposed();
1824+
1825+
SocketError errorCode = SocketPal.SetRawSockOpt(_handle, optionLevel, optionName, optionValue);
1826+
1827+
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"SetSockOpt optionLevel:{optionLevel} optionName:{optionName} returns errorCode:{errorCode}");
1828+
1829+
if (errorCode != SocketError.Success)
1830+
{
1831+
UpdateStatusAfterSocketErrorAndThrowException(errorCode);
1832+
}
1833+
}
1834+
18211835
// Gets the value of a socket option.
18221836
public object? GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName)
18231837
{
@@ -1894,7 +1908,7 @@ public byte[] GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName op
18941908
optionValue,
18951909
ref realOptionLength);
18961910

1897-
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"Interop.Winsock.getsockopt returns errorCode:{errorCode}");
1911+
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"GetSockOpt returned errorCode:{errorCode}");
18981912

18991913
// Throw an appropriate SocketException if the native call fails.
19001914
if (errorCode != SocketError.Success)
@@ -1912,6 +1926,23 @@ public byte[] GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName op
19121926
return optionValue;
19131927
}
19141928

1929+
public int GetRawSocketOption(int optionLevel, int optionName, Span<byte> optionValue)
1930+
{
1931+
ThrowIfDisposed();
1932+
1933+
int realOptionLength = optionValue.Length;
1934+
SocketError errorCode = SocketPal.GetRawSockOpt(_handle, optionLevel, optionName, optionValue, ref realOptionLength);
1935+
1936+
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"GetRawSockOpt optionLevel:{optionLevel} optionName:{optionName} returned errorCode:{errorCode}");
1937+
1938+
if (errorCode != SocketError.Success)
1939+
{
1940+
UpdateStatusAfterSocketErrorAndThrowException(errorCode);
1941+
}
1942+
1943+
return realOptionLength;
1944+
}
1945+
19151946
public void SetIPProtectionLevel(IPProtectionLevel level)
19161947
{
19171948
if (level == IPProtectionLevel.Unspecified)

src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.Windows.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,7 @@ out remoteSocketAddress.InternalSize
11561156
return socketError;
11571157
}
11581158

1159-
private SocketError FinishOperationConnect()
1159+
private unsafe SocketError FinishOperationConnect()
11601160
{
11611161
try
11621162
{

0 commit comments

Comments
 (0)