forked from Mirror/Ryujinx
Stub unsupported BSD socket options (#5670)
* Stub unsupported BSD socket options * Span.Clear
This commit is contained in:
parent
e601419bd4
commit
44862dce3e
2 changed files with 143 additions and 2 deletions
|
@ -299,11 +299,21 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||||
{
|
{
|
||||||
try
|
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))
|
if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName))
|
||||||
{
|
{
|
||||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported GetSockOpt Option: {option} Level: {level}");
|
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];
|
byte[] tempOptionValue = new byte[optionValue.Length];
|
||||||
|
@ -324,11 +334,20 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||||
{
|
{
|
||||||
try
|
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))
|
if (!WinSockHelper.TryConvertSocketOption(option, level, out SocketOptionName optionName))
|
||||||
{
|
{
|
||||||
Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported SetSockOpt Option: {option} Level: {level}");
|
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);
|
int value = optionValue.Length >= 4 ? MemoryMarshal.Read<int>(optionValue) : MemoryMarshal.Read<byte>(optionValue);
|
||||||
|
|
|
@ -183,6 +183,104 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||||
{ BsdSocketOption.TcpKeepCnt, SocketOptionName.TcpKeepAliveRetryCount },
|
{ 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)
|
public static LinuxError ConvertError(WsaError errorCode)
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsMacOS())
|
if (OperatingSystem.IsMacOS())
|
||||||
|
@ -221,5 +319,29 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||||
|
|
||||||
return table.TryGetValue(option, out name);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue