diff --git a/docs/features/dns_mitm.md b/docs/features/dns_mitm.md index 8040fca71..e61f499c2 100644 --- a/docs/features/dns_mitm.md +++ b/docs/features/dns_mitm.md @@ -11,6 +11,8 @@ In particular, hosts files parsed by DNS.mitm have the following extensions to t + `*` is treated as a wildcard character, matching any collection of 0 or more characters wherever it occurs in a hostname. + `%` is treated as a stand-in for the value of `nsd!environment_identifier`. This is always `lp1`, on production devices. +If multiple entries in a host file match a domain, the last-defined match is used. + Please note that homebrew may trigger a hosts file re-parse by sending the extension IPC command 65000 ("AtmosphereReloadHostsFile") to a connected `sfdnsres` session. ### Hosts file selection diff --git a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_host_redirection.cpp b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_host_redirection.cpp index e608f3387..4cc945678 100644 --- a/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_host_redirection.cpp +++ b/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_host_redirection.cpp @@ -69,7 +69,21 @@ namespace ams::mitm::socket::resolver { "127.0.0.1 receive-%.dg.srv.nintendo.net receive-%.er.srv.nintendo.net\n"; constinit os::SdkMutex g_redirection_lock; - std::unordered_map g_redirection_map; + std::vector> g_redirection_list; + + void RemoveRedirection(const char *hostname) { + for (auto it = g_redirection_list.begin(); it != g_redirection_list.end(); ++it) { + if (std::strcmp(it->first.c_str(), hostname) == 0) { + g_redirection_list.erase(it); + break; + } + } + } + + void AddRedirection(const char *hostname, ams::socket::InAddrT addr) { + RemoveRedirection(hostname); + g_redirection_list.emplace(g_redirection_list.begin(), std::string(hostname), addr); + } constinit char g_specific_emummc_hosts_path[0x40] = {}; @@ -206,7 +220,7 @@ namespace ams::mitm::socket::resolver { AMS_ABORT_UNLESS(work < sizeof(current_hostname)); current_hostname[work] = '\x00'; - g_redirection_map[static_cast(current_hostname)] = current_address; + AddRedirection(current_hostname, current_address); work = 0; if (c == '\n') { @@ -229,7 +243,7 @@ namespace ams::mitm::socket::resolver { AMS_ABORT_UNLESS(work < sizeof(current_hostname)); current_hostname[work] = '\x00'; - g_redirection_map[static_cast(current_hostname)] = current_address; + AddRedirection(current_hostname, current_address); } } @@ -293,7 +307,7 @@ namespace ams::mitm::socket::resolver { std::scoped_lock lk(g_redirection_lock); /* Clear the redirections map. */ - g_redirection_map.clear(); + g_redirection_list.clear(); /* Open log file. */ ::FsFile log_file; @@ -362,7 +376,7 @@ namespace ams::mitm::socket::resolver { /* Print the redirections. */ Log(log_file, "Redirections:\n"); - for (const auto &[host, address] : g_redirection_map) { + for (const auto &[host, address] : g_redirection_list) { Log(log_file, " `%s` -> %u.%u.%u.%u\n", host.c_str(), (address >> 0) & 0xFF, (address >> 8) & 0xFF, (address >> 16) & 0xFF, (address >> 24) & 0xFF); } } @@ -370,7 +384,7 @@ namespace ams::mitm::socket::resolver { bool GetRedirectedHostByName(ams::socket::InAddrT *out, const char *hostname) { std::scoped_lock lk(g_redirection_lock); - for (const auto &[host, address] : g_redirection_map) { + for (const auto &[host, address] : g_redirection_list) { if (wildcardcmp(host.c_str(), hostname)) { *out = address; return true;