diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9571c1ad9..6f20c1352 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1045,6 +1045,14 @@ add_library(core STATIC hle/service/sm/sm_controller.h hle/service/sockets/bsd.cpp hle/service/sockets/bsd.h + hle/service/sockets/bsd_nu.cpp + hle/service/sockets/bsd_nu.h + hle/service/sockets/bsdcfg.cpp + hle/service/sockets/bsdcfg.h + hle/service/sockets/dns_priv.cpp + hle/service/sockets/dns_priv.h + hle/service/sockets/ethc.cpp + hle/service/sockets/ethc.h hle/service/sockets/nsd.cpp hle/service/sockets/nsd.h hle/service/sockets/sfdnsres.cpp diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index ef0320334..b2c9c60a1 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -479,6 +480,122 @@ void BSD::EventFd(HLERequestContext& ctx) { BuildErrnoResponse(ctx, Errno::SUCCESS); } +void BSD::Sysctl(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + // Return an error if not implemented + rb.Push(-1); + rb.PushEnum(Errno::INVAL); +} + +void BSD::Ioctl(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + // Return an error if not implemented + rb.Push(-1); + rb.PushEnum(Errno::INVAL); +} + +void BSD::ShutdownAllSockets(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); + rb.PushEnum(Errno::SUCCESS); +} + +void BSD::GetResourceStatistics(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); + rb.PushEnum(Errno::SUCCESS); +} + +void BSD::RecvMMsg(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + // Return an error if not implemented + rb.Push(-1); + rb.PushEnum(Errno::INVAL); +} + +void BSD::SendMMsg(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + // Return an error if not implemented + rb.Push(-1); + rb.PushEnum(Errno::INVAL); +} + +void BSD::RegisterResourceStatisticsName(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSD::RegisterClientShared(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSD::GetSocketStatistics(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); + rb.PushEnum(Errno::SUCCESS); +} + +void BSD::NifIoctl(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + // Return an error if not implemented + rb.Push(-1); + rb.PushEnum(Errno::INVAL); +} + +void BSD::SetThreadCoreMask(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSD::GetThreadCoreMask(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSD::SocketExempt(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u32 domain = rp.Pop(); + const u32 type = rp.Pop(); + const u32 protocol = rp.Pop(); + + LOG_WARNING(Service, "(STUBBED) called - domain={} type={} protocol={}", domain, type, protocol); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(-1); // Return -1 on exempted socket + rb.PushEnum(Errno::SUCCESS); +} + +void BSD::Open(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + // Return an error if not implemented + rb.Push(-1); + rb.PushEnum(Errno::INVAL); +} + template void BSD::ExecuteWork(HLERequestContext& ctx, Work work) { work.Execute(this); @@ -508,9 +625,9 @@ std::pair BSD::SocketImpl(Domain domain, Type type, Protocol protoco LOG_INFO(Service, "New socket fd={}", fd); - auto room_member = room_network.GetRoomMember().lock(); + auto room_member = system.GetRoomNetwork().GetRoomMember().lock(); if (room_member && room_member->IsConnected()) { - descriptor.socket = std::make_shared(room_network); + descriptor.socket = std::make_shared(system.GetRoomNetwork()); } else { descriptor.socket = std::make_shared(); } @@ -970,17 +1087,17 @@ void BSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) { } BSD::BSD(Core::System& system_, const char* name) - : ServiceFramework{system_, name}, room_network{system_.GetRoomNetwork()} { + : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { {0, &BSD::RegisterClient, "RegisterClient"}, {1, &BSD::StartMonitoring, "StartMonitoring"}, {2, &BSD::Socket, "Socket"}, - {3, nullptr, "SocketExempt"}, - {4, nullptr, "Open"}, + {3, &BSD::SocketExempt, "SocketExempt"}, + {4, &BSD::Open, "Open"}, {5, &BSD::Select, "Select"}, {6, &BSD::Poll, "Poll"}, - {7, nullptr, "Sysctl"}, + {7, &BSD::Sysctl, "Sysctl"}, {8, &BSD::Recv, "Recv"}, {9, &BSD::RecvFrom, "RecvFrom"}, {10, &BSD::Send, "Send"}, @@ -992,27 +1109,32 @@ BSD::BSD(Core::System& system_, const char* name) {16, &BSD::GetSockName, "GetSockName"}, {17, &BSD::GetSockOpt, "GetSockOpt"}, {18, &BSD::Listen, "Listen"}, - {19, nullptr, "Ioctl"}, + {19, &BSD::Ioctl, "Ioctl"}, {20, &BSD::Fcntl, "Fcntl"}, {21, &BSD::SetSockOpt, "SetSockOpt"}, {22, &BSD::Shutdown, "Shutdown"}, - {23, nullptr, "ShutdownAllSockets"}, + {23, &BSD::ShutdownAllSockets, "ShutdownAllSockets"}, {24, &BSD::Write, "Write"}, {25, &BSD::Read, "Read"}, {26, &BSD::Close, "Close"}, {27, &BSD::DuplicateSocket, "DuplicateSocket"}, - {28, nullptr, "GetResourceStatistics"}, - {29, nullptr, "RecvMMsg"}, - {30, nullptr, "SendMMsg"}, + {28, &BSD::GetResourceStatistics, "GetResourceStatistics"}, + {29, &BSD::RecvMMsg, "RecvMMsg"}, + {30, &BSD::SendMMsg, "SendMMsg"}, {31, &BSD::EventFd, "EventFd"}, - {32, nullptr, "RegisterResourceStatisticsName"}, - {33, nullptr, "Initialize2"}, + {32, &BSD::RegisterResourceStatisticsName, "RegisterResourceStatisticsName"}, + {33, &BSD::RegisterClientShared, "RegisterClientShared"}, + {34, &BSD::GetSocketStatistics, "GetSocketStatistics"}, + {35, &BSD::NifIoctl, "NifIoctl"}, + {200, &BSD::SetThreadCoreMask, "SetThreadCoreMask"}, + {201, &BSD::GetThreadCoreMask, "GetThreadCoreMask"}, }; // clang-format on RegisterHandlers(functions); - if (auto room_member = room_network.GetRoomMember().lock()) { + auto room_member = system.GetRoomNetwork().GetRoomMember().lock(); + if (room_member) { proxy_packet_received = room_member->BindOnProxyPacketReceived( [this](const Network::ProxyPacket& packet) { OnProxyPacketReceived(packet); }); } else { @@ -1021,7 +1143,8 @@ BSD::BSD(Core::System& system_, const char* name) } BSD::~BSD() { - if (auto room_member = room_network.GetRoomMember().lock()) { + auto room_member = system.GetRoomNetwork().GetRoomMember().lock(); + if (room_member) { room_member->Unbind(proxy_packet_received); } } @@ -1031,31 +1154,4 @@ std::unique_lock BSD::LockService() { return {}; } -BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "SetIfUp"}, - {1, nullptr, "SetIfUpWithEvent"}, - {2, nullptr, "CancelIf"}, - {3, nullptr, "SetIfDown"}, - {4, nullptr, "GetIfState"}, - {5, nullptr, "DhcpRenew"}, - {6, nullptr, "AddStaticArpEntry"}, - {7, nullptr, "RemoveArpEntry"}, - {8, nullptr, "LookupArpEntry"}, - {9, nullptr, "LookupArpEntry2"}, - {10, nullptr, "ClearArpEntries"}, - {11, nullptr, "ClearArpEntries2"}, - {12, nullptr, "PrintArpEntries"}, - {13, nullptr, "Unknown13"}, - {14, nullptr, "Unknown14"}, - {15, nullptr, "Unknown15"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -BSDCFG::~BSDCFG() = default; - } // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index 4f69d382c..c4f930155 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -124,11 +125,30 @@ private: Errno bsd_errno{}; }; + struct LibraryConfigData { + u32 version; + u32 tcp_tx_buf_size; + u32 tcp_rx_buf_size; + u32 tcp_tx_buf_max_size; + u32 tcp_rx_buf_max_size; + u32 udp_tx_buf_size; + u32 udp_rx_buf_size; + u32 sb_efficiency; + }; + + // This is nn::socket::sf::IClient void RegisterClient(HLERequestContext& ctx); void StartMonitoring(HLERequestContext& ctx); void Socket(HLERequestContext& ctx); + void SocketExempt(HLERequestContext& ctx); + void Open(HLERequestContext& ctx); void Select(HLERequestContext& ctx); void Poll(HLERequestContext& ctx); + void Sysctl(HLERequestContext& ctx); + void Recv(HLERequestContext& ctx); + void RecvFrom(HLERequestContext& ctx); + void Send(HLERequestContext& ctx); + void SendTo(HLERequestContext& ctx); void Accept(HLERequestContext& ctx); void Bind(HLERequestContext& ctx); void Connect(HLERequestContext& ctx); @@ -136,18 +156,25 @@ private: void GetSockName(HLERequestContext& ctx); void GetSockOpt(HLERequestContext& ctx); void Listen(HLERequestContext& ctx); + void Ioctl(HLERequestContext& ctx); void Fcntl(HLERequestContext& ctx); void SetSockOpt(HLERequestContext& ctx); void Shutdown(HLERequestContext& ctx); - void Recv(HLERequestContext& ctx); - void RecvFrom(HLERequestContext& ctx); - void Send(HLERequestContext& ctx); - void SendTo(HLERequestContext& ctx); + void ShutdownAllSockets(HLERequestContext& ctx); void Write(HLERequestContext& ctx); void Read(HLERequestContext& ctx); void Close(HLERequestContext& ctx); void DuplicateSocket(HLERequestContext& ctx); + void GetResourceStatistics(HLERequestContext& ctx); + void RecvMMsg(HLERequestContext& ctx); + void SendMMsg(HLERequestContext& ctx); void EventFd(HLERequestContext& ctx); + void RegisterResourceStatisticsName(HLERequestContext& ctx); + void RegisterClientShared(HLERequestContext& ctx); + void GetSocketStatistics(HLERequestContext& ctx); + void NifIoctl(HLERequestContext& ctx); + void SetThreadCoreMask(HLERequestContext& ctx); + void GetThreadCoreMask(HLERequestContext& ctx); template void ExecuteWork(HLERequestContext& ctx, Work work); @@ -171,30 +198,23 @@ private: std::pair SendImpl(s32 fd, u32 flags, std::span message); std::pair SendToImpl(s32 fd, u32 flags, std::span message, std::span addr); - s32 FindFreeFileDescriptorHandle() noexcept; bool IsFileDescriptorValid(s32 fd) const noexcept; void BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noexcept; - std::array, MAX_FD> file_descriptors; - - Network::RoomNetwork& room_network; - - /// Callback to parse and handle a received wifi packet. void OnProxyPacketReceived(const Network::ProxyPacket& packet); - // Callback identifier for the OnProxyPacketReceived event. Network::RoomMember::CallbackHandle proxy_packet_received; + /// Mapping of file descriptors to sockets + std::array, MAX_FD> file_descriptors{}; + + /// Mutex to protect file descriptor operations + std::mutex mutex; + protected: virtual std::unique_lock LockService() override; }; -class BSDCFG final : public ServiceFramework { -public: - explicit BSDCFG(Core::System& system_); - ~BSDCFG() override; -}; - } // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/bsd_nu.cpp b/src/core/hle/service/sockets/bsd_nu.cpp new file mode 100644 index 000000000..78919bf0c --- /dev/null +++ b/src/core/hle/service/sockets/bsd_nu.cpp @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/sockets/bsd_nu.h" + +namespace Service::Sockets { + +ISfUserService::ISfUserService(Core::System& system_) + : ServiceFramework{system_, "ISfUserService"}, + service_context{system_, "ISfUserService"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &ISfUserService::Assign, "Assign"}, + {128, &ISfUserService::GetUserInfo, "GetUserInfo"}, + {129, &ISfUserService::GetStateChangedEvent, "GetStateChangedEvent"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ISfUserService::~ISfUserService() = default; + +void ISfUserService::Assign(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(system); +} + +void ISfUserService::GetUserInfo(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISfUserService::GetStateChangedEvent(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + + auto* event = service_context.CreateEvent("ISfUserService:StateChanged"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(event->GetReadableEvent()); +} + +ISfAssignedNetworkInterfaceService::ISfAssignedNetworkInterfaceService(Core::System& system_) + : ServiceFramework{system_, "ISfAssignedNetworkInterfaceService"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &ISfAssignedNetworkInterfaceService::AddSession, "AddSession"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ISfAssignedNetworkInterfaceService::~ISfAssignedNetworkInterfaceService() = default; + +void ISfAssignedNetworkInterfaceService::AddSession(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +BSD_NU::BSD_NU(Core::System& system_) : ServiceFramework{system_, "bsd:nu"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &BSD_NU::CreateUserService, "CreateUserService"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +BSD_NU::~BSD_NU() = default; + +void BSD_NU::CreateUserService(HLERequestContext& ctx) { + LOG_DEBUG(Service, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(system); +} + +} // namespace Service::Sockets \ No newline at end of file diff --git a/src/core/hle/service/sockets/bsd_nu.h b/src/core/hle/service/sockets/bsd_nu.h new file mode 100644 index 000000000..277259c41 --- /dev/null +++ b/src/core/hle/service/sockets/bsd_nu.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" +#include "core/hle/service/kernel_helpers.h" + +namespace Core { +class System; +} + +namespace Service::Sockets { + +class ISfUserService final : public ServiceFramework { +public: + explicit ISfUserService(Core::System& system_); + ~ISfUserService() override; + +private: + void Assign(HLERequestContext& ctx); + void GetUserInfo(HLERequestContext& ctx); + void GetStateChangedEvent(HLERequestContext& ctx); + + KernelHelpers::ServiceContext service_context; +}; + +class ISfAssignedNetworkInterfaceService final : public ServiceFramework { +public: + explicit ISfAssignedNetworkInterfaceService(Core::System& system_); + ~ISfAssignedNetworkInterfaceService() override; + +private: + void AddSession(HLERequestContext& ctx); +}; + +class BSD_NU final : public ServiceFramework { +public: + explicit BSD_NU(Core::System& system_); + ~BSD_NU() override; + +private: + void CreateUserService(HLERequestContext& ctx); +}; + +} // namespace Service::Sockets \ No newline at end of file diff --git a/src/core/hle/service/sockets/bsdcfg.cpp b/src/core/hle/service/sockets/bsdcfg.cpp new file mode 100644 index 000000000..3a74302fa --- /dev/null +++ b/src/core/hle/service/sockets/bsdcfg.cpp @@ -0,0 +1,140 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/kernel_helpers.h" +#include "core/hle/service/sockets/bsdcfg.h" + +namespace Service::Sockets { + +BSDCFG::BSDCFG(Core::System& system_) + : ServiceFramework{system_, "bsdcfg"}, + service_context{system_, "BSDCFG"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &BSDCFG::SetIfUp, "SetIfUp"}, + {1, &BSDCFG::SetIfUpWithEvent, "SetIfUpWithEvent"}, + {2, &BSDCFG::CancelIf, "CancelIf"}, + {3, &BSDCFG::SetIfDown, "SetIfDown"}, + {4, &BSDCFG::GetIfState, "GetIfState"}, + {5, &BSDCFG::DhcpRenew, "DhcpRenew"}, + {6, &BSDCFG::AddStaticArpEntry, "AddStaticArpEntry"}, + {7, &BSDCFG::RemoveArpEntry, "RemoveArpEntry"}, + {8, &BSDCFG::LookupArpEntry, "LookupArpEntry"}, + {9, &BSDCFG::LookupArpEntry2, "LookupArpEntry2"}, + {10, &BSDCFG::ClearArpEntries, "ClearArpEntries"}, + {11, &BSDCFG::ClearArpEntries2, "ClearArpEntries2"}, + {12, &BSDCFG::PrintArpEntries, "PrintArpEntries"}, + {13, &BSDCFG::Cmd13, "Unknown13"}, + {14, &BSDCFG::Cmd14, "Unknown14"}, + {15, &BSDCFG::Cmd15, "Unknown15"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +BSDCFG::~BSDCFG() = default; + +void BSDCFG::SetIfUp(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::SetIfUpWithEvent(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + + auto* event = service_context.CreateEvent("BSDCFG:SetIfUpWithEvent"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(event->GetReadableEvent()); +} + +void BSDCFG::CancelIf(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::SetIfDown(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::GetIfState(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(1); // Interface is up (stubbed) +} + +void BSDCFG::DhcpRenew(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::AddStaticArpEntry(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::RemoveArpEntry(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::LookupArpEntry(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::LookupArpEntry2(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::ClearArpEntries(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::ClearArpEntries2(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::PrintArpEntries(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::Cmd13(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::Cmd14(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void BSDCFG::Cmd15(HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +} // namespace Service::Sockets \ No newline at end of file diff --git a/src/core/hle/service/sockets/bsdcfg.h b/src/core/hle/service/sockets/bsdcfg.h new file mode 100644 index 000000000..9935fd591 --- /dev/null +++ b/src/core/hle/service/sockets/bsdcfg.h @@ -0,0 +1,41 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" +#include "core/hle/service/kernel_helpers.h" + +namespace Core { +class System; +} + +namespace Service::Sockets { + +class BSDCFG final : public ServiceFramework { +public: + explicit BSDCFG(Core::System& system_); + ~BSDCFG() override; + +private: + void SetIfUp(HLERequestContext& ctx); + void SetIfUpWithEvent(HLERequestContext& ctx); + void CancelIf(HLERequestContext& ctx); + void SetIfDown(HLERequestContext& ctx); + void GetIfState(HLERequestContext& ctx); + void DhcpRenew(HLERequestContext& ctx); + void AddStaticArpEntry(HLERequestContext& ctx); + void RemoveArpEntry(HLERequestContext& ctx); + void LookupArpEntry(HLERequestContext& ctx); + void LookupArpEntry2(HLERequestContext& ctx); + void ClearArpEntries(HLERequestContext& ctx); + void ClearArpEntries2(HLERequestContext& ctx); + void PrintArpEntries(HLERequestContext& ctx); + void Cmd13(HLERequestContext& ctx); + void Cmd14(HLERequestContext& ctx); + void Cmd15(HLERequestContext& ctx); + + KernelHelpers::ServiceContext service_context; +}; + +} // namespace Service::Sockets \ No newline at end of file diff --git a/src/core/hle/service/sockets/dns_priv.cpp b/src/core/hle/service/sockets/dns_priv.cpp new file mode 100644 index 000000000..631d62379 --- /dev/null +++ b/src/core/hle/service/sockets/dns_priv.cpp @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/sockets/dns_priv.h" + +namespace Service::Sockets { + +DNS_PRIV::DNS_PRIV(Core::System& system_) : ServiceFramework{system_, "dns:priv"} { + // dns:priv doesn't have documented commands yet + static const FunctionInfo functions[] = { + {0, nullptr, "DummyFunction"}, + }; + + RegisterHandlers(functions); +} + +DNS_PRIV::~DNS_PRIV() = default; + +} // namespace Service::Sockets \ No newline at end of file diff --git a/src/core/hle/service/sockets/dns_priv.h b/src/core/hle/service/sockets/dns_priv.h new file mode 100644 index 000000000..9e74bc82c --- /dev/null +++ b/src/core/hle/service/sockets/dns_priv.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::Sockets { + +class DNS_PRIV final : public ServiceFramework { +public: + explicit DNS_PRIV(Core::System& system_); + ~DNS_PRIV() override; +}; + +} // namespace Service::Sockets \ No newline at end of file diff --git a/src/core/hle/service/sockets/ethc.cpp b/src/core/hle/service/sockets/ethc.cpp new file mode 100644 index 000000000..f7f93d3eb --- /dev/null +++ b/src/core/hle/service/sockets/ethc.cpp @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/sockets/ethc.h" + +namespace Service::Sockets { + +ETHC_C::ETHC_C(Core::System& system_) : ServiceFramework{system_, "ethc:c"} { + // ethc:c doesn't have documented commands yet + static const FunctionInfo functions[] = { + {0, nullptr, "DummyFunction"}, + }; + + RegisterHandlers(functions); +} + +ETHC_C::~ETHC_C() = default; + +ETHC_I::ETHC_I(Core::System& system_) : ServiceFramework{system_, "ethc:i"} { + // ethc:i doesn't have documented commands yet + static const FunctionInfo functions[] = { + {0, nullptr, "DummyFunction"}, + }; + + RegisterHandlers(functions); +} + +ETHC_I::~ETHC_I() = default; + +} // namespace Service::Sockets \ No newline at end of file diff --git a/src/core/hle/service/sockets/ethc.h b/src/core/hle/service/sockets/ethc.h new file mode 100644 index 000000000..7837a6fff --- /dev/null +++ b/src/core/hle/service/sockets/ethc.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::Sockets { + +class ETHC_C final : public ServiceFramework { +public: + explicit ETHC_C(Core::System& system_); + ~ETHC_C() override; +}; + +class ETHC_I final : public ServiceFramework { +public: + explicit ETHC_I(Core::System& system_); + ~ETHC_I() override; +}; + +} // namespace Service::Sockets \ No newline at end of file diff --git a/src/core/hle/service/sockets/sockets.cpp b/src/core/hle/service/sockets/sockets.cpp index 676d24e03..ba42ffebc 100644 --- a/src/core/hle/service/sockets/sockets.cpp +++ b/src/core/hle/service/sockets/sockets.cpp @@ -1,8 +1,13 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/server_manager.h" #include "core/hle/service/sockets/bsd.h" +#include "core/hle/service/sockets/bsd_nu.h" +#include "core/hle/service/sockets/bsdcfg.h" +#include "core/hle/service/sockets/dns_priv.h" +#include "core/hle/service/sockets/ethc.h" #include "core/hle/service/sockets/nsd.h" #include "core/hle/service/sockets/sfdnsres.h" #include "core/hle/service/sockets/sockets.h" @@ -12,12 +17,33 @@ namespace Service::Sockets { void LoopProcess(Core::System& system) { auto server_manager = std::make_unique(system); + // Register BSD services server_manager->RegisterNamedService("bsd:s", std::make_shared(system, "bsd:s")); server_manager->RegisterNamedService("bsd:u", std::make_shared(system, "bsd:u")); + + // Register BSD:A service for [18.0.0+] + server_manager->RegisterNamedService("bsd:a", std::make_shared(system, "bsd:a")); + + // Register BSD:NU service for [15.0.0+] + server_manager->RegisterNamedService("bsd:nu", std::make_shared(system)); + + // Register BSDCFG service server_manager->RegisterNamedService("bsdcfg", std::make_shared(system)); + + // Register NSD services server_manager->RegisterNamedService("nsd:a", std::make_shared(system, "nsd:a")); server_manager->RegisterNamedService("nsd:u", std::make_shared(system, "nsd:u")); + + // Register SFDNSRES service server_manager->RegisterNamedService("sfdnsres", std::make_shared(system)); + + // Register DNS:PRIV service + server_manager->RegisterNamedService("dns:priv", std::make_shared(system)); + + // Register ETHC services + server_manager->RegisterNamedService("ethc:c", std::make_shared(system)); + server_manager->RegisterNamedService("ethc:i", std::make_shared(system)); + server_manager->StartAdditionalHostThreads("bsdsocket", 2); ServerManager::RunServer(std::move(server_manager)); }