diff options
author | TSRBerry <20988865+TSRBerry@users.noreply.github.com> | 2022-12-12 18:04:08 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-12 18:04:08 +0100 |
commit | df758eddd1d61f776415422dc4dd1fa8a776719c (patch) | |
tree | 1959798b68d5f6660d51b1ea8d1a891a486736f3 | |
parent | 5f32a8ed946d5a4f40b5d10cfcb82529143310be (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.cs | 19 | ||||
-rw-r--r-- | Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/Proxy/DnsMitmResolver.cs | 106 |
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 |