diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index d12debd120..af1098a98e 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -20,10 +20,11 @@ #include #include #include -#include #include #include #include +#include +#include #endif #include "common/assert.h" @@ -936,38 +937,57 @@ Socket::Socket(Socket&& rhs) noexcept { fd = std::exchange(rhs.fd, INVALID_SOCKET); } -static s32 TranslateOptNameToNative(Network::OptName optname) { - switch (optname) { - // managarm doesn't like these +static s32 TranslateOptNameToNative(Network::SocketLevel level, Network::OptName optname) { + switch (level) { + case Network::SocketLevel::SOCKET: + switch (optname) { + // managarm doesn't like these #ifdef SO_DEBUG - case Network::OptName::DEBUG: return SO_DEBUG; + case Network::OptName::DEBUG: return SO_DEBUG; #endif #ifdef SO_ACCEPTCONN - case Network::OptName::ACCEPTCONN: return SO_ACCEPTCONN; + case Network::OptName::ACCEPTCONN: return SO_ACCEPTCONN; #endif - case Network::OptName::LINGER: return SO_LINGER; - case Network::OptName::REUSEADDR: return SO_REUSEADDR; - case Network::OptName::KEEPALIVE: return SO_KEEPALIVE; - case Network::OptName::BROADCAST: return SO_BROADCAST; - case Network::OptName::SNDBUF: return SO_SNDBUF; - case Network::OptName::RCVBUF: return SO_RCVBUF; - case Network::OptName::SNDTIMEO: return SO_SNDTIMEO; - case Network::OptName::RCVTIMEO: return SO_RCVTIMEO; - case Network::OptName::NOSIGPIPE: return SO_NOSIGPIPE; + case Network::OptName::LINGER: return SO_LINGER; + case Network::OptName::REUSEADDR: return SO_REUSEADDR; + case Network::OptName::KEEPALIVE: return SO_KEEPALIVE; + case Network::OptName::BROADCAST: return SO_BROADCAST; + case Network::OptName::SNDBUF: return SO_SNDBUF; + case Network::OptName::RCVBUF: return SO_RCVBUF; + case Network::OptName::SNDTIMEO: return SO_SNDTIMEO; + case Network::OptName::RCVTIMEO: return SO_RCVTIMEO; + case Network::OptName::NOSIGPIPE: return SO_NOSIGPIPE; #ifdef SO_REUSEPORT - case Network::OptName::REUSEPORT: return SO_REUSEPORT; + case Network::OptName::REUSEPORT: return SO_REUSEPORT; #endif #ifdef SO_ACCEPTFILTER - case Network::OptName::ACCEPTFILTER: return SO_ACCEPTFILTER; + case Network::OptName::ACCEPTFILTER: return SO_ACCEPTFILTER; #endif #ifdef SO_TIMESTAMP - case Network::OptName::TIMESTAMP: return SO_TIMESTAMP; + case Network::OptName::TIMESTAMP: return SO_TIMESTAMP; #endif - case Network::OptName::ERROR_: return SO_ERROR; + case Network::OptName::ERROR_: return SO_ERROR; + default: + break; + } + break; + case Network::SocketLevel::TCP: + switch (Network::TcpOptName(optname)) { + case Network::TcpOptName::NODELAY: return TCP_NODELAY; + case Network::TcpOptName::MAXSEG: return TCP_MAXSEG; + case Network::TcpOptName::NOPUSH: return TCP_NOPUSH; + case Network::TcpOptName::NOOPT: return TCP_NOOPT; + case Network::TcpOptName::MD5SIG: return TCP_MD5SIG; + case Network::TcpOptName::INFO: return TCP_INFO; + default: + break; + } + break; default: - UNIMPLEMENTED_MSG("Unimplemented optname={}", optname); - return 0; + break; } + UNIMPLEMENTED_MSG("Unimplemented level={},optname={}", level, optname); + return 0; } static s32 TranslateSocketLevelToNative(Network::SocketLevel level) { @@ -976,15 +996,23 @@ static s32 TranslateSocketLevelToNative(Network::SocketLevel level) { // FreeBSD doesn't define below but Linux does :-( #ifdef SOL_IP case Network::SocketLevel::IP: return SOL_IP; +#else + case Network::SocketLevel::IP: return IPPROTO_IP; #endif #ifdef SOL_ICMP case Network::SocketLevel::ICMP: return SOL_ICMP; +#else + case Network::SocketLevel::ICMP: return IPPROTO_ICMP; #endif #ifdef SOL_TCP case Network::SocketLevel::TCP: return SOL_TCP; +#else + case Network::SocketLevel::TCP: return IPPROTO_TCP; #endif #ifdef SOL_UDP case Network::SocketLevel::UDP: return SOL_UDP; +#else + case Network::SocketLevel::UDP: return IPPROTO_UDP; #endif #ifdef SOL_CONFIG case Network::SocketLevel::CONFIG: return SOL_CONFIG; @@ -998,7 +1026,7 @@ static s32 TranslateSocketLevelToNative(Network::SocketLevel level) { Errno Socket::GetSockOpt(Network::SocketLevel level, Network::OptName optname, std::span value) { socklen_t len = socklen_t(value.size()); auto const native_level = TranslateSocketLevelToNative(level); - auto const native_optname = TranslateOptNameToNative(optname); + auto const native_optname = TranslateOptNameToNative(level, optname); const int result = getsockopt(fd, native_level, native_optname, reinterpret_cast(value.data()), &len); if (result != SOCKET_ERROR) { ASSERT(len == socklen_t(value.size())); @@ -1018,7 +1046,7 @@ Errno Socket::SetNonBlock(bool enable) { Errno Socket::SetSockOpt(Network::SocketLevel level, Network::OptName optname, std::span optval) { LOG_DEBUG(Network, "level={},optname={},optval={}", level, optname, optval.size()); auto const native_level = TranslateSocketLevelToNative(level); - auto const native_optname = TranslateOptNameToNative(optname); + auto const native_optname = TranslateOptNameToNative(level, optname); // TODO: is it >= or ==? for sizes if (optname == Network::OptName::LINGER) { if (optval.size() >= sizeof(Network::Linger)) { diff --git a/src/core/internal_network/socket_types.h b/src/core/internal_network/socket_types.h index e54c94a849..4ae8d5ff62 100644 --- a/src/core/internal_network/socket_types.h +++ b/src/core/internal_network/socket_types.h @@ -281,6 +281,14 @@ enum class OptName : u32 { NO_OFFLOAD = 0x4000, NO_DDP = 0x8000, }; +enum class TcpOptName : u32 { + NODELAY = 0x0001, + MAXSEG = 0x0002, + NOPUSH = 0x0004, + NOOPT = 0x0008, + MS5SIG = 0x0010, + INFO = 0x0020 +}; enum class ShutdownHow : s32 { RD = 0,