|
@@ -10,16 +10,22 @@ using Microsoft.Extensions.Logging;
|
|
|
|
|
|
namespace Emby.Server.Implementations.Networking
|
|
|
{
|
|
|
+ /// <summary>
|
|
|
+ /// Class to take care of network interface management.
|
|
|
+ /// </summary>
|
|
|
public class NetworkManager : INetworkManager
|
|
|
{
|
|
|
private readonly ILogger _logger;
|
|
|
-
|
|
|
- private IPAddress[] _localIpAddresses;
|
|
|
private readonly object _localIpAddressSyncLock = new object();
|
|
|
-
|
|
|
private readonly object _subnetLookupLock = new object();
|
|
|
- private Dictionary<string, List<string>> _subnetLookup = new Dictionary<string, List<string>>(StringComparer.Ordinal);
|
|
|
+ private readonly Dictionary<string, List<string>> _subnetLookup = new Dictionary<string, List<string>>(StringComparer.Ordinal);
|
|
|
+ private IPAddress[] _localIpAddresses;
|
|
|
+ private List<PhysicalAddress> _macAddresses;
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Initializes a new instance of the <see cref="NetworkManager"/> class.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="logger">Logger to use for messages.</param>
|
|
|
public NetworkManager(ILogger<NetworkManager> logger)
|
|
|
{
|
|
|
_logger = logger;
|
|
@@ -28,10 +34,232 @@ namespace Emby.Server.Implementations.Networking
|
|
|
NetworkChange.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged;
|
|
|
}
|
|
|
|
|
|
+ /// <inheritdoc/>
|
|
|
public event EventHandler NetworkChanged;
|
|
|
|
|
|
+ /// <inheritdoc/>
|
|
|
public Func<string[]> LocalSubnetsFn { get; set; }
|
|
|
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public IPAddress[] GetLocalIpAddresses()
|
|
|
+ {
|
|
|
+ lock (_localIpAddressSyncLock)
|
|
|
+ {
|
|
|
+ if (_localIpAddresses == null)
|
|
|
+ {
|
|
|
+ var addresses = GetLocalIpAddressesInternal().ToArray();
|
|
|
+
|
|
|
+ _localIpAddresses = addresses;
|
|
|
+ }
|
|
|
+
|
|
|
+ return _localIpAddresses;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public bool IsInPrivateAddressSpace(string endpoint)
|
|
|
+ {
|
|
|
+ return IsInPrivateAddressSpace(endpoint, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public bool IsInLocalNetwork(string endpoint)
|
|
|
+ {
|
|
|
+ return IsInLocalNetworkInternal(endpoint, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public bool IsAddressInSubnets(string addressString, string[] subnets)
|
|
|
+ {
|
|
|
+ return IsAddressInSubnets(IPAddress.Parse(addressString), addressString, subnets);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public bool IsInPrivateAddressSpaceAndLocalSubnet(string endpoint)
|
|
|
+ {
|
|
|
+ if (endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase))
|
|
|
+ {
|
|
|
+ var endpointFirstPart = endpoint.Split('.')[0];
|
|
|
+
|
|
|
+ var subnets = GetSubnets(endpointFirstPart);
|
|
|
+
|
|
|
+ foreach (var subnet_Match in subnets)
|
|
|
+ {
|
|
|
+ // logger.LogDebug("subnet_Match:" + subnet_Match);
|
|
|
+
|
|
|
+ if (endpoint.StartsWith(subnet_Match + ".", StringComparison.OrdinalIgnoreCase))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Gets a random port number that is currently available.
|
|
|
+ /// </summary>
|
|
|
+ /// <returns>System.Int32.</returns>
|
|
|
+ public int GetRandomUnusedTcpPort()
|
|
|
+ {
|
|
|
+ var listener = new TcpListener(IPAddress.Any, 0);
|
|
|
+ listener.Start();
|
|
|
+ var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
|
|
+ listener.Stop();
|
|
|
+ return port;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public int GetRandomUnusedUdpPort()
|
|
|
+ {
|
|
|
+ var localEndPoint = new IPEndPoint(IPAddress.Any, 0);
|
|
|
+ var udpClient = new UdpClient(localEndPoint);
|
|
|
+ using (udpClient)
|
|
|
+ {
|
|
|
+ var port = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port;
|
|
|
+ return port;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public List<PhysicalAddress> GetMacAddresses()
|
|
|
+ {
|
|
|
+ if (_macAddresses == null)
|
|
|
+ {
|
|
|
+ _macAddresses = GetMacAddressesInternal().ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ return _macAddresses;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public bool IsInSameSubnet(IPAddress address1, IPAddress address2, IPAddress subnetMask)
|
|
|
+ {
|
|
|
+ IPAddress network1 = GetNetworkAddress(address1, subnetMask);
|
|
|
+ IPAddress network2 = GetNetworkAddress(address2, subnetMask);
|
|
|
+ return network1.Equals(network2);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public bool IsAddressInSubnets(IPAddress address, bool excludeInterfaces, bool excludeRFC)
|
|
|
+ {
|
|
|
+ byte[] octet = address.GetAddressBytes();
|
|
|
+
|
|
|
+ if ((octet[0] == 127) || // RFC1122
|
|
|
+ (octet[0] == 169 && octet[1] == 254)) // RFC3927
|
|
|
+ {
|
|
|
+ // don't use on loopback or 169 interfaces
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ string addressString = address.ToString();
|
|
|
+ string excludeAddress = "[" + addressString + "]";
|
|
|
+ var subnets = LocalSubnetsFn();
|
|
|
+
|
|
|
+ // Exclude any addresses if they appear in the LAN list in [ ]
|
|
|
+ if (Array.IndexOf(subnets, excludeAddress) != -1)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return IsAddressInSubnets(address, addressString, subnets);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public IPAddress GetLocalIpSubnetMask(IPAddress address)
|
|
|
+ {
|
|
|
+ NetworkInterface[] interfaces;
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var validStatuses = new[] { OperationalStatus.Up, OperationalStatus.Unknown };
|
|
|
+
|
|
|
+ interfaces = NetworkInterface.GetAllNetworkInterfaces()
|
|
|
+ .Where(i => validStatuses.Contains(i.OperationalStatus))
|
|
|
+ .ToArray();
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ _logger.LogError(ex, "Error in GetAllNetworkInterfaces");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (NetworkInterface ni in interfaces)
|
|
|
+ {
|
|
|
+ foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
|
|
|
+ {
|
|
|
+ if (ip.Address.Equals(address) && ip.IPv4Mask != null)
|
|
|
+ {
|
|
|
+ return ip.IPv4Mask;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Checks if the give address false within the ranges givin in [subnets]. The addresses in subnets can be hosts or subnets in the CIDR format.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="address">IPAddress version of the address.</param>
|
|
|
+ /// <param name="addressString">The address to check.</param>
|
|
|
+ /// <param name="subnets">If true, check against addresses in the LAN settings which have [] arroud and return true if it matches the address give in address.</param>
|
|
|
+ /// <returns><c>false</c>if the address isn't in the subnets, <c>true</c> otherwise.</returns>
|
|
|
+ private static bool IsAddressInSubnets(IPAddress address, string addressString, string[] subnets)
|
|
|
+ {
|
|
|
+ foreach (var subnet in subnets)
|
|
|
+ {
|
|
|
+ var normalizedSubnet = subnet.Trim();
|
|
|
+ // Is the subnet a host address and does it match the address being passes?
|
|
|
+ if (string.Equals(normalizedSubnet, addressString, StringComparison.OrdinalIgnoreCase))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Parse CIDR subnets and see if address falls within it.
|
|
|
+ if (normalizedSubnet.Contains('/', StringComparison.Ordinal))
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var ipNetwork = IPNetwork.Parse(normalizedSubnet);
|
|
|
+ if (ipNetwork.Contains(address))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch
|
|
|
+ {
|
|
|
+ // Ignoring - invalid subnet passed encountered.
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Task<IPAddress[]> GetIpAddresses(string hostName)
|
|
|
+ {
|
|
|
+ return Dns.GetHostAddressesAsync(hostName);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static async Task<IEnumerable<IPAddress>> GetLocalIpAddressesFallback()
|
|
|
+ {
|
|
|
+ var host = await Dns.GetHostEntryAsync(Dns.GetHostName()).ConfigureAwait(false);
|
|
|
+
|
|
|
+ // Reverse them because the last one is usually the correct one
|
|
|
+ // It's not fool-proof so ultimately the consumer will have to examine them and decide
|
|
|
+ return host.AddressList
|
|
|
+ .Where(i => i.AddressFamily == AddressFamily.InterNetwork || i.AddressFamily == AddressFamily.InterNetworkV6)
|
|
|
+ .Reverse();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static IEnumerable<PhysicalAddress> GetMacAddressesInternal()
|
|
|
+ => NetworkInterface.GetAllNetworkInterfaces()
|
|
|
+ .Where(i => i.NetworkInterfaceType != NetworkInterfaceType.Loopback)
|
|
|
+ .Select(x => x.GetPhysicalAddress())
|
|
|
+ .Where(x => x != null && x != PhysicalAddress.None);
|
|
|
+
|
|
|
private void OnNetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
|
|
|
{
|
|
|
_logger.LogDebug("NetworkAvailabilityChanged");
|
|
@@ -55,21 +283,6 @@ namespace Emby.Server.Implementations.Networking
|
|
|
NetworkChanged?.Invoke(this, EventArgs.Empty);
|
|
|
}
|
|
|
|
|
|
- public IPAddress[] GetLocalIpAddresses()
|
|
|
- {
|
|
|
- lock (_localIpAddressSyncLock)
|
|
|
- {
|
|
|
- if (_localIpAddresses == null)
|
|
|
- {
|
|
|
- var addresses = GetLocalIpAddressesInternal().ToArray();
|
|
|
-
|
|
|
- _localIpAddresses = addresses;
|
|
|
- }
|
|
|
-
|
|
|
- return _localIpAddresses;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private List<IPAddress> GetLocalIpAddressesInternal()
|
|
|
{
|
|
|
var list = GetIPsDefault().ToList();
|
|
@@ -89,6 +302,7 @@ namespace Emby.Server.Implementations.Networking
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
+
|
|
|
if (Array.IndexOf(subnets, "[" + i.ToString() + "]") == -1)
|
|
|
{
|
|
|
listClone.Add(i);
|
|
@@ -103,12 +317,7 @@ namespace Emby.Server.Implementations.Networking
|
|
|
.ToList();
|
|
|
}
|
|
|
|
|
|
- public bool IsInPrivateAddressSpace(string endpoint)
|
|
|
- {
|
|
|
- return IsInPrivateAddressSpace(endpoint, true);
|
|
|
- }
|
|
|
-
|
|
|
- // checks if the address in endpoint is an RFC1918, RFC1122, or RFC3927 address
|
|
|
+ // Checks if the address in endpoint is an RFC1918, RFC1122, or RFC3927 address
|
|
|
private bool IsInPrivateAddressSpace(string endpoint, bool checkSubnets)
|
|
|
{
|
|
|
if (string.Equals(endpoint, "::1", StringComparison.OrdinalIgnoreCase))
|
|
@@ -116,12 +325,12 @@ namespace Emby.Server.Implementations.Networking
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- // ipv6
|
|
|
+ // IPV6
|
|
|
if (endpoint.Split('.').Length > 4)
|
|
|
{
|
|
|
// Handle ipv4 mapped to ipv6
|
|
|
var originalEndpoint = endpoint;
|
|
|
- endpoint = endpoint.Replace("::ffff:", string.Empty);
|
|
|
+ endpoint = endpoint.Replace("::ffff:", string.Empty, StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
|
if (string.Equals(endpoint, originalEndpoint, StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
@@ -131,27 +340,20 @@ namespace Emby.Server.Implementations.Networking
|
|
|
|
|
|
// Private address space:
|
|
|
|
|
|
- if (endpoint.ToLower() == "localhost")
|
|
|
+ if (string.Equals(endpoint, "localhost", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- try
|
|
|
- {
|
|
|
- byte[] octet = IPAddress.Parse(endpoint).GetAddressBytes();
|
|
|
+ byte[] octet = IPAddress.Parse(endpoint).GetAddressBytes();
|
|
|
|
|
|
- if ((octet[0] == 10) ||
|
|
|
- (octet[0] == 172 && (octet[1] >= 16 && octet[1] <= 31)) || // RFC1918
|
|
|
- (octet[0] == 192 && octet[1] == 168) || // RFC1918
|
|
|
- (octet[0] == 127) || // RFC1122
|
|
|
- (octet[0] == 169 && octet[1] == 254)) // RFC3927
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- catch
|
|
|
+ if ((octet[0] == 10) ||
|
|
|
+ (octet[0] == 172 && (octet[1] >= 16 && octet[1] <= 31)) || // RFC1918
|
|
|
+ (octet[0] == 192 && octet[1] == 168) || // RFC1918
|
|
|
+ (octet[0] == 127) || // RFC1122
|
|
|
+ (octet[0] == 169 && octet[1] == 254)) // RFC3927
|
|
|
{
|
|
|
-
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
if (checkSubnets && IsInPrivateAddressSpaceAndLocalSubnet(endpoint))
|
|
@@ -162,29 +364,7 @@ namespace Emby.Server.Implementations.Networking
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- public bool IsInPrivateAddressSpaceAndLocalSubnet(string endpoint)
|
|
|
- {
|
|
|
- if (endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase))
|
|
|
- {
|
|
|
- var endpointFirstPart = endpoint.Split('.')[0];
|
|
|
-
|
|
|
- var subnets = GetSubnets(endpointFirstPart);
|
|
|
-
|
|
|
- foreach (var subnet_Match in subnets)
|
|
|
- {
|
|
|
- //logger.LogDebug("subnet_Match:" + subnet_Match);
|
|
|
-
|
|
|
- if (endpoint.StartsWith(subnet_Match + ".", StringComparison.OrdinalIgnoreCase))
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // Gives a list of possible subnets from the system whose interface ip starts with endpointFirstPart
|
|
|
+ // Gives a list of possible subnets from the system whose interface ip starts with endpointFirstPart
|
|
|
private List<string> GetSubnets(string endpointFirstPart)
|
|
|
{
|
|
|
lock (_subnetLookupLock)
|
|
@@ -230,74 +410,6 @@ namespace Emby.Server.Implementations.Networking
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public bool IsInLocalNetwork(string endpoint)
|
|
|
- {
|
|
|
- return IsInLocalNetworkInternal(endpoint, true);
|
|
|
- }
|
|
|
-
|
|
|
- public bool IsAddressInSubnets(string addressString, string[] subnets)
|
|
|
- {
|
|
|
- return IsAddressInSubnets(IPAddress.Parse(addressString), addressString, subnets);
|
|
|
- }
|
|
|
-
|
|
|
- // returns true if address is in the LAN list in the config file
|
|
|
- // always returns false if address has been excluded from the LAN if excludeInterfaces is true
|
|
|
- // and excludes RFC addresses if excludeRFC is true
|
|
|
- public bool IsAddressInSubnets(IPAddress address, bool excludeInterfaces, bool excludeRFC)
|
|
|
- {
|
|
|
- byte[] octet = address.GetAddressBytes();
|
|
|
-
|
|
|
- if ((octet[0] == 127) || // RFC1122
|
|
|
- (octet[0] == 169 && octet[1] == 254)) // RFC3927
|
|
|
- {
|
|
|
- // don't use on loopback or 169 interfaces
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- string addressString = address.ToString();
|
|
|
- string excludeAddress = "[" + addressString + "]";
|
|
|
- var subnets = LocalSubnetsFn();
|
|
|
-
|
|
|
- // Exclude any addresses if they appear in the LAN list in [ ]
|
|
|
- if (Array.IndexOf(subnets, excludeAddress) != -1)
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
- return IsAddressInSubnets(address, addressString, subnets);
|
|
|
- }
|
|
|
-
|
|
|
- // Checks to see if address/addressString (same but different type) falls within subnets[]
|
|
|
- private static bool IsAddressInSubnets(IPAddress address, string addressString, string[] subnets)
|
|
|
- {
|
|
|
- foreach (var subnet in subnets)
|
|
|
- {
|
|
|
- var normalizedSubnet = subnet.Trim();
|
|
|
- // is the subnet a host address and does it match the address being passes?
|
|
|
- if (string.Equals(normalizedSubnet, addressString, StringComparison.OrdinalIgnoreCase))
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
- // parse CIDR subnets and see if address falls within it.
|
|
|
- if (normalizedSubnet.Contains('/', StringComparison.Ordinal))
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- var ipNetwork = IPNetwork.Parse(normalizedSubnet);
|
|
|
- if (ipNetwork.Contains(address))
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- catch
|
|
|
- {
|
|
|
- // Ignoring - invalid subnet passed encountered.
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
private bool IsInLocalNetworkInternal(string endpoint, bool resolveHost)
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(endpoint))
|
|
@@ -315,7 +427,7 @@ namespace Emby.Server.Implementations.Networking
|
|
|
var localSubnets = localSubnetsFn();
|
|
|
foreach (var subnet in localSubnets)
|
|
|
{
|
|
|
- // only validate if there's at least one valid entry
|
|
|
+ // Only validate if there's at least one valid entry.
|
|
|
if (!string.IsNullOrWhiteSpace(subnet))
|
|
|
{
|
|
|
return IsAddressInSubnets(address, addressString, localSubnets) || IsInPrivateAddressSpace(addressString, false);
|
|
@@ -372,7 +484,7 @@ namespace Emby.Server.Implementations.Networking
|
|
|
}
|
|
|
catch (InvalidOperationException)
|
|
|
{
|
|
|
- // Can happen with reverse proxy or IIS url rewriting
|
|
|
+ // Can happen with reverse proxy or IIS url rewriting?
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
@@ -384,11 +496,6 @@ namespace Emby.Server.Implementations.Networking
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- private static Task<IPAddress[]> GetIpAddresses(string hostName)
|
|
|
- {
|
|
|
- return Dns.GetHostAddressesAsync(hostName);
|
|
|
- }
|
|
|
-
|
|
|
private IEnumerable<IPAddress> GetIPsDefault()
|
|
|
{
|
|
|
IEnumerable<NetworkInterface> interfaces;
|
|
@@ -418,64 +525,6 @@ namespace Emby.Server.Implementations.Networking
|
|
|
.Select(x => x.First());
|
|
|
}
|
|
|
|
|
|
- private static async Task<IEnumerable<IPAddress>> GetLocalIpAddressesFallback()
|
|
|
- {
|
|
|
- var host = await Dns.GetHostEntryAsync(Dns.GetHostName()).ConfigureAwait(false);
|
|
|
-
|
|
|
- // Reverse them because the last one is usually the correct one
|
|
|
- // It's not fool-proof so ultimately the consumer will have to examine them and decide
|
|
|
- return host.AddressList
|
|
|
- .Where(i => i.AddressFamily == AddressFamily.InterNetwork || i.AddressFamily == AddressFamily.InterNetworkV6)
|
|
|
- .Reverse();
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Gets a random port number that is currently available
|
|
|
- /// </summary>
|
|
|
- /// <returns>System.Int32.</returns>
|
|
|
- public int GetRandomUnusedTcpPort()
|
|
|
- {
|
|
|
- var listener = new TcpListener(IPAddress.Any, 0);
|
|
|
- listener.Start();
|
|
|
- var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
|
|
- listener.Stop();
|
|
|
- return port;
|
|
|
- }
|
|
|
-
|
|
|
- public int GetRandomUnusedUdpPort()
|
|
|
- {
|
|
|
- var localEndPoint = new IPEndPoint(IPAddress.Any, 0);
|
|
|
- using (var udpClient = new UdpClient(localEndPoint))
|
|
|
- {
|
|
|
- var port = ((IPEndPoint)udpClient.Client.LocalEndPoint).Port;
|
|
|
- return port;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private List<PhysicalAddress> _macAddresses;
|
|
|
- public List<PhysicalAddress> GetMacAddresses()
|
|
|
- {
|
|
|
- if (_macAddresses == null)
|
|
|
- {
|
|
|
- _macAddresses = GetMacAddressesInternal().ToList();
|
|
|
- }
|
|
|
-
|
|
|
- return _macAddresses;
|
|
|
- }
|
|
|
-
|
|
|
- private static IEnumerable<PhysicalAddress> GetMacAddressesInternal()
|
|
|
- => NetworkInterface.GetAllNetworkInterfaces()
|
|
|
- .Where(i => i.NetworkInterfaceType != NetworkInterfaceType.Loopback)
|
|
|
- .Select(x => x.GetPhysicalAddress())
|
|
|
- .Where(x => x != null && x != PhysicalAddress.None);
|
|
|
-
|
|
|
- public bool IsInSameSubnet(IPAddress address1, IPAddress address2, IPAddress subnetMask)
|
|
|
- {
|
|
|
- IPAddress network1 = GetNetworkAddress(address1, subnetMask);
|
|
|
- IPAddress network2 = GetNetworkAddress(address2, subnetMask);
|
|
|
- return network1.Equals(network2);
|
|
|
- }
|
|
|
-
|
|
|
private IPAddress GetNetworkAddress(IPAddress address, IPAddress subnetMask)
|
|
|
{
|
|
|
byte[] ipAdressBytes = address.GetAddressBytes();
|
|
@@ -494,37 +543,5 @@ namespace Emby.Server.Implementations.Networking
|
|
|
|
|
|
return new IPAddress(broadcastAddress);
|
|
|
}
|
|
|
-
|
|
|
- public IPAddress GetLocalIpSubnetMask(IPAddress address)
|
|
|
- {
|
|
|
- NetworkInterface[] interfaces;
|
|
|
-
|
|
|
- try
|
|
|
- {
|
|
|
- var validStatuses = new[] { OperationalStatus.Up, OperationalStatus.Unknown };
|
|
|
-
|
|
|
- interfaces = NetworkInterface.GetAllNetworkInterfaces()
|
|
|
- .Where(i => validStatuses.Contains(i.OperationalStatus))
|
|
|
- .ToArray();
|
|
|
- }
|
|
|
- catch (Exception ex)
|
|
|
- {
|
|
|
- _logger.LogError(ex, "Error in GetAllNetworkInterfaces");
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- foreach (NetworkInterface ni in interfaces)
|
|
|
- {
|
|
|
- foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
|
|
|
- {
|
|
|
- if (ip.Address.Equals(address) && ip.IPv4Mask != null)
|
|
|
- {
|
|
|
- return ip.IPv4Mask;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
}
|
|
|
}
|