Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"
This reverts commit 15b7df8ef1.
This commit is contained in:
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../amsmitm_fs_utils.hpp"
|
||||
#include "dnsmitm_debug.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit os::SdkMutex g_log_mutex;
|
||||
constinit bool g_log_enabled;
|
||||
|
||||
constinit ::FsFile g_log_file;
|
||||
constinit s64 g_log_ofs;
|
||||
|
||||
|
||||
constinit char g_log_buf[0x400];
|
||||
|
||||
}
|
||||
|
||||
void InitializeDebug(bool enable_log) {
|
||||
{
|
||||
std::scoped_lock lk(g_log_mutex);
|
||||
|
||||
g_log_enabled = enable_log;
|
||||
|
||||
if (g_log_enabled) {
|
||||
/* Create the logs directory. */
|
||||
mitm::fs::CreateAtmosphereSdDirectory("/logs");
|
||||
|
||||
/* Create the log file. */
|
||||
mitm::fs::CreateAtmosphereSdFile("/logs/dns_mitm_debug.log", 0, ams::fs::CreateOption_None);
|
||||
|
||||
/* Open the log file. */
|
||||
R_ABORT_UNLESS(mitm::fs::OpenAtmosphereSdFile(std::addressof(g_log_file), "/logs/dns_mitm_debug.log", 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);
|
||||
|
||||
if (g_log_enabled) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::mitm::socket::resolver {
|
||||
|
||||
void InitializeDebug(bool enable_log);
|
||||
|
||||
void LogDebug(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
}
|
||||
@@ -1,399 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../amsmitm_fs_utils.hpp"
|
||||
#include "dnsmitm_debug.hpp"
|
||||
#include "dnsmitm_host_redirection.hpp"
|
||||
#include "socket_allocator.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver {
|
||||
|
||||
namespace {
|
||||
|
||||
/* https://github.com/clibs/wildcardcmp */
|
||||
constexpr int wildcardcmp(const char *pattern, const char *string) {
|
||||
const char *w = nullptr; /* last `*` */
|
||||
const char *s = nullptr; /* last checked char */
|
||||
|
||||
/* malformed */
|
||||
if (!pattern || !string) return 0;
|
||||
|
||||
/* loop 1 char at a time */
|
||||
while (1) {
|
||||
if (!*string) {
|
||||
if (!*pattern) return 1;
|
||||
if ('*' == *pattern) return 1;
|
||||
if (!s || !*s) return 0;
|
||||
string = s++;
|
||||
pattern = w;
|
||||
continue;
|
||||
} else {
|
||||
if (*pattern != *string) {
|
||||
if ('*' == *pattern) {
|
||||
w = ++pattern;
|
||||
s = string;
|
||||
/* "*" -> "foobar" */
|
||||
if (*pattern) continue;
|
||||
return 1;
|
||||
} else if (w) {
|
||||
string++;
|
||||
/* "*ooba*" -> "foobar" */
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
string++;
|
||||
pattern++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
constexpr const char DefaultHostsFile[] =
|
||||
"# Nintendo telemetry servers\n"
|
||||
"127.0.0.1 receive-%.dg.srv.nintendo.net receive-%.er.srv.nintendo.net\n";
|
||||
|
||||
constinit os::SdkMutex g_redirection_lock;
|
||||
std::vector<std::pair<std::string, ams::socket::InAddrT>> 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] = {};
|
||||
|
||||
void ParseHostsFile(const char *file_data) {
|
||||
/* Get the environment identifier from settings. */
|
||||
const auto env = ams::nsd::impl::device::GetEnvironmentIdentifierFromSettings();
|
||||
const auto env_len = std::strlen(env.value);
|
||||
|
||||
/* Parse the file. */
|
||||
enum class State {
|
||||
IgnoredLine,
|
||||
BeginLine,
|
||||
Ip1,
|
||||
IpDot1,
|
||||
Ip2,
|
||||
IpDot2,
|
||||
Ip3,
|
||||
IpDot3,
|
||||
Ip4,
|
||||
WhiteSpace,
|
||||
HostName,
|
||||
};
|
||||
|
||||
ams::socket::InAddrT current_address{};
|
||||
char current_hostname[0x200];
|
||||
u32 work{};
|
||||
|
||||
State state = State::BeginLine;
|
||||
for (const char *cur = file_data; *cur != '\x00'; ++cur) {
|
||||
const char c = *cur;
|
||||
switch (state) {
|
||||
case State::IgnoredLine:
|
||||
if (c == '\n') {
|
||||
state = State::BeginLine;
|
||||
}
|
||||
break;
|
||||
case State::BeginLine:
|
||||
if (std::isdigit(static_cast<unsigned char>(c))) {
|
||||
current_address = 0;
|
||||
work = static_cast<u32>(c - '0');
|
||||
state = State::Ip1;
|
||||
} else if (c == '\n') {
|
||||
state = State::BeginLine;
|
||||
} else {
|
||||
state = State::IgnoredLine;
|
||||
}
|
||||
break;
|
||||
case State::Ip1:
|
||||
if (std::isdigit(static_cast<unsigned char>(c))) {
|
||||
work *= 10;
|
||||
work += static_cast<u32>(c - '0');
|
||||
} else if (c == '.') {
|
||||
current_address |= (work & 0xFF) << 0;
|
||||
work = 0;
|
||||
state = State::IpDot1;
|
||||
} else {
|
||||
state = State::IgnoredLine;
|
||||
}
|
||||
break;
|
||||
case State::IpDot1:
|
||||
if (std::isdigit(static_cast<unsigned char>(c))) {
|
||||
work = static_cast<u32>(c - '0');
|
||||
state = State::Ip2;
|
||||
} else {
|
||||
state = State::IgnoredLine;
|
||||
}
|
||||
break;
|
||||
case State::Ip2:
|
||||
if (std::isdigit(static_cast<unsigned char>(c))) {
|
||||
work *= 10;
|
||||
work += static_cast<u32>(c - '0');
|
||||
} else if (c == '.') {
|
||||
current_address |= (work & 0xFF) << 8;
|
||||
work = 0;
|
||||
state = State::IpDot2;
|
||||
} else {
|
||||
state = State::IgnoredLine;
|
||||
}
|
||||
break;
|
||||
case State::IpDot2:
|
||||
if (std::isdigit(static_cast<unsigned char>(c))) {
|
||||
work = static_cast<u32>(c - '0');
|
||||
state = State::Ip3;
|
||||
} else {
|
||||
state = State::IgnoredLine;
|
||||
}
|
||||
break;
|
||||
case State::Ip3:
|
||||
if (std::isdigit(static_cast<unsigned char>(c))) {
|
||||
work *= 10;
|
||||
work += static_cast<u32>(c - '0');
|
||||
} else if (c == '.') {
|
||||
current_address |= (work & 0xFF) << 16;
|
||||
work = 0;
|
||||
state = State::IpDot3;
|
||||
} else {
|
||||
state = State::IgnoredLine;
|
||||
}
|
||||
break;
|
||||
case State::IpDot3:
|
||||
if (std::isdigit(static_cast<unsigned char>(c))) {
|
||||
work = static_cast<u32>(c - '0');
|
||||
state = State::Ip4;
|
||||
} else {
|
||||
state = State::IgnoredLine;
|
||||
}
|
||||
break;
|
||||
case State::Ip4:
|
||||
if (std::isdigit(static_cast<unsigned char>(c))) {
|
||||
work *= 10;
|
||||
work += static_cast<u32>(c - '0');
|
||||
} else if (c == ' ' || c == '\t') {
|
||||
current_address |= (work & 0xFF) << 24;
|
||||
work = 0;
|
||||
state = State::WhiteSpace;
|
||||
} else {
|
||||
state = State::IgnoredLine;
|
||||
}
|
||||
break;
|
||||
case State::WhiteSpace:
|
||||
if (c == '\n') {
|
||||
state = State::BeginLine;
|
||||
} else if (c != ' ' && c != '\r' && c != '\t') {
|
||||
if (c == '%') {
|
||||
std::memcpy(current_hostname, env.value, env_len);
|
||||
work = env_len;
|
||||
} else {
|
||||
current_hostname[0] = c;
|
||||
work = 1;
|
||||
}
|
||||
state = State::HostName;
|
||||
}
|
||||
break;
|
||||
case State::HostName:
|
||||
if (c == ' ' || c == '\r' || c == '\n' || c == '\t') {
|
||||
AMS_ABORT_UNLESS(work < sizeof(current_hostname));
|
||||
current_hostname[work] = '\x00';
|
||||
|
||||
AddRedirection(current_hostname, current_address);
|
||||
work = 0;
|
||||
|
||||
if (c == '\n') {
|
||||
state = State::BeginLine;
|
||||
} else {
|
||||
state = State::WhiteSpace;
|
||||
}
|
||||
} else if (c == '%') {
|
||||
AMS_ABORT_UNLESS(work < sizeof(current_hostname) - env_len);
|
||||
std::memcpy(current_hostname + work, env.value, env_len);
|
||||
work += env_len;
|
||||
} else {
|
||||
AMS_ABORT_UNLESS(work < sizeof(current_hostname) - 1);
|
||||
current_hostname[work++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state == State::HostName) {
|
||||
AMS_ABORT_UNLESS(work < sizeof(current_hostname));
|
||||
current_hostname[work] = '\x00';
|
||||
|
||||
AddRedirection(current_hostname, current_address);
|
||||
}
|
||||
}
|
||||
|
||||
void Log(::FsFile &f, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
|
||||
void Log(::FsFile &f, const char *fmt, ...) {
|
||||
char log_buf[0x100];
|
||||
int len = 0;
|
||||
{
|
||||
std::va_list vl;
|
||||
va_start(vl, fmt);
|
||||
len = util::VSNPrintf(log_buf, sizeof(log_buf), fmt, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
s64 ofs;
|
||||
R_ABORT_UNLESS(::fsFileGetSize(std::addressof(f), std::addressof(ofs)));
|
||||
R_ABORT_UNLESS(::fsFileWrite(std::addressof(f), ofs, log_buf, len, FsWriteOption_Flush));
|
||||
}
|
||||
|
||||
const char *SelectHostsFile(::FsFile &log_file) {
|
||||
Log(log_file, "Selecting hosts file...\n");
|
||||
const bool is_emummc = emummc::IsActive();
|
||||
const u32 emummc_id = emummc::GetActiveId();
|
||||
util::SNPrintf(g_specific_emummc_hosts_path, sizeof(g_specific_emummc_hosts_path), "/hosts/emummc_%04x.txt", emummc_id);
|
||||
|
||||
if (is_emummc) {
|
||||
if (mitm::fs::HasAtmosphereSdFile(g_specific_emummc_hosts_path)) {
|
||||
return g_specific_emummc_hosts_path;
|
||||
}
|
||||
Log(log_file, "Skipping %s because it does not exist...\n", g_specific_emummc_hosts_path);
|
||||
|
||||
if (mitm::fs::HasAtmosphereSdFile("/hosts/emummc.txt")) {
|
||||
return "/hosts/emummc.txt";
|
||||
}
|
||||
Log(log_file, "Skipping %s because it does not exist...\n", "/hosts/emummc.txt");
|
||||
} else {
|
||||
if (mitm::fs::HasAtmosphereSdFile("/hosts/sysmmc.txt")) {
|
||||
return "/hosts/sysmmc.txt";
|
||||
}
|
||||
Log(log_file, "Skipping %s because it does not exist...\n", "/hosts/sysmmc.txt");
|
||||
}
|
||||
|
||||
return "/hosts/default.txt";
|
||||
}
|
||||
|
||||
bool ShouldAddDefaultResolverRedirections() {
|
||||
u8 en = 0;
|
||||
if (settings::fwdbg::GetSettingsItemValue(std::addressof(en), sizeof(en), "atmosphere", "add_defaults_to_dns_hosts") == sizeof(en)) {
|
||||
return (en != 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void InitializeResolverRedirections() {
|
||||
/* Get whether we should add defaults. */
|
||||
const bool add_defaults = ShouldAddDefaultResolverRedirections();
|
||||
|
||||
/* Acquire exclusive access to the map. */
|
||||
std::scoped_lock lk(g_redirection_lock);
|
||||
|
||||
/* Clear the redirections map. */
|
||||
g_redirection_list.clear();
|
||||
|
||||
/* Open log file. */
|
||||
::FsFile log_file;
|
||||
mitm::fs::DeleteAtmosphereSdFile("/logs/dns_mitm_startup.log");
|
||||
mitm::fs::CreateAtmosphereSdDirectory("/logs");
|
||||
R_ABORT_UNLESS(mitm::fs::CreateAtmosphereSdFile("/logs/dns_mitm_startup.log", 0, ams::fs::CreateOption_None));
|
||||
R_ABORT_UNLESS(mitm::fs::OpenAtmosphereSdFile(std::addressof(log_file), "/logs/dns_mitm_startup.log", ams::fs::OpenMode_ReadWrite | ams::fs::OpenMode_AllowAppend));
|
||||
ON_SCOPE_EXIT { ::fsFileClose(std::addressof(log_file)); };
|
||||
|
||||
Log(log_file, "DNS Mitm:\n");
|
||||
|
||||
/* If a default hosts file doesn't exist on the sd card, create one. */
|
||||
if (!mitm::fs::HasAtmosphereSdFile("/hosts/default.txt")) {
|
||||
Log(log_file, "Creating /hosts/default.txt because it does not exist.\n");
|
||||
|
||||
mitm::fs::CreateAtmosphereSdDirectory("/hosts");
|
||||
R_ABORT_UNLESS(mitm::fs::CreateAtmosphereSdFile("/hosts/default.txt", sizeof(DefaultHostsFile) - 1, ams::fs::CreateOption_None));
|
||||
|
||||
::FsFile default_file;
|
||||
R_ABORT_UNLESS(mitm::fs::OpenAtmosphereSdFile(std::addressof(default_file), "/hosts/default.txt", ams::fs::OpenMode_ReadWrite));
|
||||
R_ABORT_UNLESS(::fsFileWrite(std::addressof(default_file), 0, DefaultHostsFile, sizeof(DefaultHostsFile) - 1, ::FsWriteOption_Flush));
|
||||
::fsFileClose(std::addressof(default_file));
|
||||
}
|
||||
|
||||
/* If we should, add the defaults. */
|
||||
if (add_defaults) {
|
||||
Log(log_file, "Adding defaults to redirection list.\n");
|
||||
ParseHostsFile(DefaultHostsFile);
|
||||
}
|
||||
|
||||
/* Select the hosts file. */
|
||||
const char *hosts_path = SelectHostsFile(log_file);
|
||||
Log(log_file, "Selected %s\n", hosts_path);
|
||||
|
||||
/* Load the hosts file. */
|
||||
{
|
||||
char *hosts_file_data = nullptr;
|
||||
ON_SCOPE_EXIT { if (hosts_file_data != nullptr) { ams::Free(hosts_file_data); } };
|
||||
{
|
||||
::FsFile hosts_file;
|
||||
R_ABORT_UNLESS(mitm::fs::OpenAtmosphereSdFile(std::addressof(hosts_file), hosts_path, ams::fs::OpenMode_Read));
|
||||
ON_SCOPE_EXIT { ::fsFileClose(std::addressof(hosts_file)); };
|
||||
|
||||
/* Get the hosts file size. */
|
||||
s64 hosts_size;
|
||||
R_ABORT_UNLESS(::fsFileGetSize(std::addressof(hosts_file), std::addressof(hosts_size)));
|
||||
|
||||
/* Validate we can read the file. */
|
||||
AMS_ABORT_UNLESS(0 <= hosts_size && hosts_size < 0x8000);
|
||||
|
||||
/* Read the data. */
|
||||
hosts_file_data = static_cast<char *>(ams::Malloc(0x8000));
|
||||
AMS_ABORT_UNLESS(hosts_file_data != nullptr);
|
||||
|
||||
u64 br;
|
||||
R_ABORT_UNLESS(::fsFileRead(std::addressof(hosts_file), 0, hosts_file_data, hosts_size, ::FsReadOption_None, std::addressof(br)));
|
||||
AMS_ABORT_UNLESS(br == static_cast<u64>(hosts_size));
|
||||
|
||||
/* Null-terminate. */
|
||||
hosts_file_data[hosts_size] = '\x00';
|
||||
}
|
||||
|
||||
/* Parse the hosts file. */
|
||||
ParseHostsFile(hosts_file_data);
|
||||
}
|
||||
|
||||
/* Print the redirections. */
|
||||
Log(log_file, "Redirections:\n");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
bool GetRedirectedHostByName(ams::socket::InAddrT *out, const char *hostname) {
|
||||
std::scoped_lock lk(g_redirection_lock);
|
||||
|
||||
for (const auto &[host, address] : g_redirection_list) {
|
||||
if (wildcardcmp(host.c_str(), hostname)) {
|
||||
*out = address;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::mitm::socket::resolver {
|
||||
|
||||
void InitializeResolverRedirections();
|
||||
|
||||
bool GetRedirectedHostByName(ams::socket::InAddrT *out, const char *hostname);
|
||||
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../amsmitm_initialization.hpp"
|
||||
#include "dnsmitm_module.hpp"
|
||||
#include "dnsmitm_debug.hpp"
|
||||
#include "dnsmitm_resolver_impl.hpp"
|
||||
#include "dnsmitm_host_redirection.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;
|
||||
|
||||
struct ServerOptions {
|
||||
static constexpr size_t PointerBufferSize = sf::hipc::DefaultServerManagerOptions::PointerBufferSize;
|
||||
static constexpr size_t MaxDomains = sf::hipc::DefaultServerManagerOptions::MaxDomains;
|
||||
static constexpr size_t MaxDomainObjects = sf::hipc::DefaultServerManagerOptions::MaxDomainObjects;
|
||||
static constexpr bool CanDeferInvokeRequest = sf::hipc::DefaultServerManagerOptions::CanDeferInvokeRequest;
|
||||
static constexpr bool CanManageMitmServers = true;
|
||||
};
|
||||
|
||||
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> {
|
||||
private:
|
||||
virtual Result OnNeedsToAccept(int port_index, Server *server) override;
|
||||
};
|
||||
|
||||
alignas(os::MemoryPageSize) constinit u8 g_resolver_allocator_buffer[16_KB];
|
||||
|
||||
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:
|
||||
R_RETURN(this->AcceptMitmImpl(server, sf::CreateSharedObjectEmplaced<IResolver, ResolverImpl>(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<socket::resolver::MitmModule>::StackSize;
|
||||
alignas(os::MemoryPageSize) u8 g_extra_thread_stacks[NumExtraThreads][ThreadStackSize];
|
||||
|
||||
os::ThreadType g_extra_threads[NumExtraThreads];
|
||||
|
||||
void LoopServerThread(void *) {
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ShouldMitmDns() {
|
||||
u8 en = 0;
|
||||
if (settings::fwdbg::GetSettingsItemValue(std::addressof(en), sizeof(en), "atmosphere", "enable_dns_mitm") == sizeof(en)) {
|
||||
return (en != 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShouldEnableDebugLog() {
|
||||
u8 en = 0;
|
||||
if (settings::fwdbg::GetSettingsItemValue(std::addressof(en), sizeof(en), "atmosphere", "enable_dns_mitm_debug_log") == sizeof(en)) {
|
||||
return (en != 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MitmModule::ThreadFunction(void *) {
|
||||
/* Wait until initialization is complete. */
|
||||
mitm::WaitInitialized();
|
||||
|
||||
/* If we shouldn't mitm dns, don't do anything at all. */
|
||||
if (!ShouldMitmDns()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the socket allocator. */
|
||||
ams::socket::InitializeAllocatorForInternal(g_resolver_allocator_buffer, sizeof(g_resolver_allocator_buffer));
|
||||
|
||||
/* Initialize debug. */
|
||||
resolver::InitializeDebug(ShouldEnableDebugLog());
|
||||
|
||||
/* Initialize redirection map. */
|
||||
resolver::InitializeResolverRedirections();
|
||||
|
||||
/* Create mitm servers. */
|
||||
R_ABORT_UNLESS((g_server_manager.RegisterMitmServer<ResolverImpl>(PortIndex_Mitm, DnsMitmServiceName)));
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
ProcessForServerOnAllThreads();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
#include "../amsmitm_module.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver {
|
||||
|
||||
DEFINE_MITM_MODULE_CLASS(0x2000, AMS_GET_SYSTEM_THREAD_PRIORITY(socket, ResolverIpcServer) - 1);
|
||||
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "dnsmitm_resolver_impl.hpp"
|
||||
#include "dnsmitm_debug.hpp"
|
||||
#include "dnsmitm_host_redirection.hpp"
|
||||
#include "serializer/serializer.hpp"
|
||||
#include "sfdnsres_shim.h"
|
||||
|
||||
namespace ams::mitm::socket::resolver {
|
||||
|
||||
ssize_t SerializeRedirectedHostEnt(u8 * const dst, size_t dst_size, const char *hostname, ams::socket::InAddrT redirect_addr) {
|
||||
struct in_addr addr = { .s_addr = redirect_addr };
|
||||
struct in_addr *addr_list[2] = { std::addressof(addr), nullptr };
|
||||
|
||||
struct hostent ent = {
|
||||
.h_name = const_cast<char *>(hostname),
|
||||
.h_aliases = nullptr,
|
||||
.h_addrtype = AF_INET,
|
||||
.h_length = sizeof(u32),
|
||||
.h_addr_list = (char **)addr_list,
|
||||
};
|
||||
|
||||
const auto result = serializer::DNSSerializer::ToBuffer(dst, dst_size, ent);
|
||||
AMS_ABORT_UNLESS(result >= 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
ssize_t SerializeRedirectedAddrInfo(u8 * const dst, size_t dst_size, const char *hostname, ams::socket::InAddrT redirect_addr, u16 redirect_port, const struct addrinfo *hint) {
|
||||
AMS_UNUSED(hostname);
|
||||
|
||||
struct addrinfo ai = {
|
||||
.ai_flags = 0,
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = 0,
|
||||
.ai_protocol = 0,
|
||||
.ai_addrlen = 0,
|
||||
.ai_canonname = nullptr,
|
||||
.ai_next = nullptr,
|
||||
};
|
||||
|
||||
if (hint != nullptr) {
|
||||
ai = *hint;
|
||||
}
|
||||
|
||||
switch (ai.ai_family) {
|
||||
case AF_UNSPEC: ai.ai_family = AF_INET; break;
|
||||
case AF_INET: ai.ai_family = AF_INET; break;
|
||||
case AF_INET6: AMS_ABORT("Redirected INET6 not supported"); break;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
|
||||
if (ai.ai_socktype == 0) {
|
||||
ai.ai_socktype = SOCK_STREAM;
|
||||
}
|
||||
|
||||
if (ai.ai_protocol == 0) {
|
||||
ai.ai_protocol = IPPROTO_TCP;
|
||||
}
|
||||
|
||||
const struct sockaddr_in sin = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = ams::socket::InetHtons(redirect_port),
|
||||
.sin_addr = { .s_addr = redirect_addr },
|
||||
.sin_zero = {},
|
||||
};
|
||||
|
||||
ai.ai_addrlen = sizeof(sin);
|
||||
ai.ai_addr = (struct sockaddr *)(std::addressof(sin));
|
||||
|
||||
const auto result = serializer::DNSSerializer::ToBuffer(dst, dst_size, ai);
|
||||
AMS_ABORT_UNLESS(result >= 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
Result ResolverImpl::GetHostByNameRequest(u32 cancel_handle, const sf::ClientProcessId &client_pid, bool use_nsd_resolve, const sf::InBuffer &name, sf::Out<u32> out_host_error, sf::Out<u32> out_errno, const sf::OutBuffer &out_hostent, sf::Out<u32> out_size) {
|
||||
AMS_UNUSED(cancel_handle, client_pid, use_nsd_resolve);
|
||||
|
||||
const char *hostname = reinterpret_cast<const char *>(name.GetPointer());
|
||||
|
||||
LogDebug("[%016lx]: GetHostByNameRequest(%s)\n", m_client_info.program_id.value, hostname);
|
||||
|
||||
R_UNLESS(hostname != nullptr, sm::mitm::ResultShouldForwardToSession());
|
||||
|
||||
ams::socket::InAddrT redirect_addr = {};
|
||||
R_UNLESS(GetRedirectedHostByName(std::addressof(redirect_addr), hostname), sm::mitm::ResultShouldForwardToSession());
|
||||
|
||||
LogDebug("[%016lx]: Redirecting %s to %u.%u.%u.%u\n", m_client_info.program_id.value, hostname, (redirect_addr >> 0) & 0xFF, (redirect_addr >> 8) & 0xFF, (redirect_addr >> 16) & 0xFF, (redirect_addr >> 24) & 0xFF);
|
||||
const auto size = SerializeRedirectedHostEnt(out_hostent.GetPointer(), out_hostent.GetSize(), hostname, redirect_addr);
|
||||
|
||||
*out_host_error = 0;
|
||||
*out_errno = 0;
|
||||
*out_size = size;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
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<u32> out_errno, sf::Out<s32> out_retval, sf::Out<u32> out_size) {
|
||||
AMS_UNUSED(cancel_handle, client_pid, use_nsd_resolve);
|
||||
|
||||
const char *hostname = reinterpret_cast<const char *>(node.GetPointer());
|
||||
|
||||
LogDebug("[%016lx]: GetAddrInfoRequest(%s, %s)\n", m_client_info.program_id.value, reinterpret_cast<const char *>(node.GetPointer()), reinterpret_cast<const char *>(srv.GetPointer()));
|
||||
|
||||
R_UNLESS(hostname != nullptr, sm::mitm::ResultShouldForwardToSession());
|
||||
|
||||
ams::socket::InAddrT redirect_addr = {};
|
||||
R_UNLESS(GetRedirectedHostByName(std::addressof(redirect_addr), hostname), sm::mitm::ResultShouldForwardToSession());
|
||||
|
||||
u16 port = 0;
|
||||
if (srv.GetPointer() != nullptr) {
|
||||
for (const char *cur = reinterpret_cast<const char *>(srv.GetPointer()); *cur != 0; ++cur) {
|
||||
AMS_ABORT_UNLESS(std::isdigit(static_cast<unsigned char>(*cur)));
|
||||
port *= 10;
|
||||
port += *cur - '0';
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug("[%016lx]: Redirecting %s:%u to %u.%u.%u.%u\n", m_client_info.program_id.value, hostname, port, (redirect_addr >> 0) & 0xFF, (redirect_addr >> 8) & 0xFF, (redirect_addr >> 16) & 0xFF, (redirect_addr >> 24) & 0xFF);
|
||||
|
||||
const bool use_hint = serialized_hint.GetPointer() != nullptr;
|
||||
struct addrinfo hint = {};
|
||||
if (use_hint) {
|
||||
AMS_ABORT_UNLESS(serializer::DNSSerializer::FromBuffer(hint, serialized_hint.GetPointer(), serialized_hint.GetSize()) >= 0);
|
||||
}
|
||||
ON_SCOPE_EXIT { if (use_hint) { serializer::FreeAddrInfo(hint); } };
|
||||
|
||||
const auto size = SerializeRedirectedAddrInfo(out_addrinfo.GetPointer(), out_addrinfo.GetSize(), hostname, redirect_addr, port, use_hint ? std::addressof(hint) : nullptr);
|
||||
|
||||
*out_retval = 0;
|
||||
*out_errno = 0;
|
||||
*out_size = size;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ResolverImpl::GetHostByNameRequestWithOptions(const sf::ClientProcessId &client_pid, const sf::InAutoSelectBuffer &name, const sf::OutAutoSelectBuffer &out_hostent, sf::Out<u32> out_size, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out<s32> out_host_error, sf::Out<s32> out_errno) {
|
||||
AMS_UNUSED(client_pid, options_version, options, num_options);
|
||||
|
||||
const char *hostname = reinterpret_cast<const char *>(name.GetPointer());
|
||||
|
||||
LogDebug("[%016lx]: GetHostByNameRequestWithOptions(%s)\n", m_client_info.program_id.value, hostname);
|
||||
|
||||
R_UNLESS(hostname != nullptr, sm::mitm::ResultShouldForwardToSession());
|
||||
|
||||
ams::socket::InAddrT redirect_addr = {};
|
||||
R_UNLESS(GetRedirectedHostByName(std::addressof(redirect_addr), hostname), sm::mitm::ResultShouldForwardToSession());
|
||||
|
||||
LogDebug("[%016lx]: Redirecting %s to %u.%u.%u.%u\n", m_client_info.program_id.value, hostname, (redirect_addr >> 0) & 0xFF, (redirect_addr >> 8) & 0xFF, (redirect_addr >> 16) & 0xFF, (redirect_addr >> 24) & 0xFF);
|
||||
const auto size = SerializeRedirectedHostEnt(out_hostent.GetPointer(), out_hostent.GetSize(), hostname, redirect_addr);
|
||||
|
||||
*out_host_error = 0;
|
||||
*out_errno = 0;
|
||||
*out_size = size;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
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<u32> out_size, sf::Out<s32> out_retval, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out<s32> out_host_error, sf::Out<s32> out_errno) {
|
||||
AMS_UNUSED(client_pid, options_version, options, num_options);
|
||||
|
||||
const char *hostname = reinterpret_cast<const char *>(node.GetPointer());
|
||||
|
||||
LogDebug("[%016lx]: GetAddrInfoRequestWithOptions(%s, %s)\n", m_client_info.program_id.value, hostname, reinterpret_cast<const char *>(srv.GetPointer()));
|
||||
|
||||
R_UNLESS(hostname != nullptr, sm::mitm::ResultShouldForwardToSession());
|
||||
|
||||
ams::socket::InAddrT redirect_addr = {};
|
||||
R_UNLESS(GetRedirectedHostByName(std::addressof(redirect_addr), hostname), sm::mitm::ResultShouldForwardToSession());
|
||||
|
||||
u16 port = 0;
|
||||
if (srv.GetPointer() != nullptr) {
|
||||
for (const char *cur = reinterpret_cast<const char *>(srv.GetPointer()); *cur != 0; ++cur) {
|
||||
AMS_ABORT_UNLESS(std::isdigit(static_cast<unsigned char>(*cur)));
|
||||
port *= 10;
|
||||
port += *cur - '0';
|
||||
}
|
||||
}
|
||||
|
||||
LogDebug("[%016lx]: Redirecting %s:%u to %u.%u.%u.%u\n", m_client_info.program_id.value, hostname, port, (redirect_addr >> 0) & 0xFF, (redirect_addr >> 8) & 0xFF, (redirect_addr >> 16) & 0xFF, (redirect_addr >> 24) & 0xFF);
|
||||
|
||||
const bool use_hint = serialized_hint.GetPointer() != nullptr;
|
||||
struct addrinfo hint = {};
|
||||
if (use_hint) {
|
||||
AMS_ABORT_UNLESS(serializer::DNSSerializer::FromBuffer(hint, serialized_hint.GetPointer(), serialized_hint.GetSize()) >= 0);
|
||||
}
|
||||
ON_SCOPE_EXIT { if (use_hint) { serializer::FreeAddrInfo(hint); } };
|
||||
|
||||
const auto size = SerializeRedirectedAddrInfo(out_addrinfo.GetPointer(), out_addrinfo.GetSize(), hostname, redirect_addr, port, use_hint ? std::addressof(hint) : nullptr);
|
||||
|
||||
*out_retval = 0;
|
||||
*out_host_error = 0;
|
||||
*out_errno = 0;
|
||||
*out_size = size;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ResolverImpl::AtmosphereReloadHostsFile() {
|
||||
/* Perform a hosts file reload. */
|
||||
InitializeResolverRedirections();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
#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<u32> out_host_error, sf::Out<u32> out_errno, const sf::OutBuffer &out_hostent, sf::Out<u32> 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<u32> out_errno, sf::Out<s32> out_retval, sf::Out<u32> 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<u32> out_size, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out<s32> out_host_error, sf::Out<s32> 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<u32> out_size, sf::Out<s32> out_retval, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out<s32> out_host_error, sf::Out<s32> 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_METHOD_INFO(C, H, 65000, Result, AtmosphereReloadHostsFile, (), ())
|
||||
|
||||
AMS_SF_DEFINE_MITM_INTERFACE(ams::mitm::socket::resolver, IResolver, AMS_DNS_MITM_INTERFACE_INFO, 0x5935F91A)
|
||||
|
||||
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.
|
||||
*/
|
||||
AMS_UNUSED(client_info);
|
||||
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<u32> out_host_error, sf::Out<u32> out_errno, const sf::OutBuffer &out_hostent, sf::Out<u32> 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<u32> out_errno, sf::Out<s32> out_retval, sf::Out<u32> out_size);
|
||||
Result GetHostByNameRequestWithOptions(const sf::ClientProcessId &client_pid, const sf::InAutoSelectBuffer &name, const sf::OutAutoSelectBuffer &out_hostent, sf::Out<u32> out_size, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out<s32> out_host_error, sf::Out<s32> 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<u32> out_size, sf::Out<s32> out_retval, u32 options_version, const sf::InAutoSelectBuffer &options, u32 num_options, sf::Out<s32> out_host_error, sf::Out<s32> out_errno);
|
||||
|
||||
/* Extension commands. */
|
||||
Result AtmosphereReloadHostsFile();
|
||||
};
|
||||
static_assert(IsIResolver<ResolverImpl>);
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../dnsmitm_debug.hpp"
|
||||
#include "serializer.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver::serializer {
|
||||
|
||||
ssize_t DNSSerializer::CheckToBufferArguments(const u8 *dst, size_t dst_size, size_t required, int error_id) {
|
||||
/* TODO: Logging, using error_id */
|
||||
AMS_UNUSED(error_id);
|
||||
|
||||
if (dst == nullptr) {
|
||||
return -1;
|
||||
} else if (dst_size < required) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 DNSSerializer::InternalHton(const u32 &v) {
|
||||
return ams::socket::InetHtonl(v);
|
||||
}
|
||||
|
||||
u16 DNSSerializer::InternalHton(const u16 &v) {
|
||||
return ams::socket::InetHtons(v);
|
||||
}
|
||||
|
||||
u32 DNSSerializer::InternalNtoh(const u32 &v) {
|
||||
return ams::socket::InetNtohl(v);
|
||||
}
|
||||
|
||||
u16 DNSSerializer::InternalNtoh(const u16 &v) {
|
||||
return ams::socket::InetNtohs(v);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::mitm::socket::resolver::serializer {
|
||||
|
||||
class DNSSerializer {
|
||||
public:
|
||||
static ssize_t CheckToBufferArguments(const u8 *dst, size_t dst_size, size_t required, int error_id);
|
||||
|
||||
static u32 InternalHton(const u32 &v);
|
||||
static u16 InternalHton(const u16 &v);
|
||||
static u32 InternalNtoh(const u32 &v);
|
||||
static u16 InternalNtoh(const u16 &v);
|
||||
public:
|
||||
template<typename T>
|
||||
static size_t SizeOf(const T &in);
|
||||
|
||||
template<typename T>
|
||||
static size_t SizeOf(const T *in);
|
||||
|
||||
template<typename T>
|
||||
static size_t SizeOf(const T *in, size_t count);
|
||||
|
||||
template<typename T>
|
||||
static size_t SizeOf(const T **arr, u32 &out_count);
|
||||
|
||||
template<typename T>
|
||||
static ssize_t ToBuffer(u8 * const dst, size_t dst_size, const T &in);
|
||||
|
||||
template<typename T>
|
||||
static ssize_t FromBuffer(T &out, const u8 *src, size_t src_size);
|
||||
|
||||
template<typename T>
|
||||
static ssize_t ToBuffer(u8 * const dst, size_t dst_Size, T *in);
|
||||
|
||||
template<typename T>
|
||||
static ssize_t ToBuffer(u8 * const dst, size_t dst_size, T **arr);
|
||||
|
||||
template<typename T>
|
||||
static ssize_t FromBuffer(T *&out, const u8 *src, size_t src_size);
|
||||
|
||||
template<typename T>
|
||||
static ssize_t FromBuffer(T **&out_arr, const u8 *src, size_t src_size);
|
||||
|
||||
template<typename T>
|
||||
static ssize_t ToBuffer(u8 * const dst, size_t dst_size, const T * const arr, size_t count);
|
||||
|
||||
template<typename T>
|
||||
static ssize_t FromBuffer(T * const arr, size_t arr_size, const u8 *src, size_t src_size, size_t count);
|
||||
};
|
||||
|
||||
void FreeHostent(ams::socket::HostEnt &ent);
|
||||
void FreeHostent(struct hostent &ent);
|
||||
|
||||
void FreeAddrInfo(ams::socket::AddrInfo &addr_info);
|
||||
void FreeAddrInfo(struct addrinfo &addr_info);
|
||||
|
||||
}
|
||||
@@ -1,444 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../dnsmitm_debug.hpp"
|
||||
#include "../socket_allocator.hpp"
|
||||
#include "serializer.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver::serializer {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr inline u32 AddrInfoMagic = 0xBEEFCAFE;
|
||||
|
||||
template<typename T>
|
||||
concept IsAddrInfo = std::same_as<T, ams::socket::AddrInfo> || std::same_as<T, struct addrinfo>;
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
using SockAddrType = typename std::conditional<std::same_as<T, ams::socket::AddrInfo>, ams::socket::SockAddr, struct sockaddr>::type;
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
using SockAddrInType = typename std::conditional<std::same_as<T, ams::socket::AddrInfo>, ams::socket::SockAddrIn, struct sockaddr_in>::type;
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
using SockAddrIn6Type = typename std::conditional<std::same_as<T, ams::socket::AddrInfo>, struct sockaddr_in6, struct sockaddr_in6>::type;
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
constexpr bool IsAfInet(const auto ai_family) {
|
||||
if constexpr (std::same_as<T, ams::socket::AddrInfo>) {
|
||||
return ai_family == ams::socket::Family::Af_Inet;
|
||||
} else {
|
||||
return ai_family == AF_INET;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
constexpr bool IsAfInet6(const auto ai_family) {
|
||||
if constexpr (std::same_as<T, ams::socket::AddrInfo>) {
|
||||
return ai_family == ams::socket::Family::Af_Inet6;
|
||||
} else {
|
||||
return ai_family == AF_INET;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
void FreeAddrInfoImpl(T &addr_info) {
|
||||
T *next = nullptr;
|
||||
for (T *cur = std::addressof(addr_info); cur != nullptr; cur = next) {
|
||||
next = cur->ai_next;
|
||||
|
||||
if (cur->ai_addr != nullptr) {
|
||||
if (IsAfInet<T>(cur->ai_family)) {
|
||||
ams::socket::impl::Free(reinterpret_cast<SockAddrInType<T> *>(cur->ai_addr));
|
||||
} else if (IsAfInet6<T>(cur->ai_family)) {
|
||||
ams::socket::impl::Free(reinterpret_cast<SockAddrIn6Type<T> *>(cur->ai_addr));
|
||||
} else {
|
||||
ams::socket::impl::Free(cur->ai_addr);
|
||||
}
|
||||
cur->ai_addr = nullptr;
|
||||
}
|
||||
|
||||
if (cur->ai_canonname != nullptr) {
|
||||
ams::socket::impl::Free(cur->ai_canonname);
|
||||
cur->ai_canonname = nullptr;
|
||||
}
|
||||
|
||||
if (cur != std::addressof(addr_info)) {
|
||||
ams::socket::impl::Free(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
size_t AddrInfoSingleSizeOf(const T *addr_info) {
|
||||
size_t rc = 6 * sizeof(u32);
|
||||
|
||||
if (addr_info->ai_addr == nullptr) {
|
||||
rc += sizeof(u32);
|
||||
} else if (IsAfInet<T>(addr_info->ai_family)) {
|
||||
rc += DNSSerializer::SizeOf(*reinterpret_cast<SockAddrInType<T> *>(addr_info->ai_addr));
|
||||
} else if (IsAfInet6<T>(addr_info->ai_family)) {
|
||||
rc += DNSSerializer::SizeOf(*reinterpret_cast<SockAddrIn6Type<T> *>(addr_info->ai_addr));
|
||||
} else if (addr_info->ai_addrlen == 0) {
|
||||
rc += sizeof(u32);
|
||||
} else {
|
||||
rc += addr_info->ai_addrlen;
|
||||
}
|
||||
|
||||
if (addr_info->ai_canonname != nullptr) {
|
||||
rc += DNSSerializer::SizeOf(static_cast<const char *>(addr_info->ai_canonname));
|
||||
} else {
|
||||
rc += sizeof(u8);
|
||||
}
|
||||
|
||||
if (addr_info->ai_next == nullptr) {
|
||||
rc += sizeof(u32);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
size_t SizeOfImpl(const T &in) {
|
||||
size_t rc = 0;
|
||||
|
||||
for (const T *addr_info = std::addressof(in); addr_info != nullptr; addr_info = addr_info->ai_next) {
|
||||
rc += AddrInfoSingleSizeOf(addr_info);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
ssize_t ToBufferInternalImpl(u8 * const dst, size_t dst_size, const T &addr_info) {
|
||||
ssize_t rc = -1;
|
||||
u8 *cur = dst;
|
||||
|
||||
{
|
||||
const u32 value = AddrInfoMagic;
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), value)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
const u32 value = static_cast<u32>(addr_info.ai_flags);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), value)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
const u32 value = static_cast<u32>(addr_info.ai_family);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), value)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
const u32 value = static_cast<u32>(addr_info.ai_socktype);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), value)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
const u32 value = static_cast<u32>(addr_info.ai_protocol);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), value)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
const u32 value = static_cast<u32>(addr_info.ai_addrlen);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), value)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
if (addr_info.ai_addr == nullptr || addr_info.ai_addrlen == 0) {
|
||||
const u32 value = 0;
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), value)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
} else if (IsAfInet<T>(addr_info.ai_family)) {
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), *reinterpret_cast<SockAddrInType<T> *>(addr_info.ai_addr))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
} else if (IsAfInet6<T>(addr_info.ai_family)) {
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), *reinterpret_cast<SockAddrIn6Type<T> *>(addr_info.ai_addr))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
if (dst_size - (cur - dst) < addr_info.ai_addrlen) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* NOTE: This is clearly a nintendo bug, see the accompanying note in FromBufferInternalImpl */
|
||||
std::memmove(cur, std::addressof(addr_info.ai_addr), addr_info.ai_addrlen);
|
||||
rc = addr_info.ai_addrlen;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), addr_info.ai_canonname)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
if (addr_info.ai_next == nullptr) {
|
||||
const u32 value = 0;
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), value)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
rc = cur - dst;
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
ssize_t ToBufferImpl(u8 * const dst, size_t dst_size, const T &in) {
|
||||
ssize_t rc = -1;
|
||||
u8 *cur = dst;
|
||||
std::memset(dst, 0, dst_size);
|
||||
|
||||
const size_t required = DNSSerializer::SizeOf(in);
|
||||
if ((rc = DNSSerializer::CheckToBufferArguments(cur, dst_size, required, __LINE__)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (const T *addr_info = std::addressof(in); addr_info != nullptr; addr_info = addr_info->ai_next) {
|
||||
if ((rc = ToBufferInternalImpl(cur, dst_size, *addr_info)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
rc = cur - dst;
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
ssize_t FromBufferInternalImpl(T &out, const u8 *src, size_t src_size) {
|
||||
ssize_t rc = -1;
|
||||
const u8 *cur = src;
|
||||
|
||||
std::memset(std::addressof(out), 0, sizeof(out));
|
||||
|
||||
ON_SCOPE_EXIT { if (rc < 0) { FreeAddrInfo(out); } };
|
||||
|
||||
u32 tmp_value;
|
||||
|
||||
{
|
||||
if ((rc = DNSSerializer::FromBuffer(tmp_value, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
} else if (tmp_value != AddrInfoMagic) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
if ((rc = DNSSerializer::FromBuffer(tmp_value, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.ai_flags = static_cast<decltype(out.ai_flags)>(tmp_value);
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
if ((rc = DNSSerializer::FromBuffer(tmp_value, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.ai_family = static_cast<decltype(out.ai_family)>(tmp_value);
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
if ((rc = DNSSerializer::FromBuffer(tmp_value, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.ai_socktype = static_cast<decltype(out.ai_socktype)>(tmp_value);
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
if ((rc = DNSSerializer::FromBuffer(tmp_value, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.ai_protocol = static_cast<decltype(out.ai_protocol)>(tmp_value);
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
if ((rc = DNSSerializer::FromBuffer(tmp_value, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.ai_addrlen = static_cast<decltype(out.ai_addrlen)>(tmp_value);
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
if (out.ai_addrlen == 0) {
|
||||
if ((rc = DNSSerializer::FromBuffer(tmp_value, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (tmp_value != 0) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
out.ai_addr = nullptr;
|
||||
} else if (IsAfInet<T>(out.ai_family)) {
|
||||
out.ai_addr = static_cast<SockAddrType<T> *>(ams::socket::impl::Alloc(sizeof(SockAddrInType<T>)));
|
||||
if (out.ai_addr == nullptr) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
std::memset(out.ai_addr, 0, sizeof(SockAddrInType<T>));
|
||||
|
||||
if ((rc = DNSSerializer::FromBuffer(*reinterpret_cast<SockAddrInType<T> *>(out.ai_addr), cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
} else if (IsAfInet6<T>(out.ai_family)) {
|
||||
out.ai_addr = static_cast<SockAddrType<T> *>(ams::socket::impl::Alloc(sizeof(SockAddrIn6Type<T>)));
|
||||
if (out.ai_addr == nullptr) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
std::memset(out.ai_addr, 0, sizeof(SockAddrIn6Type<T>));
|
||||
|
||||
if ((rc = DNSSerializer::FromBuffer(*reinterpret_cast<SockAddrIn6Type<T> *>(out.ai_addr), cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
out.ai_addr = static_cast<decltype(out.ai_addr)>(ams::socket::impl::Alloc(out.ai_addrlen));
|
||||
if (out.ai_addr == nullptr) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* NOTE: This is *clearly* a nintendo bug. */
|
||||
/* They obviously intend to copy to the buffer they just allocated, but instead they copy to the addrinfo structure itself. */
|
||||
/* Probably &out.ai_addr instead of &out.ai_addr[0]? Either way, we'll implement what they do, but... */
|
||||
std::memcpy(std::addressof(out.ai_addr), cur, out.ai_addrlen);
|
||||
rc = out.ai_addrlen;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
if ((rc = DNSSerializer::FromBuffer(out.ai_canonname, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
{
|
||||
if ((rc = DNSSerializer::FromBuffer(tmp_value, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
} else if (tmp_value == 0) {
|
||||
out.ai_next = nullptr;
|
||||
cur += rc;
|
||||
} else if (tmp_value == AddrInfoMagic) {
|
||||
out.ai_next = static_cast<T *>(ams::socket::impl::Alloc(sizeof(T)));
|
||||
if (out.ai_next == nullptr) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::memset(out.ai_next, 0, sizeof(T));
|
||||
} else {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
rc = cur - src;
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsAddrInfo<T>
|
||||
ssize_t FromBufferImpl(T &out, const u8 *src, size_t src_size) {
|
||||
ssize_t rc = 0;
|
||||
const u8 *cur = src;
|
||||
|
||||
const size_t required = DNSSerializer::SizeOf(out);
|
||||
if (src_size < required) {
|
||||
ams::socket::SetLastError(ams::socket::Errno::ENoSpc);
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (T *addr_info = std::addressof(out); addr_info != nullptr; addr_info = addr_info->ai_next) {
|
||||
if ((rc = FromBufferInternalImpl(*addr_info, cur, src_size - (cur - src))) == -1) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
rc = cur - src;
|
||||
return rc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const struct addrinfo &in) {
|
||||
return SizeOfImpl(in);
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const ams::socket::AddrInfo &in) {
|
||||
return SizeOfImpl(in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const ams::socket::AddrInfo &in) {
|
||||
return ToBufferImpl(dst, dst_size, in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const struct addrinfo &in) {
|
||||
return ToBufferImpl(dst, dst_size, in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(ams::socket::AddrInfo &out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(struct addrinfo &out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
void FreeAddrInfo(ams::socket::AddrInfo &addr_info) {
|
||||
return FreeAddrInfoImpl(addr_info);
|
||||
}
|
||||
|
||||
void FreeAddrInfo(struct addrinfo &addr_info) {
|
||||
return FreeAddrInfoImpl(addr_info);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../dnsmitm_debug.hpp"
|
||||
#include "../socket_allocator.hpp"
|
||||
#include "serializer.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver::serializer {
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T>
|
||||
concept IsHostEnt = std::same_as<T, ams::socket::HostEnt> || std::same_as<T, struct hostent>;
|
||||
|
||||
template<typename T> requires IsHostEnt<T>
|
||||
using InAddrType = typename std::conditional<std::same_as<T, ams::socket::HostEnt>, ams::socket::InAddr, struct in_addr>::type;
|
||||
|
||||
template<typename T> requires IsHostEnt<T>
|
||||
constexpr bool IsAfInet(const auto h_addrtype) {
|
||||
if constexpr (std::same_as<T, ams::socket::HostEnt>) {
|
||||
return h_addrtype == ams::socket::Family::Af_Inet;
|
||||
} else {
|
||||
return h_addrtype == AF_INET;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> requires IsHostEnt<T>
|
||||
constexpr bool IsAfInet6(const auto h_addrtype) {
|
||||
if constexpr (std::same_as<T, ams::socket::HostEnt>) {
|
||||
return h_addrtype == ams::socket::Family::Af_Inet6;
|
||||
} else {
|
||||
return h_addrtype == AF_INET;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> requires IsHostEnt<T>
|
||||
size_t SizeOfImpl(const T &in) {
|
||||
size_t rc = 0;
|
||||
u32 dummy = 0;
|
||||
|
||||
rc += DNSSerializer::SizeOf((const char *)(in.h_name));
|
||||
rc += DNSSerializer::SizeOf((const char **)(in.h_aliases), dummy);
|
||||
rc += sizeof(u32);
|
||||
rc += sizeof(u32);
|
||||
rc += DNSSerializer::SizeOf((const InAddrType<T> **)(in.h_addr_list), dummy);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsHostEnt<T>
|
||||
ssize_t ToBufferImpl(u8 * const dst, size_t dst_size, const T &in) {
|
||||
ssize_t rc = -1;
|
||||
u8 *cur = dst;
|
||||
|
||||
const size_t required = DNSSerializer::SizeOf(in);
|
||||
if ((rc = DNSSerializer::CheckToBufferArguments(cur, dst_size, required, __LINE__)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), in.h_name)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), in.h_aliases)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
const u16 h_addrtype = static_cast<u16>(in.h_addrtype);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), h_addrtype)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
const u16 h_length = in.h_length;
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), h_length)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
if (IsAfInet<T>(in.h_addrtype)) {
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), (InAddrType<T> **)(in.h_addr_list))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
} else if (IsAfInet6<T>(in.h_addrtype)) {
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), (InAddrType<T> **)(in.h_addr_list))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
const u32 null = 0;
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), null)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
rc = cur - dst;
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsHostEnt<T>
|
||||
ssize_t FromBufferImpl(T &out, const u8 *src, size_t src_size) {
|
||||
ssize_t rc = -1;
|
||||
const u8 *cur = src;
|
||||
|
||||
std::memset(std::addressof(out), 0, sizeof(out));
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
if (rc < 0) {
|
||||
FreeHostent(out);
|
||||
}
|
||||
};
|
||||
|
||||
if ((rc = DNSSerializer::FromBuffer(out.h_name, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
if ((rc = DNSSerializer::FromBuffer(out.h_aliases, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
u16 h_addrtype = 0;
|
||||
if ((rc = DNSSerializer::FromBuffer(h_addrtype, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.h_addrtype = static_cast<decltype(out.h_addrtype)>(h_addrtype);
|
||||
cur += rc;
|
||||
|
||||
u16 h_length = 0;
|
||||
if ((rc = DNSSerializer::FromBuffer(h_length, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.h_length = h_length;
|
||||
cur += rc;
|
||||
|
||||
InAddrType<T> **addrs = nullptr;
|
||||
if ((rc = DNSSerializer::FromBuffer(addrs, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.h_addr_list = (char **)addrs;
|
||||
cur += rc;
|
||||
|
||||
rc = cur - src;
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsHostEnt<T>
|
||||
void FreeHostentImpl(T &ent) {
|
||||
if (ent.h_name != nullptr) {
|
||||
ams::socket::impl::Free(ent.h_name);
|
||||
ent.h_name = nullptr;
|
||||
}
|
||||
|
||||
if (ent.h_aliases != nullptr) {
|
||||
u32 i = 0;
|
||||
for (char *str = ent.h_aliases[i]; str != nullptr; str = ent.h_aliases[++i]) {
|
||||
ams::socket::impl::Free(str);
|
||||
ent.h_aliases[i] = nullptr;
|
||||
}
|
||||
|
||||
ams::socket::impl::Free(ent.h_aliases);
|
||||
ent.h_aliases = nullptr;
|
||||
}
|
||||
|
||||
if (ent.h_addr_list != nullptr) {
|
||||
AMS_ASSERT(ent.h_length == sizeof(u32));
|
||||
if (ent.h_length == sizeof(u32)) {
|
||||
auto **addr_list = reinterpret_cast<InAddrType<T> **>(ent.h_addr_list);
|
||||
|
||||
u32 i = 0;
|
||||
for (auto *addr = addr_list[i]; addr != nullptr; addr = addr_list[++i]) {
|
||||
ams::socket::impl::Free(addr);
|
||||
addr_list[i] = nullptr;
|
||||
}
|
||||
|
||||
ams::socket::impl::Free(ent.h_addr_list);
|
||||
ent.h_addr_list = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::memset(std::addressof(ent), 0, sizeof(ent));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const struct hostent &in) {
|
||||
return SizeOfImpl(in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const struct hostent &in) {
|
||||
return ToBufferImpl(dst, dst_size, in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(struct hostent &out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const ams::socket::HostEnt &in) {
|
||||
return SizeOfImpl(in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const ams::socket::HostEnt &in) {
|
||||
return ToBufferImpl(dst, dst_size, in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(ams::socket::HostEnt &out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
void FreeHostent(ams::socket::HostEnt &ent) {
|
||||
return FreeHostentImpl(ent);
|
||||
}
|
||||
|
||||
void FreeHostent(struct hostent &ent) {
|
||||
return FreeHostentImpl(ent);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../dnsmitm_debug.hpp"
|
||||
#include "../socket_allocator.hpp"
|
||||
#include "serializer.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver::serializer {
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T>
|
||||
concept IsInAddr = std::same_as<T, ams::socket::InAddr> || std::same_as<T, struct in_addr>;
|
||||
|
||||
template<typename T> requires IsInAddr<T>
|
||||
size_t SizeOfImpl(const T &) {
|
||||
return sizeof(u32);
|
||||
}
|
||||
|
||||
template<typename T> requires IsInAddr<T>
|
||||
size_t SizeOfImpl(const T **in, u32 &out_count) {
|
||||
size_t rc = sizeof(u32);
|
||||
out_count = 0;
|
||||
|
||||
if (in != nullptr) {
|
||||
for (const T ** cur_addr = in; *cur_addr != nullptr; ++cur_addr) {
|
||||
++out_count;
|
||||
rc += sizeof(u32);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsInAddr<T>
|
||||
ssize_t ToBufferImpl(u8 * const dst, size_t dst_size, const T &in) {
|
||||
ssize_t rc = -1;
|
||||
u8 *cur = dst;
|
||||
|
||||
const u32 val = DNSSerializer::InternalHton(in.s_addr);
|
||||
|
||||
if ((rc = DNSSerializer::CheckToBufferArguments(cur, dst_size, sizeof(in), __LINE__)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::memcpy(cur, std::addressof(val), sizeof(val));
|
||||
rc += sizeof(val);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsInAddr<T>
|
||||
ssize_t FromBufferImpl(T &out, const u8 *src, size_t src_size) {
|
||||
ssize_t rc = -1;
|
||||
if (src_size < sizeof(out)) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::memset(std::addressof(out), 0, sizeof(out));
|
||||
out.s_addr = DNSSerializer::InternalNtoh(*reinterpret_cast<const u32 *>(src));
|
||||
|
||||
rc = sizeof(u32);
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsInAddr<T>
|
||||
ssize_t ToBufferImpl(u8 * const dst, size_t dst_size, T **arr) {
|
||||
ssize_t rc = -1;
|
||||
u8 *cur = dst;
|
||||
|
||||
if (arr == nullptr && dst_size < sizeof(u32)) {
|
||||
return rc;
|
||||
} else if (arr == nullptr) {
|
||||
const u32 null = 0;
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), null)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
} else {
|
||||
u32 count = 0;
|
||||
for (auto *tmp = arr; *tmp != nullptr; ++tmp) {
|
||||
++count;
|
||||
}
|
||||
|
||||
if ((rc = DNSSerializer::CheckToBufferArguments(cur, dst_size, (count + 1) * sizeof(**arr), __LINE__)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), count)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
rc = 0;
|
||||
for (auto i = 0; arr[i] != nullptr; ++i) {
|
||||
const T addr = *arr[i];
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), addr)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
cur += rc;
|
||||
}
|
||||
|
||||
rc = cur - dst;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsInAddr<T>
|
||||
ssize_t FromBufferImpl(T **&out, const u8 *src, size_t src_size) {
|
||||
ssize_t rc = -1;
|
||||
const u8 *cur = src;
|
||||
|
||||
out = nullptr;
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
if (rc == -1 && out != nullptr) {
|
||||
for (auto i = 0; out[i] != nullptr; ++i) {
|
||||
ams::socket::impl::Free(out[i]);
|
||||
out[i] = nullptr;
|
||||
}
|
||||
|
||||
ams::socket::impl::Free(out);
|
||||
out = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
if (src == nullptr) {
|
||||
rc = 0;
|
||||
return rc;
|
||||
} else if (src_size == 0) {
|
||||
rc = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
u32 count = 0;
|
||||
if ((rc = DNSSerializer::FromBuffer(count, cur, src_size)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
if (count == 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
out = static_cast<T **>(ams::socket::impl::Alloc((count + 1) * sizeof(T *)));
|
||||
if (out == nullptr) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
std::memset(out, 0, (count + 1) * sizeof(T *));
|
||||
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
out[i] = static_cast<T *>(ams::socket::impl::Alloc(sizeof(T)));
|
||||
if (out[i] == nullptr) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
u32 s_addr = 0;
|
||||
if ((rc = DNSSerializer::FromBuffer(s_addr, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out[i]->s_addr = s_addr;
|
||||
cur += rc;
|
||||
}
|
||||
out[count] = nullptr;
|
||||
|
||||
rc = cur - src;
|
||||
return rc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const struct in_addr &in) {
|
||||
return SizeOfImpl(in);
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const ams::socket::InAddr &in) {
|
||||
return SizeOfImpl(in);
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const struct in_addr **in, u32 &out_count) {
|
||||
return SizeOfImpl(in, out_count);
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const ams::socket::InAddr **in, u32 &out_count) {
|
||||
return SizeOfImpl(in, out_count);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const struct in_addr &in) {
|
||||
return ToBufferImpl(dst, dst_size, in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const ams::socket::InAddr &in) {
|
||||
return ToBufferImpl(dst, dst_size, in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(struct in_addr &out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(struct ams::socket::InAddr &out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, struct in_addr **arr) {
|
||||
return ToBufferImpl(dst, dst_size, arr);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, ams::socket::InAddr **arr) {
|
||||
return ToBufferImpl(dst, dst_size, arr);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(struct in_addr **&out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(struct ams::socket::InAddr **&out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../dnsmitm_debug.hpp"
|
||||
#include "serializer.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver::serializer {
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const u16 &in) {
|
||||
/* Convert the value. */
|
||||
u8 *cur = dst;
|
||||
const u16 val = InternalHton(in);
|
||||
|
||||
/* Check arguments. */
|
||||
ssize_t rc = -1;
|
||||
if ((rc = CheckToBufferArguments(cur, dst_size, sizeof(u16), __LINE__)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::memcpy(cur, std::addressof(val), sizeof(u16));
|
||||
rc += sizeof(u16);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(u16 &out, const u8 *src, size_t src_size) {
|
||||
if (src_size < sizeof(u16)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
out = InternalNtoh(*reinterpret_cast<const u16 *>(src));
|
||||
return sizeof(u16);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const u32 &in) {
|
||||
/* Convert the value. */
|
||||
u8 *cur = dst;
|
||||
const u32 val = InternalHton(in);
|
||||
|
||||
/* Check arguments. */
|
||||
ssize_t rc = -1;
|
||||
if ((rc = CheckToBufferArguments(cur, dst_size, sizeof(u32), __LINE__)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::memcpy(cur, std::addressof(val), sizeof(u32));
|
||||
rc += sizeof(u32);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(u32 &out, const u8 *src, size_t src_size) {
|
||||
if (src_size < sizeof(u32)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
out = InternalNtoh(*reinterpret_cast<const u32 *>(src));
|
||||
return sizeof(u32);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../dnsmitm_debug.hpp"
|
||||
#include "../socket_allocator.hpp"
|
||||
#include "serializer.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver::serializer {
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T>
|
||||
concept IsSockAddrIn = std::same_as<T, ams::socket::SockAddrIn> || std::same_as<T, struct sockaddr_in>;
|
||||
|
||||
template<typename T> requires IsSockAddrIn<T>
|
||||
size_t SizeOfImpl(const T &in) {
|
||||
size_t rc = 0;
|
||||
rc += sizeof(u16);
|
||||
rc += sizeof(u16);
|
||||
rc += DNSSerializer::SizeOf(in.sin_addr);
|
||||
rc += sizeof(in.sin_zero);
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsSockAddrIn<T>
|
||||
ssize_t ToBufferImpl(u8 * const dst, size_t dst_size, const T &in) {
|
||||
ssize_t rc = -1;
|
||||
u8 *cur = dst;
|
||||
|
||||
if ((rc = DNSSerializer::CheckToBufferArguments(cur, dst_size, sizeof(in), __LINE__)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
const u16 sin_family = static_cast<u16>(in.sin_family);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), sin_family)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
const u16 sin_port = static_cast<u16>(in.sin_port);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), sin_port)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
const u32 s_addr = static_cast<u32>(in.sin_addr.s_addr);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), s_addr)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
if (dst_size - (cur - dst) < sizeof(in.sin_zero)) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::memcpy(cur, in.sin_zero, sizeof(in.sin_zero));
|
||||
cur += sizeof(in.sin_zero);
|
||||
|
||||
rc = cur - dst;
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsSockAddrIn<T>
|
||||
ssize_t FromBufferImpl(T &out, const u8 *src, size_t src_size) {
|
||||
ssize_t rc = -1;
|
||||
const u8 *cur = src;
|
||||
|
||||
u16 sin_family;
|
||||
if ((rc = DNSSerializer::FromBuffer(sin_family, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.sin_family = static_cast<decltype(out.sin_family)>(sin_family);
|
||||
cur += rc;
|
||||
|
||||
u16 sin_port;
|
||||
if ((rc = DNSSerializer::FromBuffer(sin_port, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.sin_port = static_cast<decltype(out.sin_port)>(sin_port);
|
||||
cur += rc;
|
||||
|
||||
u32 s_addr;
|
||||
if ((rc = DNSSerializer::FromBuffer(s_addr, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.sin_addr.s_addr = static_cast<decltype(out.sin_addr.s_addr)>(s_addr);
|
||||
cur += rc;
|
||||
|
||||
if (src_size - (cur - src) < sizeof(out.sin_zero)) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::memcpy(out.sin_zero, cur, sizeof(out.sin_zero));
|
||||
cur += sizeof(out.sin_zero);
|
||||
|
||||
rc = cur - src;
|
||||
return rc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const struct sockaddr_in &in) {
|
||||
return SizeOfImpl(in);
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const ams::socket::SockAddrIn &in) {
|
||||
return SizeOfImpl(in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const struct sockaddr_in &in) {
|
||||
return ToBufferImpl(dst, dst_size, in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const ams::socket::SockAddrIn &in) {
|
||||
return ToBufferImpl(dst, dst_size, in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(struct sockaddr_in &out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(struct ams::socket::SockAddrIn &out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../dnsmitm_debug.hpp"
|
||||
#include "../socket_allocator.hpp"
|
||||
#include "serializer.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver::serializer {
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T>
|
||||
concept IsSockAddrIn6 = std::same_as<T, struct sockaddr_in6>;
|
||||
|
||||
template<typename T> requires IsSockAddrIn6<T>
|
||||
size_t SizeOfImpl(const T &in) {
|
||||
size_t rc = 0;
|
||||
rc += sizeof(u16);
|
||||
rc += sizeof(u16);
|
||||
rc += sizeof(u32);
|
||||
rc += DNSSerializer::SizeOf(in.sin6_addr);
|
||||
rc += sizeof(u32);
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsSockAddrIn6<T>
|
||||
ssize_t ToBufferImpl(u8 * const dst, size_t dst_size, const T &in) {
|
||||
ssize_t rc = -1;
|
||||
u8 *cur = dst;
|
||||
|
||||
if ((rc = DNSSerializer::CheckToBufferArguments(cur, dst_size, sizeof(in), __LINE__)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
const u16 sin6_family = static_cast<u16>(in.sin6_family);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), sin6_family)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
const u16 sin6_port = static_cast<u16>(in.sin6_port);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), sin6_port)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
const u32 sin6_flowinfo = static_cast<u32>(in.sin6_flowinfo);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), sin6_flowinfo)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
std::memcpy(cur, std::addressof(in.sin6_addr), sizeof(in.sin6_addr));
|
||||
cur += sizeof(in.sin6_addr);
|
||||
|
||||
const u32 sin6_scope_id = static_cast<u32>(in.sin6_scope_id);
|
||||
if ((rc = DNSSerializer::ToBuffer(cur, dst_size - (cur - dst), sin6_scope_id)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
rc = cur - dst;
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<typename T> requires IsSockAddrIn6<T>
|
||||
ssize_t FromBufferImpl(T &out, const u8 *src, size_t src_size) {
|
||||
ssize_t rc = -1;
|
||||
const u8 *cur = src;
|
||||
|
||||
u16 sin6_family;
|
||||
if ((rc = DNSSerializer::FromBuffer(sin6_family, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.sin6_family = static_cast<decltype(out.sin6_family)>(sin6_family);
|
||||
cur += rc;
|
||||
|
||||
u16 sin6_port;
|
||||
if ((rc = DNSSerializer::FromBuffer(sin6_port, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.sin6_port = static_cast<decltype(out.sin6_port)>(sin6_port);
|
||||
cur += rc;
|
||||
|
||||
u32 sin6_flowinfo;
|
||||
if ((rc = DNSSerializer::FromBuffer(sin6_flowinfo, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.sin6_flowinfo = static_cast<decltype(out.sin6_flowinfo)>(sin6_flowinfo);
|
||||
cur += rc;
|
||||
|
||||
std::memcpy(std::addressof(out.sin6_addr), cur, sizeof(out.sin6_addr));
|
||||
cur += sizeof(out.sin6_addr);
|
||||
|
||||
u32 sin6_scope_id;
|
||||
if ((rc = DNSSerializer::FromBuffer(sin6_scope_id, cur, src_size - (cur - src))) == -1) {
|
||||
return rc;
|
||||
}
|
||||
out.sin6_scope_id = static_cast<decltype(out.sin6_scope_id)>(sin6_scope_id);
|
||||
cur += rc;
|
||||
|
||||
rc = cur - src;
|
||||
return rc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const struct sockaddr_in6 &in) {
|
||||
return SizeOfImpl(in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, const struct sockaddr_in6 &in) {
|
||||
return ToBufferImpl(dst, dst_size, in);
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(struct sockaddr_in6 &out, const u8 *src, size_t src_size) {
|
||||
return FromBufferImpl(out, src, src_size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "../dnsmitm_debug.hpp"
|
||||
#include "../socket_allocator.hpp"
|
||||
#include "serializer.hpp"
|
||||
|
||||
namespace ams::mitm::socket::resolver::serializer {
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const char *str) {
|
||||
if (str == nullptr) {
|
||||
return sizeof(char);
|
||||
}
|
||||
return std::strlen(str) + 1;
|
||||
}
|
||||
|
||||
template<> size_t DNSSerializer::SizeOf(const char **str, u32 &out_count) {
|
||||
size_t rc = sizeof(u32);
|
||||
out_count = 0;
|
||||
|
||||
if (str != nullptr) {
|
||||
for (const char **cur = str; *cur != nullptr; ++cur) {
|
||||
++out_count;
|
||||
rc += SizeOf(*cur);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, char *str) {
|
||||
ssize_t rc = -1;
|
||||
u8 *cur = dst;
|
||||
|
||||
if (str == nullptr && dst_size == 0) {
|
||||
return -1;
|
||||
} else if (str == nullptr) {
|
||||
*cur = '\x00';
|
||||
return 1;
|
||||
} else if ((rc = SizeOf(static_cast<const char *>(str))) == 0) {
|
||||
*cur = '\x00';
|
||||
return 1;
|
||||
} else if (CheckToBufferArguments(cur, dst_size, rc + 1, __LINE__) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::memmove(cur, str, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(char *&out, const u8 *src, size_t src_size) {
|
||||
size_t len = 0;
|
||||
|
||||
if (src == nullptr) {
|
||||
return 0;
|
||||
} else if (src_size == 0) {
|
||||
return 0;
|
||||
} else if (src_size < (len = SizeOf(reinterpret_cast<const char *>(src)))) {
|
||||
return 1;
|
||||
} else if (src[0] == '\x00') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
out = static_cast<char *>(ams::socket::impl::Alloc(len));
|
||||
if (out == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::memmove(out, src, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::ToBuffer(u8 * const dst, size_t dst_size, char **str) {
|
||||
ssize_t rc = -1;
|
||||
u8 *cur = dst;
|
||||
u32 count = 0;
|
||||
|
||||
if (dst_size == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t total_size = SizeOf(const_cast<const char **>(str), count);
|
||||
AMS_UNUSED(total_size);
|
||||
|
||||
if ((rc = CheckToBufferArguments(cur, dst_size, sizeof(u32), __LINE__)) == -1) {
|
||||
return rc;
|
||||
} else if ((rc = ToBuffer(cur, dst_size, count)) == -1) {
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
dst_size -= rc;
|
||||
|
||||
if (str != nullptr) {
|
||||
for (char **cur_str = str; *cur_str != nullptr; ++cur_str) {
|
||||
const auto tmp = ToBuffer(cur, dst_size, *cur_str);
|
||||
if (tmp == -1) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
cur += tmp;
|
||||
dst_size -= tmp;
|
||||
rc += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
rc = cur - dst;
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<> ssize_t DNSSerializer::FromBuffer(char **&out, const u8 *src, size_t src_size) {
|
||||
ssize_t rc = -1;
|
||||
const u8 *cur = src;
|
||||
u32 count = 0;
|
||||
|
||||
out = nullptr;
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
if (rc < 0 && out != nullptr) {
|
||||
u32 i = 0;
|
||||
for (char *str = *out; str != nullptr; str = out[++i]) {
|
||||
ams::socket::impl::Free(str);
|
||||
}
|
||||
ams::socket::impl::Free(out);
|
||||
out = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
if (src == nullptr) {
|
||||
rc = 0;
|
||||
return rc;
|
||||
} else if (src_size == 0) {
|
||||
rc = 0;
|
||||
return rc;
|
||||
} else if ((rc = FromBuffer(count, cur, src_size)) == -1) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
cur += rc;
|
||||
|
||||
out = static_cast<char **>(ams::socket::impl::Alloc((count + 1) * sizeof(char *)));
|
||||
if (out == nullptr) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
std::memset(out, 0, (count + 1) * sizeof(char *));
|
||||
|
||||
u32 i;
|
||||
for (i = 0; i < count; ++i) {
|
||||
const size_t len = std::strlen(reinterpret_cast<const char *>(cur));
|
||||
out[i] = static_cast<char *>(ams::socket::impl::Alloc(len + 1));
|
||||
if (out[i] == nullptr) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::memmove(out[i], cur, len + 1);
|
||||
cur += len + 1;
|
||||
}
|
||||
|
||||
out[i] = nullptr;
|
||||
rc = cur - src;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "sfdnsres_shim.h"
|
||||
#include <stratosphere/sf/sf_mitm_dispatch.h>
|
||||
|
||||
/* Command forwarders. */
|
||||
Result sfdnsresGetHostByNameRequestWithOptionsFwd(Service *s, u64 process_id, const void *name, size_t name_size, void *out_hostent, size_t out_hostent_size, u32 *out_size, u32 options_version, const void *option, size_t option_size, u32 num_options, s32 *out_host_error, s32 *out_errno) {
|
||||
const struct {
|
||||
u32 options_version;
|
||||
u32 num_options;
|
||||
u64 process_id;
|
||||
} in = { options_version, num_options, process_id };
|
||||
struct {
|
||||
u32 size;
|
||||
s32 host_error;
|
||||
s32 errno;
|
||||
} out;
|
||||
|
||||
Result rc = serviceMitmDispatchInOut(s, 10, in, out,
|
||||
.buffer_attrs = {
|
||||
SfBufferAttr_HipcAutoSelect | SfBufferAttr_In,
|
||||
SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out,
|
||||
SfBufferAttr_HipcAutoSelect | SfBufferAttr_In
|
||||
},
|
||||
.buffers = {
|
||||
{ name, name_size },
|
||||
{ out_hostent, out_hostent_size },
|
||||
{ option, option_size }
|
||||
},
|
||||
.in_send_pid = true,
|
||||
.override_pid = process_id,
|
||||
);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (out_size) *out_size = out.size;
|
||||
if (out_host_error) *out_host_error = out.host_error;
|
||||
if (out_errno) *out_errno = out.errno;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result sfdnsresGetAddrInfoRequestWithOptionsFwd(Service *s, u64 process_id, const void *node, size_t node_size, const void *srv, size_t srv_size, const void *hint, size_t hint_size, void *out_ai, size_t out_ai_size, u32 *out_size, s32 *out_rv, u32 options_version, const void *option, size_t option_size, u32 num_options, s32 *out_host_error, s32 *out_errno) {
|
||||
const struct {
|
||||
u32 options_version;
|
||||
u32 num_options;
|
||||
u64 process_id;
|
||||
} in = { options_version, num_options, process_id };
|
||||
struct {
|
||||
u32 size;
|
||||
s32 rv;
|
||||
s32 host_error;
|
||||
s32 errno;
|
||||
} out;
|
||||
|
||||
Result rc = serviceMitmDispatchInOut(s, 12, in, out,
|
||||
.buffer_attrs = {
|
||||
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
|
||||
SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out,
|
||||
SfBufferAttr_HipcAutoSelect | SfBufferAttr_In
|
||||
},
|
||||
.buffers = {
|
||||
{ node, node_size },
|
||||
{ srv, srv_size },
|
||||
{ hint, hint_size },
|
||||
{ out_ai, out_ai_size },
|
||||
{ option, option_size }
|
||||
},
|
||||
.in_send_pid = true,
|
||||
.override_pid = process_id,
|
||||
);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (out_size) *out_size = out.size;
|
||||
if (out_rv) *out_rv = out.rv;
|
||||
if (out_host_error) *out_host_error = out.host_error;
|
||||
if (out_errno) *out_errno = out.errno;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @file sfdnsres_shim.h
|
||||
* @brief IPC wrapper for dns.mitm.
|
||||
* @author SciresM
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Command forwarders. */
|
||||
Result sfdnsresGetHostByNameRequestWithOptionsFwd(Service *s, u64 process_id, const void *name, size_t name_size, void *out_hostent, size_t out_hostent_size, u32 *out_size, u32 options_version, const void *option, size_t option_size, u32 num_options, s32 *out_host_error, s32 *out_errno);
|
||||
|
||||
Result sfdnsresGetAddrInfoRequestWithOptionsFwd(Service *s, u64 process_id, const void *node, size_t node_size, const void *srv, size_t srv_size, const void *hint, size_t hint_size, void *out_ai, size_t out_ai_size, u32 *out_size, s32 *out_rv, u32 options_version, const void *option, size_t option_size, u32 num_options, s32 *out_host_error, s32 *out_errno);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::socket::impl {
|
||||
|
||||
void *Alloc(size_t size);
|
||||
void *Calloc(size_t num, size_t size);
|
||||
void Free(void *ptr);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user