diff --git a/libraries/libstratosphere/include/stratosphere/ams/impl/ams_system_thread_definitions.hpp b/libraries/libstratosphere/include/stratosphere/ams/impl/ams_system_thread_definitions.hpp
index 06a1e0269..ff789a78d 100644
--- a/libraries/libstratosphere/include/stratosphere/ams/impl/ams_system_thread_definitions.hpp
+++ b/libraries/libstratosphere/include/stratosphere/ams/impl/ams_system_thread_definitions.hpp
@@ -113,6 +113,9 @@ namespace ams::impl {
AMS_DEFINE_SYSTEM_THREAD(21, erpt, Main);
AMS_DEFINE_SYSTEM_THREAD(21, erpt, IpcServer);
+ /* socket. */
+ AMS_DEFINE_SYSTEM_THREAD(29, socket, ResolverIpcServer);
+
/* jpegdec. */
AMS_DEFINE_SYSTEM_THREAD(21, jpegdec, Main);
diff --git a/libraries/libstratosphere/include/stratosphere/socket.hpp b/libraries/libstratosphere/include/stratosphere/socket.hpp
new file mode 100644
index 000000000..d43f92384
--- /dev/null
+++ b/libraries/libstratosphere/include/stratosphere/socket.hpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+#include
diff --git a/libraries/libstratosphere/include/stratosphere/socket/socket_types.hpp b/libraries/libstratosphere/include/stratosphere/socket/socket_types.hpp
new file mode 100644
index 000000000..bac58080f
--- /dev/null
+++ b/libraries/libstratosphere/include/stratosphere/socket/socket_types.hpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+#include
+
+namespace ams::socket {
+
+ using InAddrT = u32;
+ using InPortT = u16;
+ using SockLenT = u32;
+ using NfdsT = u64;
+ using FdMask = u64;
+
+ constexpr inline unsigned int FdSetSize = 0x400;
+
+ template
+ constexpr inline InAddrT EncodeInAddr = (A << 24) | (B << 16) | (C << 8) | (D << 0);
+
+ constexpr inline InAddrT InAddr_Any = EncodeInAddr< 0, 0, 0, 0>;
+ constexpr inline InAddrT InAddr_Broadcast = EncodeInAddr<255, 255, 255, 255>;
+ constexpr inline InAddrT InAddr_None = EncodeInAddr<255, 255, 255, 255>;
+ constexpr inline InAddrT InAddr_Loopback = EncodeInAddr<127, 0, 0, 1>;
+
+ enum class Family : u8 {
+ Af_Unspec = 0,
+ Pf_Unspec = Af_Unspec,
+
+ Af_Inet = 2,
+ Pf_Inet = Af_Inet,
+
+ Af_Route = 17,
+ Pf_Route = Af_Route,
+
+ Af_Link = 18,
+ Pf_Link = Af_Link,
+
+ Af_Inet6 = 28,
+ Pf_Inet6 = Af_Inet6,
+
+ Af_Max = 42,
+ Pf_Max = Af_Max
+ };
+
+ struct HostEnt {
+ char *h_name;
+ char **h_aliases;
+ Family h_addrtype;
+ int h_length;
+ char **h_addr_list;
+ };
+
+}
diff --git a/stratosphere/ams_mitm/source/amsmitm_module_management.cpp b/stratosphere/ams_mitm/source/amsmitm_module_management.cpp
index 1bd12f55f..436c95e43 100644
--- a/stratosphere/ams_mitm/source/amsmitm_module_management.cpp
+++ b/stratosphere/ams_mitm/source/amsmitm_module_management.cpp
@@ -22,6 +22,7 @@
#include "bpc_mitm/bpcmitm_module.hpp"
#include "bpc_mitm/bpc_ams_module.hpp"
#include "ns_mitm/nsmitm_module.hpp"
+#include "dns_mitm/dnsmitm_module.hpp"
#include "sysupdater/sysupdater_module.hpp"
namespace ams::mitm {
@@ -34,6 +35,7 @@ namespace ams::mitm {
ModuleId_BpcMitm,
ModuleId_BpcAms,
ModuleId_NsMitm,
+ ModuleId_DnsMitm,
ModuleId_Sysupdater,
ModuleId_Count,
@@ -66,6 +68,7 @@ namespace ams::mitm {
GetModuleDefinition(),
GetModuleDefinition(),
GetModuleDefinition(),
+ GetModuleDefinition(),
GetModuleDefinition(),
};
diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_debug.cpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_debug.cpp
new file mode 100644
index 000000000..81d67a9f3
--- /dev/null
+++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_debug.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include
+#include "../amsmitm_fs_utils.hpp"
+#include "dnsmitm_debug.hpp"
+
+namespace ams::mitm::socket::resolver {
+
+ #if 1
+
+ namespace {
+
+ ::FsFile g_log_file;
+ s64 g_log_ofs;
+
+ os::SdkMutex g_log_mutex;
+
+ char g_log_buf[0x400];
+
+ }
+
+ void InitializeDebug() {
+ /* Create the log file. */
+ mitm::fs::CreateAtmosphereSdFile("dns_log.txt", 0, ams::fs::CreateOption_None);
+
+ /* Open the log file. */
+ R_ABORT_UNLESS(mitm::fs::OpenAtmosphereSdFile(std::addressof(g_log_file), "dns_log.txt", ams::fs::OpenMode_ReadWrite | ams::fs::OpenMode_AllowAppend));
+
+ /* Get the current log offset. */
+ R_ABORT_UNLESS(::fsFileGetSize(std::addressof(g_log_file), std::addressof(g_log_ofs)));
+
+ /* Start a new log. */
+ LogDebug("\n---\n");
+ }
+
+ void LogDebug(const char *fmt, ...) {
+ std::scoped_lock lk(g_log_mutex);
+
+ int len = 0;
+ {
+ std::va_list vl;
+ va_start(vl, fmt);
+ len = util::VSNPrintf(g_log_buf, sizeof(g_log_buf), fmt, vl);
+ va_end(vl);
+ }
+
+ R_ABORT_UNLESS(::fsFileWrite(std::addressof(g_log_file), g_log_ofs, g_log_buf, len, FsWriteOption_Flush));
+ g_log_ofs += len;
+ }
+
+ #else
+
+ void InitializeDebug() {
+ /* ... */
+ }
+
+ void LogDebug(const char *fmt, ...) {
+ /* ... */
+ }
+
+ #endif
+
+}
diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_debug.hpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_debug.hpp
new file mode 100644
index 000000000..ce6848fdf
--- /dev/null
+++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_debug.hpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+#include
+
+namespace ams::mitm::socket::resolver {
+
+ void InitializeDebug();
+
+ void LogDebug(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+
+}
diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp
new file mode 100644
index 000000000..827019d17
--- /dev/null
+++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include
+#include "../amsmitm_initialization.hpp"
+#include "dnsmitm_module.hpp"
+#include "dnsmitm_resolver_impl.hpp"
+#include "dnsmitm_debug.hpp"
+
+namespace ams::mitm::socket::resolver {
+
+ namespace {
+
+ enum PortIndex {
+ PortIndex_Mitm,
+ PortIndex_Count,
+ };
+
+ constexpr sm::ServiceName DnsMitmServiceName = sm::ServiceName::Encode("sfdnsres");
+
+ constexpr size_t MaxSessions = 30;
+ using ServerOptions = sf::hipc::DefaultServerManagerOptions;
+
+ class ServerManager final : public sf::hipc::ServerManager {
+ private:
+ virtual Result OnNeedsToAccept(int port_index, Server *server) override;
+ };
+
+ ServerManager g_server_manager;
+
+ Result ServerManager::OnNeedsToAccept(int port_index, Server *server) {
+ /* Acknowledge the mitm session. */
+ std::shared_ptr<::Service> fsrv;
+ sm::MitmProcessInfo client_info;
+ server->AcknowledgeMitmSession(std::addressof(fsrv), std::addressof(client_info));
+
+ switch (port_index) {
+ case PortIndex_Mitm:
+ return this->AcceptMitmImpl(server, sf::CreateSharedObjectEmplaced(decltype(fsrv)(fsrv), client_info), fsrv);
+ AMS_UNREACHABLE_DEFAULT_CASE();
+ }
+ }
+
+ constexpr size_t TotalThreads = 8;
+ static_assert(TotalThreads >= 1, "TotalThreads");
+ constexpr size_t NumExtraThreads = TotalThreads - 1;
+ constexpr size_t ThreadStackSize = mitm::ModuleTraits::StackSize;
+ alignas(os::MemoryPageSize) u8 g_extra_thread_stacks[NumExtraThreads][ThreadStackSize];
+
+ os::ThreadType g_extra_threads[NumExtraThreads];
+
+ void LoopServerThread(void *arg) {
+ /* Loop forever, servicing our services. */
+ g_server_manager.LoopProcess();
+ }
+
+ void ProcessForServerOnAllThreads() {
+ /* Initialize threads. */
+ if constexpr (NumExtraThreads > 0) {
+ const s32 priority = os::GetThreadCurrentPriority(os::GetCurrentThread());
+ for (size_t i = 0; i < NumExtraThreads; i++) {
+ R_ABORT_UNLESS(os::CreateThread(g_extra_threads + i, LoopServerThread, nullptr, g_extra_thread_stacks[i], ThreadStackSize, priority));
+ }
+ }
+
+ /* Start extra threads. */
+ if constexpr (NumExtraThreads > 0) {
+ for (size_t i = 0; i < NumExtraThreads; i++) {
+ os::StartThread(g_extra_threads + i);
+ }
+ }
+
+ /* Loop this thread. */
+ LoopServerThread(nullptr);
+
+ /* Wait for extra threads to finish. */
+ if constexpr (NumExtraThreads > 0) {
+ for (size_t i = 0; i < NumExtraThreads; i++) {
+ os::WaitThread(g_extra_threads + i);
+ }
+ }
+ }
+
+ }
+
+ void MitmModule::ThreadFunction(void *arg) {
+ /* Wait until initialization is complete. */
+ mitm::WaitInitialized();
+
+ /* Initialize debug. */
+ resolver::InitializeDebug();
+
+ /* Create mitm servers. */
+ R_ABORT_UNLESS((g_server_manager.RegisterMitmServer(PortIndex_Mitm, DnsMitmServiceName)));
+
+ /* Loop forever, servicing our services. */
+ ProcessForServerOnAllThreads();
+ }
+
+}
diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.hpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.hpp
new file mode 100644
index 000000000..59756d319
--- /dev/null
+++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_module.hpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+#include
+#include "../amsmitm_module.hpp"
+
+namespace ams::mitm::socket::resolver {
+
+ DEFINE_MITM_MODULE_CLASS(0x2000, AMS_GET_SYSTEM_THREAD_PRIORITY(socket, ResolverIpcServer) - 1);
+
+}
diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.cpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.cpp
new file mode 100644
index 000000000..9ab72463f
--- /dev/null
+++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include
+#include "dnsmitm_resolver_impl.hpp"
+#include "dnsmitm_debug.hpp"
+
+namespace ams::mitm::socket::resolver {
+
+ Result ResolverImpl::GetHostByNameRequest(u32 cancel_handle, const sf::ClientProcessId &client_pid, bool use_nsd_resolve, const sf::InBuffer &name, sf::Out out_host_error, sf::Out out_errno, const sf::OutBuffer &out_hostent, sf::Out out_size) {
+ LogDebug("[%016lx]: GetHostByNameRequest(%s)\n", this->client_info.program_id.value, reinterpret_cast(name.GetPointer()));
+ return sm::mitm::ResultShouldForwardToSession();
+ }
+
+ Result ResolverImpl::GetAddrInfoRequest(u32 cancel_handle, const sf::ClientProcessId &client_pid, bool use_nsd_resolve, const sf::InBuffer &node, const sf::InBuffer &srv, const sf::InBuffer &serialized_hint, const sf::OutBuffer &out_addrinfo, sf::Out out_errno, sf::Out out_retval, sf::Out out_size) {
+ LogDebug("[%016lx]: GetAddrInfoRequest(%s, %s)\n", this->client_info.program_id.value, reinterpret_cast(node.GetPointer()), reinterpret_cast(srv.GetPointer()));
+ return sm::mitm::ResultShouldForwardToSession();
+ }
+
+ Result ResolverImpl::GetHostByNameRequestWithOptions(const sf::ClientProcessId &client_pid, const sf::InAutoSelectBuffer &name, const sf::OutAutoSelectBuffer &out_hostent, sf::Out out_size, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out out_host_error, sf::Out out_errno) {
+ LogDebug("[%016lx]: GetHostByNameRequestWithOptions(%s)\n", this->client_info.program_id.value, reinterpret_cast(name.GetPointer()));
+ return sm::mitm::ResultShouldForwardToSession();
+ }
+
+ Result ResolverImpl::GetAddrInfoRequestWithOptions(const sf::ClientProcessId &client_pid, const sf::InBuffer &node, const sf::InBuffer &srv, const sf::InBuffer &serialized_hint, const sf::OutAutoSelectBuffer &out_addrinfo, sf::Out out_size, sf::Out out_retval, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out out_host_error, sf::Out out_errno) {
+ LogDebug("[%016lx]: GetAddrInfoRequestWithOptions(%s, %s)\n", this->client_info.program_id.value, reinterpret_cast(node.GetPointer()), reinterpret_cast(srv.GetPointer()));
+ return sm::mitm::ResultShouldForwardToSession();
+ }
+
+}
diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.hpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.hpp
new file mode 100644
index 000000000..90c472bc3
--- /dev/null
+++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.hpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+#include
+
+#define AMS_DNS_MITM_INTERFACE_INFO(C, H) \
+ AMS_SF_METHOD_INFO(C, H, 2, Result, GetHostByNameRequest, (u32 cancel_handle, const sf::ClientProcessId &client_pid, bool use_nsd_resolve, const sf::InBuffer &name, sf::Out out_host_error, sf::Out out_errno, const sf::OutBuffer &out_hostent, sf::Out out_size), (cancel_handle, client_pid, use_nsd_resolve, name, out_host_error, out_errno, out_hostent, out_size)) \
+ AMS_SF_METHOD_INFO(C, H, 6, Result, GetAddrInfoRequest, (u32 cancel_handle, const sf::ClientProcessId &client_pid, bool use_nsd_resolve, const sf::InBuffer &node, const sf::InBuffer &srv, const sf::InBuffer &serialized_hint, const sf::OutBuffer &out_addrinfo, sf::Out out_errno, sf::Out out_retval, sf::Out out_size), (cancel_handle, client_pid, use_nsd_resolve, node, srv, serialized_hint, out_addrinfo, out_errno, out_retval, out_size)) \
+ AMS_SF_METHOD_INFO(C, H, 10, Result, GetHostByNameRequestWithOptions, (const sf::ClientProcessId &client_pid, const sf::InAutoSelectBuffer &name, const sf::OutAutoSelectBuffer &out_hostent, sf::Out out_size, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out out_host_error, sf::Out out_errno), (client_pid, name, out_hostent, out_size, options_version, options, num_options, out_host_error, out_errno), hos::Version_5_0_0) \
+ AMS_SF_METHOD_INFO(C, H, 12, Result, GetAddrInfoRequestWithOptions, (const sf::ClientProcessId &client_pid, const sf::InBuffer &node, const sf::InBuffer &srv, const sf::InBuffer &serialized_hint, const sf::OutAutoSelectBuffer &out_addrinfo, sf::Out out_size, sf::Out out_retval, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out out_host_error, sf::Out out_errno), (client_pid, node, srv, serialized_hint, out_addrinfo, out_size, out_retval, options_version, options, num_options, out_host_error, out_errno), hos::Version_5_0_0)
+
+AMS_SF_DEFINE_MITM_INTERFACE(ams::mitm::socket::resolver, IResolver, AMS_DNS_MITM_INTERFACE_INFO)
+
+namespace ams::mitm::socket::resolver {
+
+ class ResolverImpl : public sf::MitmServiceImplBase {
+ public:
+ using MitmServiceImplBase::MitmServiceImplBase;
+ public:
+ static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
+ /* We will mitm:
+ * - everything.
+ */
+ return true;
+ }
+ public:
+ /* Overridden commands. */
+ Result GetHostByNameRequest(u32 cancel_handle, const sf::ClientProcessId &client_pid, bool use_nsd_resolve, const sf::InBuffer &name, sf::Out out_host_error, sf::Out out_errno, const sf::OutBuffer &out_hostent, sf::Out out_size);
+ Result GetAddrInfoRequest(u32 cancel_handle, const sf::ClientProcessId &client_pid, bool use_nsd_resolve, const sf::InBuffer &node, const sf::InBuffer &srv, const sf::InBuffer &serialized_hint, const sf::OutBuffer &out_addrinfo, sf::Out out_errno, sf::Out out_retval, sf::Out out_size);
+ Result GetHostByNameRequestWithOptions(const sf::ClientProcessId &client_pid, const sf::InAutoSelectBuffer &name, const sf::OutAutoSelectBuffer &out_hostent, sf::Out out_size, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out out_host_error, sf::Out out_errno);
+ Result GetAddrInfoRequestWithOptions(const sf::ClientProcessId &client_pid, const sf::InBuffer &node, const sf::InBuffer &srv, const sf::InBuffer &serialized_hint, const sf::OutAutoSelectBuffer &out_addrinfo, sf::Out out_size, sf::Out out_retval, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out out_host_error, sf::Out out_errno);
+ };
+ static_assert(IsIResolver);
+
+}