aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTSRBerry <20988865+TSRBerry@users.noreply.github.com>2022-12-12 18:04:08 +0100
committerGitHub <noreply@github.com>2022-12-12 18:04:08 +0100
commitdf758eddd1d61f776415422dc4dd1fa8a776719c (patch)
tree1959798b68d5f6660d51b1ea8d1a891a486736f3
parent5f32a8ed946d5a4f40b5d10cfcb82529143310be (diff)
Bsd: Add support for dns_mitm (#4102)1.1.468
* bsd: Add dns_mitm from Atmosphère related AMS files: - https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_resolver_impl.cpp - https://github.com/Atmosphere-NX/Atmosphere/blob/master/stratosphere/ams_mitm/source/dns_mitm/dnsmitm_host_redirection.cpp * Remove debug logging and adjust redirect message * Improve formatting Co-authored-by: Ac_K <Acoustik666@gmail.com> * Replace Initialize with instance property * bsd: dns_mitm - Ignore empty lines * bsd: Mark _mitmHostEntries as readonly * bsd: Initialize Aliases when returning IpHostEntry Fixes NullReferenceException Co-authored-by: Ac_K <Acoustik666@gmail.com>
-rw-r--r--Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs19
-rw-r--r--Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/Proxy/DnsMitmResolver.cs106
2 files changed, 122 insertions, 3 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs b/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs
index 80339b4a..13c5597f 100644
--- a/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs
+++ b/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs
@@ -18,7 +18,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres
[Service("sfdnsres")]
class IResolver : IpcService
{
- public IResolver(ServiceCtx context) { }
+ public IResolver(ServiceCtx context)
+ {
+ DnsMitmResolver.Instance.ReloadEntries(context);
+ }
[CommandHipc(0)]
// SetDnsAddressesPrivateRequest(u32, buffer<unknown, 5, 0>)
@@ -259,6 +262,16 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres
return ResultCode.Success;
}
+ // Atmosphère extension for dns_mitm
+ [CommandHipc(65000)]
+ // AtmosphereReloadHostsFile()
+ public ResultCode AtmosphereReloadHostsFile(ServiceCtx context)
+ {
+ DnsMitmResolver.Instance.ReloadEntries(context);
+
+ return ResultCode.Success;
+ }
+
private static ResultCode GetHostByNameRequestImpl(
ServiceCtx context,
ulong inputBufferPosition,
@@ -321,7 +334,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres
try
{
- hostEntry = Dns.GetHostEntry(targetHost);
+ hostEntry = DnsMitmResolver.Instance.ResolveAddress(targetHost);
}
catch (SocketException exception)
{
@@ -537,7 +550,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres
try
{
- hostEntry = Dns.GetHostEntry(targetHost);
+ hostEntry = DnsMitmResolver.Instance.ResolveAddress(targetHost);
}
catch (SocketException exception)
{
diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/Proxy/DnsMitmResolver.cs b/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/Proxy/DnsMitmResolver.cs
new file mode 100644
index 00000000..8eece5ea
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/Proxy/DnsMitmResolver.cs
@@ -0,0 +1,106 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Services.Sockets.Nsd;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Enumeration;
+using System.Net;
+
+namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Proxy
+{
+ class DnsMitmResolver
+ {
+ private const string HostsFilePath = "/atmosphere/hosts/default.txt";
+
+ private static DnsMitmResolver _instance;
+ public static DnsMitmResolver Instance => _instance ??= new DnsMitmResolver();
+
+ private readonly Dictionary<string, IPAddress> _mitmHostEntries = new();
+
+ public void ReloadEntries(ServiceCtx context)
+ {
+ string sdPath = context.Device.Configuration.VirtualFileSystem.GetSdCardPath();
+ string filePath = context.Device.Configuration.VirtualFileSystem.GetFullPath(sdPath, HostsFilePath);
+
+ _mitmHostEntries.Clear();
+
+ if (File.Exists(filePath))
+ {
+ using FileStream fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read);
+ using StreamReader reader = new(fileStream);
+
+ while (!reader.EndOfStream)
+ {
+ string line = reader.ReadLine();
+
+ if (line == null)
+ {
+ break;
+ }
+
+ // Ignore comments and empty lines
+ if (line.StartsWith("#") || line.Trim().Length == 0)
+ {
+ continue;
+ }
+
+ string[] entry = line.Split(new[] { ' ', '\t' }, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
+
+ // Hosts file example entry:
+ // 127.0.0.1 localhost loopback
+
+ // 0. Check the size of the array
+ if (entry.Length < 2)
+ {
+ Logger.Warning?.PrintMsg(LogClass.ServiceBsd, $"Invalid entry in hosts file: {line}");
+
+ continue;
+ }
+
+ // 1. Parse the address
+ if (!IPAddress.TryParse(entry[0], out IPAddress address))
+ {
+ Logger.Warning?.PrintMsg(LogClass.ServiceBsd, $"Failed to parse IP address in hosts file: {entry[0]}");
+
+ continue;
+ }
+
+ // 2. Check for AMS hosts file extension: "%"
+ for (int i = 1; i < entry.Length; i++)
+ {
+ entry[i] = entry[i].Replace("%", IManager.NsdSettings.Environment);
+ }
+
+ // 3. Add hostname to entry dictionary (updating duplicate entries)
+ foreach (string hostname in entry[1..])
+ {
+ _mitmHostEntries[hostname] = address;
+ }
+ }
+ }
+ }
+
+ public IPHostEntry ResolveAddress(string host)
+ {
+ foreach (var hostEntry in _mitmHostEntries)
+ {
+ // Check for AMS hosts file extension: "*"
+ // NOTE: MatchesSimpleExpression also allows "?" as a wildcard
+ if (FileSystemName.MatchesSimpleExpression(hostEntry.Key, host))
+ {
+ Logger.Info?.PrintMsg(LogClass.ServiceBsd, $"Redirecting '{host}' to: {hostEntry.Value}");
+
+ return new IPHostEntry
+ {
+ AddressList = new[] { hostEntry.Value },
+ HostName = hostEntry.Key,
+ Aliases = Array.Empty<string>()
+ };
+ }
+ }
+
+ // No match has been found, resolve the host using regular dns
+ return Dns.GetHostEntry(host);
+ }
+ }
+} \ No newline at end of file