aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-09-19 14:35:56 -0300
committerGitHub <noreply@github.com>2023-09-19 19:35:56 +0200
commit44862dce3ef307b12366376ada3fa0db693bfaf9 (patch)
tree4c98f001c590f72a9a6815ccf4641b18beb7572c
parente601419bd46f3f251300714b9dbe836627f620f3 (diff)
Stub unsupported BSD socket options (#5670)1.1.1019
* Stub unsupported BSD socket options * Span.Clear
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs23
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs122
2 files changed, 143 insertions, 2 deletions
diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs
index dfc2a672..2d8fce1d 100644
--- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/ManagedSocket.cs
@@ -299,11 +299,21 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
{
try
{
+ LinuxError result = WinSockHelper.ValidateSocketOption(option, level, write: false);
+
+ if (result != LinuxError.SUCCESS)
+ {
+ Logger.Warning?.Print(LogClass.ServiceBsd, $"Invalid GetSockOpt Option: {option} Level: {level}");
+
+ return result;
+ }
+
if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName))
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt Option: {option} Level: {level}");
+ optionValue.Clear();
- return LinuxError.EOPNOTSUPP;
+ return LinuxError.SUCCESS;
}
byte[] tempOptionValue = new byte[optionValue.Length];
@@ -324,11 +334,20 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
{
try
{
+ LinuxError result = WinSockHelper.ValidateSocketOption(option, level, write: true);
+
+ if (result != LinuxError.SUCCESS)
+ {
+ Logger.Warning?.Print(LogClass.ServiceBsd, $"Invalid SetSockOpt Option: {option} Level: {level}");
+
+ return result;
+ }
+
if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName))
{
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt Option: {option} Level: {level}");
- return LinuxError.EOPNOTSUPP;
+ return LinuxError.SUCCESS;
}
int value = optionValue.Length >= 4 ? MemoryMarshal.Read<int>(optionValue) : MemoryMarshal.Read<byte>(optionValue);
diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs
index 9df18023..e2ef75f8 100644
--- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/WinSockHelper.cs
@@ -183,6 +183,104 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
{ BsdSocketOption.TcpKeepCnt, SocketOptionName.TcpKeepAliveRetryCount },
};
+ [Flags]
+ private enum OptionDir
+ {
+ Get = 1 << 0,
+ Set = 1 << 1,
+ GetSet = Get | Set,
+ }
+
+ private static readonly Dictionary<BsdSocketOption, OptionDir> _validSoSocketOptionMap = new()
+ {
+ { BsdSocketOption.SoDebug, OptionDir.GetSet },
+ { BsdSocketOption.SoAcceptConn, OptionDir.Get },
+ { BsdSocketOption.SoReuseAddr, OptionDir.GetSet },
+ { BsdSocketOption.SoKeepAlive, OptionDir.GetSet },
+ { BsdSocketOption.SoDontRoute, OptionDir.GetSet },
+ { BsdSocketOption.SoBroadcast, OptionDir.GetSet },
+ { BsdSocketOption.SoUseLoopBack, OptionDir.GetSet },
+ { BsdSocketOption.SoLinger, OptionDir.GetSet },
+ { BsdSocketOption.SoOobInline, OptionDir.GetSet },
+ { BsdSocketOption.SoReusePort, OptionDir.GetSet },
+ { BsdSocketOption.SoTimestamp, OptionDir.GetSet },
+ { BsdSocketOption.SoNoSigpipe, OptionDir.GetSet },
+ { BsdSocketOption.SoAcceptFilter, OptionDir.GetSet },
+ { BsdSocketOption.SoSndBuf, OptionDir.GetSet },
+ { BsdSocketOption.SoRcvBuf, OptionDir.GetSet },
+ { BsdSocketOption.SoSndLoWat, OptionDir.GetSet },
+ { BsdSocketOption.SoRcvLoWat, OptionDir.GetSet },
+ { BsdSocketOption.SoSndTimeo, OptionDir.GetSet },
+ { BsdSocketOption.SoRcvTimeo, OptionDir.GetSet },
+ { BsdSocketOption.SoError, OptionDir.Get },
+ { BsdSocketOption.SoType, OptionDir.Get },
+ { BsdSocketOption.SoLabel, OptionDir.Get },
+ { BsdSocketOption.SoPeerLabel, OptionDir.Get },
+ { BsdSocketOption.SoListenQLimit, OptionDir.Get },
+ { BsdSocketOption.SoListenQLen, OptionDir.Get },
+ { BsdSocketOption.SoListenIncQLen, OptionDir.Get },
+ { BsdSocketOption.SoSetFib, OptionDir.Set },
+ { BsdSocketOption.SoUserCookie, OptionDir.Set },
+ { BsdSocketOption.SoProtocol, OptionDir.Get },
+ { BsdSocketOption.SoBinTime, OptionDir.GetSet },
+ { BsdSocketOption.SoNoOffload, OptionDir.Set },
+ { BsdSocketOption.SoNoDdp, OptionDir.Set },
+ { BsdSocketOption.SoReusePortLb, OptionDir.GetSet },
+ };
+
+ private static readonly Dictionary<BsdSocketOption, OptionDir> _validIpSocketOptionMap = new()
+ {
+ { BsdSocketOption.IpOptions, OptionDir.GetSet },
+ { BsdSocketOption.IpHdrIncl, OptionDir.GetSet },
+ { BsdSocketOption.IpTos, OptionDir.GetSet },
+ { BsdSocketOption.IpTtl, OptionDir.GetSet },
+ { BsdSocketOption.IpRecvOpts, OptionDir.GetSet },
+ { BsdSocketOption.IpRecvRetOpts, OptionDir.GetSet },
+ { BsdSocketOption.IpRecvDstAddr, OptionDir.GetSet },
+ { BsdSocketOption.IpRetOpts, OptionDir.GetSet },
+ { BsdSocketOption.IpMulticastIf, OptionDir.GetSet },
+ { BsdSocketOption.IpMulticastTtl, OptionDir.GetSet },
+ { BsdSocketOption.IpMulticastLoop, OptionDir.GetSet },
+ { BsdSocketOption.IpAddMembership, OptionDir.GetSet },
+ { BsdSocketOption.IpDropMembership, OptionDir.GetSet },
+ { BsdSocketOption.IpMulticastVif, OptionDir.GetSet },
+ { BsdSocketOption.IpRsvpOn, OptionDir.GetSet },
+ { BsdSocketOption.IpRsvpOff, OptionDir.GetSet },
+ { BsdSocketOption.IpRsvpVifOn, OptionDir.GetSet },
+ { BsdSocketOption.IpRsvpVifOff, OptionDir.GetSet },
+ { BsdSocketOption.IpPortRange, OptionDir.GetSet },
+ { BsdSocketOption.IpRecvIf, OptionDir.GetSet },
+ { BsdSocketOption.IpIpsecPolicy, OptionDir.GetSet },
+ { BsdSocketOption.IpOnesBcast, OptionDir.GetSet },
+ { BsdSocketOption.IpBindany, OptionDir.GetSet },
+ { BsdSocketOption.IpBindMulti, OptionDir.GetSet },
+ { BsdSocketOption.IpRssListenBucket, OptionDir.GetSet },
+ { BsdSocketOption.IpOrigDstAddr, OptionDir.GetSet },
+ { BsdSocketOption.IpRecvTtl, OptionDir.GetSet },
+ { BsdSocketOption.IpMinTtl, OptionDir.GetSet },
+ { BsdSocketOption.IpDontFrag, OptionDir.GetSet },
+ { BsdSocketOption.IpRecvTos, OptionDir.GetSet },
+ { BsdSocketOption.IpAddSourceMembership, OptionDir.GetSet },
+ { BsdSocketOption.IpDropSourceMembership, OptionDir.GetSet },
+ { BsdSocketOption.IpBlockSource, OptionDir.GetSet },
+ { BsdSocketOption.IpUnblockSource, OptionDir.GetSet },
+ };
+
+ private static readonly Dictionary<BsdSocketOption, OptionDir> _validTcpSocketOptionMap = new()
+ {
+ { BsdSocketOption.TcpNoDelay, OptionDir.GetSet },
+ { BsdSocketOption.TcpMaxSeg, OptionDir.GetSet },
+ { BsdSocketOption.TcpNoPush, OptionDir.GetSet },
+ { BsdSocketOption.TcpNoOpt, OptionDir.GetSet },
+ { BsdSocketOption.TcpMd5Sig, OptionDir.GetSet },
+ { BsdSocketOption.TcpInfo, OptionDir.GetSet },
+ { BsdSocketOption.TcpCongestion, OptionDir.GetSet },
+ { BsdSocketOption.TcpKeepInit, OptionDir.GetSet },
+ { BsdSocketOption.TcpKeepIdle, OptionDir.GetSet },
+ { BsdSocketOption.TcpKeepIntvl, OptionDir.GetSet },
+ { BsdSocketOption.TcpKeepCnt, OptionDir.GetSet },
+ };
+
public static LinuxError ConvertError(WsaError errorCode)
{
if (OperatingSystem.IsMacOS())
@@ -221,5 +319,29 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
return table.TryGetValue(option, out name);
}
+
+ public static LinuxError ValidateSocketOption(BsdSocketOption option, SocketOptionLevel level, bool write)
+ {
+ var table = level switch
+ {
+ SocketOptionLevel.Socket => _validSoSocketOptionMap,
+ SocketOptionLevel.IP => _validIpSocketOptionMap,
+ SocketOptionLevel.Tcp => _validTcpSocketOptionMap,
+ _ => null,
+ };
+
+ OptionDir dir = write ? OptionDir.Set : OptionDir.Get;
+
+ if (table == null || !table.TryGetValue(option, out OptionDir validDir))
+ {
+ return LinuxError.ENOPROTOOPT;
+ }
+ else if ((validDir & dir) != dir)
+ {
+ return LinuxError.EOPNOTSUPP;
+ }
+
+ return LinuxError.SUCCESS;
+ }
}
}