diff options
Diffstat (limited to 'MediaBrowser.Common/Net')
| -rw-r--r-- | MediaBrowser.Common/Net/NetworkUtils.cs | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/MediaBrowser.Common/Net/NetworkUtils.cs b/MediaBrowser.Common/Net/NetworkUtils.cs index 5c854b39d5..25a1022d4e 100644 --- a/MediaBrowser.Common/Net/NetworkUtils.cs +++ b/MediaBrowser.Common/Net/NetworkUtils.cs @@ -7,6 +7,7 @@ using System.Net.Sockets; using System.Text.RegularExpressions; using Jellyfin.Extensions; using MediaBrowser.Model.Net; +using Microsoft.Extensions.Logging; namespace MediaBrowser.Common.Net; @@ -166,8 +167,9 @@ public static partial class NetworkUtils /// <param name="values">Input string array to be parsed.</param> /// <param name="result">Collection of <see cref="IPNetwork"/>.</param> /// <param name="negated">Boolean signaling if negated or not negated values should be parsed.</param> + /// <param name="logger">Optional logger used to warn about entries that fail to parse.</param> /// <returns><c>True</c> if parsing was successful.</returns> - public static bool TryParseToSubnets(string[] values, [NotNullWhen(true)] out IReadOnlyList<IPData>? result, bool negated = false) + public static bool TryParseToSubnets(string[] values, [NotNullWhen(true)] out IReadOnlyList<IPData>? result, bool negated = false, ILogger? logger = null) { if (values is null || values.Length == 0) { @@ -178,9 +180,20 @@ public static partial class NetworkUtils List<IPData>? tmpResult = null; for (int a = 0; a < values.Length; a++) { + // Skip entries whose '!' polarity doesn't match this pass + var trimmed = values[a].AsSpan().Trim(); + if (trimmed.StartsWith('!') != negated) + { + continue; + } + if (TryParseToSubnet(values[a], out var innerResult, negated)) { - (tmpResult ??= new()).Add(innerResult); + (tmpResult ??= []).Add(innerResult); + } + else + { + LogInvalidSubnet(logger, values[a]); } } @@ -188,6 +201,35 @@ public static partial class NetworkUtils return result is not null; } + private static void LogInvalidSubnet(ILogger? logger, string value) + { + if (logger is null) + { + return; + } + + var trimmed = value.AsSpan().Trim(); + if (trimmed.StartsWith('!')) + { + trimmed = trimmed[1..]; + } + + var slash = trimmed.IndexOf('/'); + if (slash != -1 + && trimmed.Contains(':') + && trimmed.IndexOf("::", StringComparison.Ordinal) == -1) + { + logger.LogWarning( + "Invalid IPv6 subnet '{Subnet}': IPv6 prefix-only notation is not supported. Use the full notation including '::' (e.g. '{Example}::/{Prefix}').", + value, + trimmed[..slash].ToString(), + trimmed[(slash + 1)..].ToString()); + return; + } + + logger.LogWarning("Invalid subnet '{Subnet}' will be ignored.", value); + } + /// <summary> /// Try parsing a string into an <see cref="IPData"/>, respecting exclusions. /// Inputs without a subnet mask will be represented as <see cref="IPData"/> with a single IP. |
