|
@@ -56,13 +56,13 @@ namespace Emby.Server.Implementations.Networking
|
|
|
NetworkChanged?.Invoke(this, EventArgs.Empty);
|
|
|
}
|
|
|
|
|
|
- public IPAddress[] GetLocalIpAddresses(bool ignoreVirtualInterface = true)
|
|
|
+ public IPAddress[] GetLocalIpAddresses()
|
|
|
{
|
|
|
lock (_localIpAddressSyncLock)
|
|
|
{
|
|
|
if (_localIpAddresses == null)
|
|
|
{
|
|
|
- var addresses = GetLocalIpAddressesInternal(ignoreVirtualInterface).ToArray();
|
|
|
+ var addresses = GetLocalIpAddressesInternal().ToArray();
|
|
|
|
|
|
_localIpAddresses = addresses;
|
|
|
}
|
|
@@ -71,35 +71,37 @@ namespace Emby.Server.Implementations.Networking
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private List<IPAddress> GetLocalIpAddressesInternal(bool ignoreVirtualInterface)
|
|
|
+ private List<IPAddress> GetLocalIpAddressesInternal()
|
|
|
{
|
|
|
- var list = GetIPsDefault(ignoreVirtualInterface).ToList();
|
|
|
+ var list = GetIPsDefault().ToList();
|
|
|
|
|
|
if (list.Count == 0)
|
|
|
{
|
|
|
list = GetLocalIpAddressesFallback().GetAwaiter().GetResult().ToList();
|
|
|
}
|
|
|
|
|
|
- var listClone = list.ToList();
|
|
|
+ var listClone = new List<IPAddress>();
|
|
|
|
|
|
- return list
|
|
|
- .OrderBy(i => i.AddressFamily == AddressFamily.InterNetwork ? 0 : 1)
|
|
|
- .ThenBy(i => listClone.IndexOf(i))
|
|
|
- .Where(FilterIpAddress)
|
|
|
- .GroupBy(i => i.ToString())
|
|
|
- .Select(x => x.First())
|
|
|
- .ToList();
|
|
|
- }
|
|
|
+ var subnets = LocalSubnetsFn();
|
|
|
|
|
|
- private static bool FilterIpAddress(IPAddress address)
|
|
|
- {
|
|
|
- if (address.IsIPv6LinkLocal
|
|
|
- || address.ToString().StartsWith("169.", StringComparison.OrdinalIgnoreCase))
|
|
|
+ foreach (var i in list)
|
|
|
{
|
|
|
- return false;
|
|
|
+ if (i.IsIPv6LinkLocal || i.ToString().StartsWith("169.254.", StringComparison.OrdinalIgnoreCase))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (Array.IndexOf(subnets, "[" + i.ToString() + "]") == -1)
|
|
|
+ {
|
|
|
+ listClone.Add(i);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- return true;
|
|
|
+ return listClone
|
|
|
+ .OrderBy(i => i.AddressFamily == AddressFamily.InterNetwork ? 0 : 1)
|
|
|
+ // .ThenBy(i => listClone.IndexOf(i))
|
|
|
+ .GroupBy(i => i.ToString())
|
|
|
+ .Select(x => x.First())
|
|
|
+ .ToList();
|
|
|
}
|
|
|
|
|
|
public bool IsInPrivateAddressSpace(string endpoint)
|
|
@@ -107,6 +109,7 @@ namespace Emby.Server.Implementations.Networking
|
|
|
return IsInPrivateAddressSpace(endpoint, true);
|
|
|
}
|
|
|
|
|
|
+ // 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))
|
|
@@ -128,23 +131,28 @@ namespace Emby.Server.Implementations.Networking
|
|
|
}
|
|
|
|
|
|
// Private address space:
|
|
|
- // http://en.wikipedia.org/wiki/Private_network
|
|
|
|
|
|
- if (endpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase))
|
|
|
+ if (endpoint.ToLower() == "localhost")
|
|
|
{
|
|
|
- return Is172AddressPrivate(endpoint);
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
- if (endpoint.StartsWith("localhost", StringComparison.OrdinalIgnoreCase) ||
|
|
|
- endpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
|
|
|
- endpoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase))
|
|
|
+ try
|
|
|
{
|
|
|
- return true;
|
|
|
- }
|
|
|
+ byte[] octet = IPAddress.Parse(endpoint).GetAddressBytes();
|
|
|
|
|
|
- if (checkSubnets && endpoint.StartsWith("192.168", StringComparison.OrdinalIgnoreCase))
|
|
|
+ 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
|
|
|
{
|
|
|
- return true;
|
|
|
+ // return false;
|
|
|
}
|
|
|
|
|
|
if (checkSubnets && IsInPrivateAddressSpaceAndLocalSubnet(endpoint))
|
|
@@ -177,6 +185,7 @@ namespace Emby.Server.Implementations.Networking
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ // Gives a list of possible subnets from the system whose interface ip starts with endpointFirstPart
|
|
|
private List<string> GetSubnets(string endpointFirstPart)
|
|
|
{
|
|
|
lock (_subnetLookupLock)
|
|
@@ -222,19 +231,6 @@ namespace Emby.Server.Implementations.Networking
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static bool Is172AddressPrivate(string endpoint)
|
|
|
- {
|
|
|
- for (var i = 16; i <= 31; i++)
|
|
|
- {
|
|
|
- if (endpoint.StartsWith("172." + i.ToString(CultureInfo.InvariantCulture) + ".", StringComparison.OrdinalIgnoreCase))
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
public bool IsInLocalNetwork(string endpoint)
|
|
|
{
|
|
|
return IsInLocalNetworkInternal(endpoint, true);
|
|
@@ -245,23 +241,57 @@ namespace Emby.Server.Implementations.Networking
|
|
|
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))
|
|
|
{
|
|
|
- var ipNetwork = IPNetwork.Parse(normalizedSubnet);
|
|
|
- if (ipNetwork.Contains(address))
|
|
|
+ try
|
|
|
{
|
|
|
- return true;
|
|
|
+ var ipNetwork = IPNetwork.Parse(normalizedSubnet);
|
|
|
+ if (ipNetwork.Contains(address))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch
|
|
|
+ {
|
|
|
+ // Ignoring - invalid subnet passed encountered.
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -359,8 +389,8 @@ namespace Emby.Server.Implementations.Networking
|
|
|
{
|
|
|
return Dns.GetHostAddressesAsync(hostName);
|
|
|
}
|
|
|
-
|
|
|
- private IEnumerable<IPAddress> GetIPsDefault(bool ignoreVirtualInterface)
|
|
|
+
|
|
|
+ private IEnumerable<IPAddress> GetIPsDefault()
|
|
|
{
|
|
|
IEnumerable<NetworkInterface> interfaces;
|
|
|
|
|
@@ -380,15 +410,7 @@ namespace Emby.Server.Implementations.Networking
|
|
|
{
|
|
|
var ipProperties = network.GetIPProperties();
|
|
|
|
|
|
- // Try to exclude virtual adapters
|
|
|
- // http://stackoverflow.com/questions/8089685/c-sharp-finding-my-machines-local-ip-address-and-not-the-vms
|
|
|
- var addr = ipProperties.GatewayAddresses.FirstOrDefault();
|
|
|
- if (addr == null
|
|
|
- || (ignoreVirtualInterface
|
|
|
- && (addr.Address.Equals(IPAddress.Any) || addr.Address.Equals(IPAddress.IPv6Any))))
|
|
|
- {
|
|
|
- return Enumerable.Empty<IPAddress>();
|
|
|
- }
|
|
|
+ // Exclude any addresses if they appear in the LAN list in [ ]
|
|
|
|
|
|
return ipProperties.UnicastAddresses
|
|
|
.Select(i => i.Address)
|
|
@@ -494,15 +516,12 @@ namespace Emby.Server.Implementations.Networking
|
|
|
|
|
|
foreach (NetworkInterface ni in interfaces)
|
|
|
{
|
|
|
- if (ni.GetIPProperties().GatewayAddresses.FirstOrDefault() != null)
|
|
|
+ foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
|
|
|
{
|
|
|
- foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
|
|
|
+ if (ip.Address.Equals(address) && ip.IPv4Mask != null)
|
|
|
{
|
|
|
- if (ip.Address.Equals(address) && ip.IPv4Mask != null)
|
|
|
- {
|
|
|
- return ip.IPv4Mask;
|
|
|
- }
|
|
|
- }
|
|
|
+ return ip.IPv4Mask;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|