diff options
| author | Joshua M. Boniface <joshua@boniface.me> | 2026-04-04 01:53:59 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-04 01:53:59 -0400 |
| commit | a2dcaa9521b4454f59002912df22e8a48befbe21 (patch) | |
| tree | 70eb85b468b8d7c7398ca4348f9edeaf30af161e | |
| parent | e4d6b8e1bd073fa094efb7a4ca333e46b344c546 (diff) | |
| parent | 72b4faa00b743dc5bbd2e25c54b216510e978a5a (diff) | |
Merge pull request #15902 from ZeusCraft10/fix/udp-discovery-cross-subnet-ipv6
| -rw-r--r-- | CONTRIBUTORS.md | 1 | ||||
| -rw-r--r-- | src/Jellyfin.Networking/Manager/NetworkManager.cs | 29 | ||||
| -rw-r--r-- | tests/Jellyfin.Networking.Tests/NetworkParseTests.cs | 2 |
3 files changed, 29 insertions, 3 deletions
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index cb7d3fbbc4..4b0cec3c92 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -164,6 +164,7 @@ - [XVicarious](https://github.com/XVicarious) - [YouKnowBlom](https://github.com/YouKnowBlom) - [ZachPhelan](https://github.com/ZachPhelan) + - [ZeusCraft10](https://github.com/ZeusCraft10) - [KristupasSavickas](https://github.com/KristupasSavickas) - [Pusta](https://github.com/pusta) - [nielsvanvelzen](https://github.com/nielsvanvelzen) diff --git a/src/Jellyfin.Networking/Manager/NetworkManager.cs b/src/Jellyfin.Networking/Manager/NetworkManager.cs index 8277ce54bb..6a8a91fa51 100644 --- a/src/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/src/Jellyfin.Networking/Manager/NetworkManager.cs @@ -878,7 +878,20 @@ public class NetworkManager : INetworkManager, IDisposable if (availableInterfaces.Count == 0) { // There isn't any others, so we'll use the loopback. - result = IsIPv4Enabled && !IsIPv6Enabled ? "127.0.0.1" : "::1"; + // Prefer loopback address matching the source's address family + if (source is not null && source.AddressFamily == AddressFamily.InterNetwork && IsIPv4Enabled) + { + result = "127.0.0.1"; + } + else if (source is not null && source.AddressFamily == AddressFamily.InterNetworkV6 && IsIPv6Enabled) + { + result = "::1"; + } + else + { + result = IsIPv4Enabled ? "127.0.0.1" : "::1"; + } + _logger.LogWarning("{Source}: Only loopback {Result} returned, using that as bind address.", source, result); return result; } @@ -903,9 +916,19 @@ public class NetworkManager : INetworkManager, IDisposable } } - // Fallback to first available interface + // Fallback to an interface matching the source's address family, or first available + var preferredInterface = availableInterfaces + .FirstOrDefault(x => x.Address.AddressFamily == source.AddressFamily); + + if (preferredInterface is not null) + { + result = NetworkUtils.FormatIPString(preferredInterface.Address); + _logger.LogDebug("{Source}: No matching subnet found, using interface with matching address family: {Result}", source, result); + return result; + } + result = NetworkUtils.FormatIPString(availableInterfaces[0].Address); - _logger.LogDebug("{Source}: No matching interfaces found, using preferred interface as bind address: {Result}", source, result); + _logger.LogDebug("{Source}: No matching interfaces found, using first available interface as bind address: {Result}", source, result); return result; } diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs index 871604514b..b63009d6a5 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -377,6 +377,8 @@ namespace Jellyfin.Networking.Tests [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "192.168.1.209", "10.0.0.1")] // LAN not bound, so return external. [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "8.8.8.8", "10.0.0.1")] // return external bind address [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "192.168.1.210", "192.168.1.208")] // return LAN bind address + // Cross-subnet IPv4 request should return IPv4, not IPv6 (Issue #15898) + [InlineData("192.168.1.208/24,-16,eth16|fd00::1/64,10,eth7", "192.168.1.0/24", "", "192.168.2.100", "192.168.1.208")] public void GetBindInterface_ValidSourceGiven_Success(string interfaces, string lan, string bind, string source, string result) { var conf = new NetworkConfiguration |
