From ecc28bd9c31d9244494b9c708cd2d1d18af3eff6 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 15 Aug 2026 01:06:19 +0000 Subject: [PATCH] first fake icmp impl --- src/core/CMakeLists.txt | 2 + src/core/hle/service/sockets/bsd.cpp | 3 + src/core/internal_network/socket_icmp.cpp | 155 ++++++++++++++++++++++ src/core/internal_network/socket_icmp.h | 37 ++++++ 4 files changed, 197 insertions(+) create mode 100644 src/core/internal_network/socket_icmp.cpp create mode 100644 src/core/internal_network/socket_icmp.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index fdad80a434..f802f6722a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1133,6 +1133,8 @@ add_library(core STATIC internal_network/network_interface.h internal_network/socket_proxy.cpp internal_network/socket_proxy.h + internal_network/socket_icmp.cpp + internal_network/socket_icmp.h internal_network/socket_types.h internal_network/sockets.h internal_network/wifi_scanner.h diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 9fe512c371..51e8ea8b1a 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -20,6 +20,7 @@ #include "core/hle/service/sockets/sockets_translate.h" #include "core/internal_network/network.h" #include "core/internal_network/socket_proxy.h" +#include "core/internal_network/socket_icmp.h" #include "core/internal_network/sockets.h" #include "network/network.h" #include @@ -520,6 +521,8 @@ std::pair BSD::SocketImpl(Network::Domain domain, Network:: auto room_member = Network::GetRoomMember().lock(); if (room_member && room_member->IsConnected()) { descriptor.socket = std::make_shared(); + } else if (protocol == Network::Protocol::ICMP || protocol == Network::Protocol::ICMPV6) { + descriptor.socket = std::make_shared(); } else { descriptor.socket = std::make_shared(); } diff --git a/src/core/internal_network/socket_icmp.cpp b/src/core/internal_network/socket_icmp.cpp new file mode 100644 index 0000000000..3985596c04 --- /dev/null +++ b/src/core/internal_network/socket_icmp.cpp @@ -0,0 +1,155 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/assert.h" +#include "common/logging.h" +#include "core/internal_network/socket_icmp.h" + +#ifdef __unix__ +#include +#endif + +namespace Network { + +namespace { + +u16 ComputeChecksum(std::span data) { + u32 sum = 0; + for (size_t i = 0; i < data.size(); i += 2) { + u32 value = (u32(data[i + 0]) << 8ull) | u32(data[i + 1]); //big endian + sum += value; + } + if (data.size() % 2 != 0){ + sum += u16(data[data.size() - 1]) << 8; + } + while ((sum >> 16) != 0) + sum = (sum & 0xffff) + (sum >> 16); + return (~sum) & 0xffff; +} + +} + +IcmpSocket::IcmpSocket() noexcept {} + +IcmpSocket::~IcmpSocket() { + if (fd == INVALID_SOCKET) { + return; + } + fd = INVALID_SOCKET; +} + +Errno IcmpSocket::SetSockOpt(Network::SocketLevel level, Network::OptName optname, std::span optval) { + LOG_WARNING(Network, "(stubbed) level={},optname={},optval={}", level, optname, optval.size()); + return Errno::SUCCESS; +} + +Errno IcmpSocket::Initialize(Domain domain, Type type, Protocol socket_protocol) { + return Errno::SUCCESS; +} + +std::pair IcmpSocket::Accept() { + LOG_WARNING(Network, "(stubbed) called"); + return {AcceptResult{}, Errno::SUCCESS}; +} + +Errno IcmpSocket::Connect(Network::SockAddrIn addr_in) { + LOG_WARNING(Network, "(stubbed) called"); + return Errno::SUCCESS; +} + +std::pair IcmpSocket::GetPeerName() { + LOG_WARNING(Network, "(stubbed) called"); + return {Network::SockAddrIn{}, Errno::SUCCESS}; +} + +std::pair IcmpSocket::GetSockName() { + LOG_WARNING(Network, "(stubbed) called"); + return {Network::SockAddrIn{}, Errno::SUCCESS}; +} + +Errno IcmpSocket::Bind(Network::SockAddrIn addr) { + LOG_WARNING(Network, "(stubbed) called"); + return Errno::SUCCESS; +} + +Errno IcmpSocket::Listen(s32 backlog) { + LOG_WARNING(Network, "(stubbed) called"); + return Errno::SUCCESS; +} + +Errno IcmpSocket::Shutdown(ShutdownHow how) { + LOG_WARNING(Network, "(stubbed) called"); + return Errno::SUCCESS; +} + +std::pair IcmpSocket::Recv(int flags, std::span message) { + LOG_DEBUG(Network, "(stubbed) called"); + return {s32(0), Errno::NOTCONN}; +} + +std::pair IcmpSocket::RecvFrom(int flags, std::span message, Network::SockAddrIn* addr) { + LOG_DEBUG(Network, "(stubbed) called"); + ASSERT(flags == 0); + ASSERT(message.size() < std::size_t((std::numeric_limits::max)())); + if (!data.empty()) { + auto const n = (std::max)(data.size(), message.size()); + std::copy(data.begin(), data.begin() + n, message.begin()); + return {n, Errno::SUCCESS}; + } + return {-1, Errno::TIMEDOUT}; +} + +std::pair IcmpSocket::Send(std::span message, int flags) { + LOG_DEBUG(Network, "(stubbed) called"); + return {s32(0), Errno::NOTCONN}; +} + +std::pair IcmpSocket::SendTo(u32 flags, std::span message, const Network::SockAddrIn* addr) { + LOG_DEBUG(Network, "(stubbed) called"); + // 0 -> 8 (IPv4), 128 (IPv6) + // 1 -> 0 + // 2..4 -> checksum + // 4..6 -> ident + // 6..8 -> seq + if (message.size() >= 8) { + ASSERT(message[0] == 0); + auto const csum_pos = data.size(); + data.push_back(8); + data.push_back(0); + data.push_back(0); //checksum (placeholder 0) + data.push_back(0); + data.push_back(message[4]); //ident + data.push_back(message[5]); + data.push_back(message[6]); //seq + data.push_back(message[7]); + auto const csum = ComputeChecksum(std::span{data.begin() + csum_pos, data.end()}); + data[csum_pos + 2] = u8(csum >> 8); //hi + data[csum_pos + 3] = u8(csum); //lo + } + return {s32(message.size()), Errno::SUCCESS}; +} + +Errno IcmpSocket::Close() { + LOG_DEBUG(Network, "called"); + fd = INVALID_SOCKET; + return Errno::SUCCESS; +} + +std::pair IcmpSocket::GetPendingError() { + LOG_DEBUG(Network, "called"); + return {Errno::SUCCESS, Errno::SUCCESS}; +} + +bool IcmpSocket::IsOpened() const { + return fd != INVALID_SOCKET; +} + +void IcmpSocket::HandleProxyPacket(const ProxyPacket& packet) { + LOG_WARNING(Network, "(stubbed) called"); +} +Errno IcmpSocket::SetNonBlock(bool enable) { + LOG_WARNING(Network, "(stubbed) called"); + return Errno::SUCCESS; +} + +} // namespace Network diff --git a/src/core/internal_network/socket_icmp.h b/src/core/internal_network/socket_icmp.h new file mode 100644 index 0000000000..1c8c00d9dd --- /dev/null +++ b/src/core/internal_network/socket_icmp.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include "core/internal_network/sockets.h" + +namespace Network { + +class IcmpSocket : public Network::SocketBase { +public: + explicit IcmpSocket() noexcept; + ~IcmpSocket() override; + Errno Initialize(Domain domain, Type type, Protocol socket_protocol) override; + Errno Close() override; + std::pair Accept() override; + Errno Connect(Network::SockAddrIn addr_in) override; + std::pair GetPeerName() override; + std::pair GetSockName() override; + Errno Bind(Network::SockAddrIn addr) override; + Errno Listen(s32 backlog) override; + Errno Shutdown(ShutdownHow how) override; + std::pair Recv(int flags, std::span message) override; + std::pair RecvFrom(int flags, std::span message, Network::SockAddrIn* addr) override; + std::pair Send(std::span message, int flags) override; + std::pair SendTo(u32 flags, std::span message, const Network::SockAddrIn* addr) override; + Errno SetSockOpt(Network::SocketLevel level, Network::OptName option, std::span value) override; + std::pair GetPendingError() override; + bool IsOpened() const override; + void HandleProxyPacket(const ProxyPacket& packet) override; + Errno SetNonBlock(bool enable) override; + + std::vector data; +}; + +} // namespace Network