Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ public object Convert(object value, Type targetType, object parameter, CultureIn
{
return value is not GroupViewName name
? "-/-"
: ResourceTranslator.Translate(ResourceIdentifier.ProfileGroup, name);
: ResourceTranslator.Translate(new[] { ResourceIdentifier.ProfileGroup, ResourceIdentifier.ApplicationName },
name);
}

/// <summary>
Expand Down
33 changes: 30 additions & 3 deletions Source/NETworkManager.Localization/Resources/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions Source/NETworkManager.Localization/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -5123,13 +5123,13 @@ Do you want to start the scan?</value>
<value>The name must not contain ";" and must not be a port or port range.</value>
</data>
<data name="PortProfileOfProfileNotFoundMessage" xml:space="preserve">
<value>A port profile of this profile was not found, the ports saved with the profile are used. Port profiles are saved in the settings and the profile refers to them by an internal ID - if the profile file was shared from another computer, create the port profile and then select it in the profile again (edit the profile).</value>
<value>A port profile of this profile or its group was not found, the ports saved with the profile or group are used. Port profiles are saved in the settings and the profile or group refers to them by an internal ID - if the profile file was shared from another computer, create the port profile and then select it in the profile or group again (edit it).</value>
</data>
<data name="PingHostsBeforeScan" xml:space="preserve">
<value>Ping hosts before the scan</value>
</data>
<data name="HelpMessage_PingHostsBeforeScan" xml:space="preserve">
<value>Only hosts that answer a ping (ICMP echo, with the timeout and attempts above) are scanned. Faster for ranges with many unused IP addresses. Hosts that block ICMP (e.g. Windows with the firewall enabled) are not scanned.</value>
<value>Only hosts that answer a ping (ICMP echo, with the attempts, timeout and buffer below) are scanned. Faster for ranges with many unused IP addresses. Hosts that block ICMP (e.g. Windows with the firewall enabled) are not scanned.</value>
</data>
<data name="XHostsDidNotAnswerThePingAndWereNotScanned" xml:space="preserve">
<value>{0} host(s) did not answer the ping and were not scanned.</value>
Expand All @@ -5141,6 +5141,15 @@ Do you want to start the scan?</value>
<value>The name must not contain ";".</value>
</data>
<data name="DNSServerOfProfileNotFoundMessage" xml:space="preserve">
<value>A DNS server of this profile was not found, the DNS servers saved with the profile are used. DNS servers are saved in the settings and the profile refers to them by an internal ID - if the profile file was shared from another computer, create the DNS server and then select it in the profile again (edit the profile).</value>
<value>A DNS server of this profile or its group was not found, the DNS servers saved with the profile or group are used. DNS servers are saved in the settings and the profile or group refers to them by an internal ID - if the profile file was shared from another computer, create the DNS server and then select it in the profile or group again (edit it).</value>
</data>
<data name="ApplicationName_Firewall" xml:space="preserve">
<value>Firewall</value>
</data>
<data name="PTRRequiresIPAddressX" xml:space="preserve">
<value>PTR records can only be looked up for IP addresses, "{0}" is skipped.</value>
</data>
<data name="ErrorMessage_PTRRequiresIPAddresses" xml:space="preserve">
<value>PTR records can only be looked up for IP addresses.</value>
</data>
</root>
42 changes: 42 additions & 0 deletions Source/NETworkManager.Models/Network/DNSServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,48 @@ public static bool TryDecodeReferences(string inputWithReferences,
return NamedReferenceInput.TryDecodeReferences(inputWithReferences, profiles, out input);
}

/// <summary>
/// Converts a DNS server input (e.g. of a profile or group) to the values that are saved: the servers (DNS
/// server profiles replaced by their servers, see <see cref="ReplaceProfilesByServers" />, used if a DNS server
/// profile can't be found later, e.g. a profile file from another computer) and the input with references (see
/// <see cref="EncodeReferences" />).
/// </summary>
/// <param name="input">DNS server input.</param>
/// <param name="profiles">DNS server profiles.</param>
/// <returns>Servers and DNS server input with references (null if it contains no DNS server profile).</returns>
public static (string DNSServer, string DNSServerInput) Encode(string input,
IEnumerable<DNSServerConnectionInfoProfile> profiles)
{
var profileList = profiles.ToList();

return (ReplaceProfilesByServers(input?.Trim(), profileList), EncodeReferences(input, profileList));
}

/// <summary>
/// Converts the saved values (see <see cref="Encode" />) back to the DNS server input: the DNS server profiles
/// with their current name (also after a rename), or the saved servers if a DNS server profile can't be found.
/// </summary>
/// <param name="dnsServer">Saved servers.</param>
/// <param name="dnsServerInput">Saved DNS server input with references.</param>
/// <param name="profiles">DNS server profiles.</param>
/// <param name="dnsServerNotFound">True if a DNS server profile can't be found.</param>
/// <returns>DNS server input.</returns>
public static string Decode(string dnsServer, string dnsServerInput,
IEnumerable<DNSServerConnectionInfoProfile> profiles, out bool dnsServerNotFound)
{
dnsServerNotFound = false;

if (string.IsNullOrEmpty(dnsServerInput))
return dnsServer;

if (TryDecodeReferences(dnsServerInput, profiles, out var input))
return input;

dnsServerNotFound = true;

return dnsServer;
}

/// <summary>
/// Replaces the names of DNS server profiles in a DNS server input by their servers (e.g. "Cloudflare; 9.9.9.9"
/// -> "1.1.1.1:53; 1.0.0.1:53; 9.9.9.9"), so the input still works without the DNS server profiles (e.g. on another
Expand Down
41 changes: 41 additions & 0 deletions Source/NETworkManager.Models/Network/PortProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,47 @@ public static bool TryDecodeReferences(string inputWithReferences, IEnumerable<P
return NamedReferenceInput.TryDecodeReferences(inputWithReferences, portProfiles, out input);
}

/// <summary>
/// Converts a ports input (e.g. of a profile or group) to the values that are saved: the ports (port profiles
/// replaced by their ports, used if a port profile can't be found later, e.g. a profile file from another
/// computer) and the input with references to the port profiles (see <see cref="EncodeReferences" />).
/// </summary>
/// <param name="input">Ports input.</param>
/// <param name="portProfiles">Port profiles.</param>
/// <returns>Ports and ports input with references (null if it contains no port profile).</returns>
public static (string Ports, string PortsInput) Encode(string input, IEnumerable<PortProfileInfo> portProfiles)
{
var portProfileList = portProfiles.ToList();

return (TryResolvePorts(input, portProfileList, out var ports) ? ports : input?.Trim(),
EncodeReferences(input, portProfileList));
}

/// <summary>
/// Converts the saved values (see <see cref="Encode" />) back to the ports input: the port profiles with their
/// current name (also after a rename), or the saved ports if a port profile can't be found.
/// </summary>
/// <param name="ports">Saved ports.</param>
/// <param name="portsInput">Saved ports input with references.</param>
/// <param name="portProfiles">Port profiles.</param>
/// <param name="portProfileNotFound">True if a port profile can't be found.</param>
/// <returns>Ports input.</returns>
public static string Decode(string ports, string portsInput, IEnumerable<PortProfileInfo> portProfiles,
out bool portProfileNotFound)
{
portProfileNotFound = false;

if (string.IsNullOrEmpty(portsInput))
return ports;

if (TryDecodeReferences(portsInput, portProfiles, out var input))
return input;

portProfileNotFound = true;

return ports;
}

public static List<PortProfileInfo> GetDefaultList()
{
return new List<PortProfileInfo>
Expand Down
10 changes: 2 additions & 8 deletions Source/NETworkManager.Models/Network/PortScanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,6 @@ public PortScanner(PortScannerOptions options)
private readonly InterlockedCounter _portsTimedOut = new();
private readonly InterlockedCounter _hostsSkipped = new();

/// <summary>
/// Data of the ping before the scan (see <see cref="PortScannerOptions.PingHostsBeforeScan" />), like the
/// default buffer of the IP Scanner.
/// </summary>
private static readonly byte[] PingBuffer = new byte[32];

// Closed and timed out ports per host, see GetClosedAndTimedOutPortsPerHost
private readonly ConcurrentDictionary<IPAddress, (InterlockedCounter closed, InterlockedCounter timedOut)>
_portsPerHost = new();
Expand Down Expand Up @@ -399,8 +393,8 @@ await Parallel.ForEachAsync(hosts, pingParallelOptions, async (host, ct) =>
/// <returns>True if the host answered the ping.</returns>
private async Task<bool> IsReachableAsync(IPAddress ipAddress, int portCount, CancellationToken cancellationToken)
{
var pingInfo = await PingProbe.PingAsync(ipAddress, _options.Timeout, _options.Attempts, PingBuffer,
cancellationToken).ConfigureAwait(false);
var pingInfo = await PingProbe.PingAsync(ipAddress, _options.ICMPTimeout, _options.ICMPAttempts,
_options.ICMPBuffer, cancellationToken).ConfigureAwait(false);

if (pingInfo.Status == IPStatus.Success)
return true;
Expand Down
20 changes: 18 additions & 2 deletions Source/NETworkManager.Models/Network/PortScannerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,27 @@ public record PortScannerOptions
public required int Attempts { get; init; }

/// <summary>
/// Ping every host before its ports are scanned (with <see cref="Timeout" /> and <see cref="Attempts" />), a host
/// that doesn't answer is not scanned.
/// Ping every host before its ports are scanned (with <see cref="ICMPAttempts" />, <see cref="ICMPTimeout" /> and
/// <see cref="ICMPBuffer" />), a host that doesn't answer is not scanned.
/// </summary>
public required bool PingHostsBeforeScan { get; init; }

/// <summary>
/// Number of pings before the scan if there was no answer (see <see cref="PingHostsBeforeScan" />).
/// </summary>
public required int ICMPAttempts { get; init; }

/// <summary>
/// Timeout in milliseconds after which a ping before the scan is considered lost (see
/// <see cref="PingHostsBeforeScan" />).
/// </summary>
public required int ICMPTimeout { get; init; }

/// <summary>
/// Data sent with the ping before the scan (see <see cref="PingHostsBeforeScan" />).
/// </summary>
public required byte[] ICMPBuffer { get; init; }

/// <summary>
/// Resolve the hostname for an IP address.
/// </summary>
Expand Down
56 changes: 56 additions & 0 deletions Source/NETworkManager.Profiles/Application/DNSLookup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using DnsClient;
using NETworkManager.Models.Network;
using NETworkManager.Settings;
using NETworkManager.Utilities;

namespace NETworkManager.Profiles.Application;

public static class DNSLookup
{
/// <summary>
/// Gets the DNS servers for a profile: its own DNS servers (if overridden), otherwise the DNS servers of its
/// group (if overridden), otherwise none (the DNS server selected in the DNS Lookup is used). DNS servers by name
/// with their current name (also after a rename); if a DNS server can't be found (deleted, or a profile file
/// shared from another computer - DNS servers are saved in the settings), the servers saved with the profile or
/// group.
/// </summary>
/// <param name="profile">Profile to get the DNS servers for.</param>
/// <param name="dnsServerNotFound">True if a DNS server can't be found.</param>
/// <returns>DNS servers, null if neither the profile nor its group has DNS servers.</returns>
public static string GetDNSServer(ProfileInfo profile, out bool dnsServerNotFound)
{
// Get group info
var group = ProfileManager.GetGroupByName(profile.Group);

var (dnsServer, dnsServerInput) = profile.DNSLookup_OverrideDNSServer
? (profile.DNSLookup_DNSServer, profile.DNSLookup_DNSServerInput)
: group.DNSLookup_OverrideDNSServer
? (group.DNSLookup_DNSServer, group.DNSLookup_DNSServerInput)
: (null, null);

if (string.IsNullOrWhiteSpace(dnsServer))
{
dnsServerNotFound = false;

return null;
}

return DNSServer.Decode(dnsServer, dnsServerInput, SettingsManager.Current.DNSLookup_DNSServers,
out dnsServerNotFound);
}

/// <summary>
/// Gets the query type for a profile: its own type (if overridden), otherwise PTR for IP addresses and A for
/// hostnames.
/// </summary>
/// <param name="profile">Profile to get the query type for.</param>
/// <returns>Query type.</returns>
public static QueryType GetQueryType(ProfileInfo profile)
{
return profile.DNSLookup_OverrideQueryType
? profile.DNSLookup_QueryType
: IPAddressHelper.AreIPAddresses(profile.DNSLookup_Host)
? QueryType.PTR
: QueryType.A;
}
}
31 changes: 31 additions & 0 deletions Source/NETworkManager.Profiles/Application/PortScanner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using NETworkManager.Models.Network;
using NETworkManager.Settings;

namespace NETworkManager.Profiles.Application;

public static class PortScanner
{
/// <summary>
/// Gets the ports to scan for a profile: its own ports (if overridden), otherwise the ports of its group (if
/// overridden), otherwise none. Port profiles with their current name (also after a rename); if a port profile
/// can't be found (deleted, or a profile file shared from another computer - port profiles are saved in the
/// settings), the ports saved with the profile or group.
/// </summary>
/// <param name="profile">Profile to get the ports for.</param>
/// <param name="portProfileNotFound">True if a port profile can't be found.</param>
/// <returns>Ports to scan, empty if neither the profile nor its group has ports.</returns>
public static string GetPorts(ProfileInfo profile, out bool portProfileNotFound)
{
// Get group info
var group = ProfileManager.GetGroupByName(profile.Group);

var (ports, portsInput) = profile.PortScanner_OverridePorts
? (profile.PortScanner_Ports, profile.PortScanner_PortsInput)
: group.PortScanner_OverridePorts
? (group.PortScanner_Ports, group.PortScanner_PortsInput)
: (string.Empty, null);

return PortProfile.Decode(ports, portsInput, SettingsManager.Current.PortScanner_PortProfiles,
out portProfileNotFound);
}
}
Loading
Loading