diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs
index 51fcb6d9a0..17bbf9633a 100644
--- a/Jellyfin.Networking/Manager/NetworkManager.cs
+++ b/Jellyfin.Networking/Manager/NetworkManager.cs
@@ -157,15 +157,16 @@ namespace Jellyfin.Networking.Manager
/// Creates a new network collection.
///
/// Items to assign the collection, or null.
+ /// True if subnets that overlap should be merged (default).
/// The collection created.
- public static Collection CreateCollection(IEnumerable? source = null)
+ public static Collection CreateCollection(IEnumerable? source = null, bool unique = true)
{
var result = new Collection();
if (source != null)
{
foreach (var item in source)
{
- result.AddItem(item);
+ result.AddItem(item, unique);
}
}
@@ -386,10 +387,12 @@ namespace Jellyfin.Networking.Manager
}
// Get the first LAN interface address that isn't a loopback.
- var interfaces = CreateCollection(_interfaceAddresses
- .Exclude(_bindExclusions)
- .Where(IsInLocalNetwork)
- .OrderBy(p => p.Tag));
+ var interfaces = CreateCollection(
+ _interfaceAddresses
+ .Exclude(_bindExclusions)
+ .Where(IsInLocalNetwork)
+ .OrderBy(p => p.Tag),
+ false);
if (interfaces.Count > 0)
{
@@ -429,11 +432,11 @@ namespace Jellyfin.Networking.Manager
if (_bindExclusions.Count > 0)
{
// Return all the internal interfaces except the ones excluded.
- return CreateCollection(_internalInterfaces.Where(p => !_bindExclusions.ContainsAddress(p)));
+ return CreateCollection(_internalInterfaces.Where(p => !_bindExclusions.ContainsAddress(p)), false);
}
// No bind address, so return all internal interfaces.
- return CreateCollection(_internalInterfaces.Where(p => !p.IsLoopback()));
+ return CreateCollection(_internalInterfaces.Where(p => !p.IsLoopback()), false);
}
return new Collection(_bindAddresses);
@@ -555,7 +558,7 @@ namespace Jellyfin.Networking.Manager
&& ((IsIP4Enabled && iface.Address.AddressFamily == AddressFamily.InterNetwork)
|| (IsIP6Enabled && iface.Address.AddressFamily == AddressFamily.InterNetworkV6)))
{
- result.AddItem(iface);
+ result.AddItem(iface, false);
}
}
@@ -599,8 +602,8 @@ namespace Jellyfin.Networking.Manager
var address = IPNetAddress.Parse(parts[0]);
var index = int.Parse(parts[1], CultureInfo.InvariantCulture);
address.Tag = index;
- _interfaceAddresses.AddItem(address);
- _interfaceNames.Add(parts[2], Math.Abs(index));
+ _interfaceAddresses.AddItem(address, false);
+ _interfaceNames[parts[2]] = Math.Abs(index);
}
}
@@ -977,7 +980,7 @@ namespace Jellyfin.Networking.Manager
{
_logger.LogDebug("Using LAN interface addresses as user provided no LAN details.");
// Internal interfaces must be private and not excluded.
- _internalInterfaces = CreateCollection(_interfaceAddresses.Where(i => IsPrivateAddressRange(i) && !_excludedSubnets.ContainsAddress(i)));
+ _internalInterfaces = CreateCollection(_interfaceAddresses.Where(i => IsPrivateAddressRange(i) && !_excludedSubnets.ContainsAddress(i)), false);
// Subnets are the same as the calculated internal interface.
_lanSubnets = new Collection();
@@ -1012,7 +1015,7 @@ namespace Jellyfin.Networking.Manager
}
// Internal interfaces must be private, not excluded and part of the LocalNetworkSubnet.
- _internalInterfaces = CreateCollection(_interfaceAddresses.Where(i => IsInLocalNetwork(i)));
+ _internalInterfaces = CreateCollection(_interfaceAddresses.Where(i => IsInLocalNetwork(i)), false);
}
_logger.LogInformation("Defined LAN addresses : {0}", _lanSubnets.AsString());
@@ -1071,7 +1074,7 @@ namespace Jellyfin.Networking.Manager
nw.Tag *= -1;
}
- _interfaceAddresses.AddItem(nw);
+ _interfaceAddresses.AddItem(nw, false);
// Store interface name so we can use the name in Collections.
_interfaceNames[adapter.Description.ToLower(CultureInfo.InvariantCulture)] = tag;
@@ -1092,7 +1095,7 @@ namespace Jellyfin.Networking.Manager
nw.Tag *= -1;
}
- _interfaceAddresses.AddItem(nw);
+ _interfaceAddresses.AddItem(nw, false);
// Store interface name so we can use the name in Collections.
_interfaceNames[adapter.Description.ToLower(CultureInfo.InvariantCulture)] = tag;
@@ -1126,10 +1129,10 @@ namespace Jellyfin.Networking.Manager
{
_logger.LogWarning("No interfaces information available. Using loopback.");
// Last ditch attempt - use loopback address.
- _interfaceAddresses.AddItem(IPNetAddress.IP4Loopback);
+ _interfaceAddresses.AddItem(IPNetAddress.IP4Loopback, false);
if (IsIP6Enabled)
{
- _interfaceAddresses.AddItem(IPNetAddress.IP6Loopback);
+ _interfaceAddresses.AddItem(IPNetAddress.IP6Loopback, false);
}
}
}
diff --git a/MediaBrowser.Common/Net/NetworkExtensions.cs b/MediaBrowser.Common/Net/NetworkExtensions.cs
index 9c1a0cf495..cd0c2ea242 100644
--- a/MediaBrowser.Common/Net/NetworkExtensions.cs
+++ b/MediaBrowser.Common/Net/NetworkExtensions.cs
@@ -27,9 +27,10 @@ namespace MediaBrowser.Common.Net
///
/// The .
/// Item to add.
- public static void AddItem(this Collection source, IPObject item)
+ /// True if subnets that overlap should be merged (default).
+ public static void AddItem(this Collection source, IPObject item, bool unique = true)
{
- if (!source.ContainsAddress(item))
+ if (!source.ContainsAddress(item) || !unique)
{
source.Add(item);
}
diff --git a/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs
index 9f928ded1b..a13822fcbd 100644
--- a/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs
+++ b/tests/Jellyfin.Networking.Tests/NetworkTesting/NetworkParseTests.cs
@@ -38,6 +38,8 @@ namespace Jellyfin.Networking.Tests
[InlineData("192.168.1.208/24,-16,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[]")]
// vEthernet1 and vEthernet212 should be excluded.
[InlineData("192.168.1.200/24,-20,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.200/24", "[200.200.200.200/24]")]
+ // Overlapping interface,
+ [InlineData("192.168.1.110/24,-20,br0|192.168.1.10/24,-16,br0|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[192.168.1.110/24,192.168.1.10/24]")]
public void IgnoreVirtualInterfaces(string interfaces, string lan, string value)
{
var conf = new NetworkConfiguration()