init
This commit is contained in:
233
Common/DTS.CommonCore/Utils/NetworkUtils.cs
Normal file
233
Common/DTS.CommonCore/Utils/NetworkUtils.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DTS.Common.Utils
|
||||
{
|
||||
//FB 18512 This calss contains utility methods, they are moved from Netwroking module
|
||||
public static class NetworkUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// returns true if the network interface is up, false otherwise
|
||||
/// stolen from FWTU
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsNetworkInterfaceUp(IPAddress ip)
|
||||
{
|
||||
foreach (var a in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
try
|
||||
{
|
||||
var ipp = a.GetIPProperties();
|
||||
|
||||
if (ipp.MulticastAddresses.Count == 0)
|
||||
continue; // most of VPN adapters will be skipped
|
||||
if (!a.SupportsMulticast)
|
||||
continue; // multicast is meaningless for this type of connection
|
||||
if (OperationalStatus.Up != a.OperationalStatus)
|
||||
continue; // this adapter is off or not connected
|
||||
if (null == ipp.GetIPv4Properties())
|
||||
continue; // IPv4 is not configured on this adapter
|
||||
if (a.NetworkInterfaceType == NetworkInterfaceType.Loopback)
|
||||
continue;
|
||||
var addressBytes = ip.GetAddressBytes();
|
||||
if (4 == addressBytes.Length && addressBytes[0] == 169 && addressBytes[1] == 254) { continue; }
|
||||
if (a.GetIPProperties().UnicastAddresses.Any(i => i.Address.AddressFamily == AddressFamily.InterNetwork && IPAddress.Equals(i.Address, ip)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Indicates whether any network connection is available.
|
||||
/// Filter connections below a specified speed, as well as virtual network cards.
|
||||
/// </summary>
|
||||
/// <param name="minimumSpeed">The minimum speed required. Passing 0 will not filter connection using speed.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if a network connection is available; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
private static List<NetworkInterface> GetAvailableNetworkInterfaces(long minimumSpeed = 10000000)
|
||||
{
|
||||
if (!NetworkInterface.GetIsNetworkAvailable())
|
||||
return null;
|
||||
|
||||
var niList = new List<NetworkInterface>();
|
||||
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
// discard because of standard reasons
|
||||
if ((ni.NetworkInterfaceType == NetworkInterfaceType.Loopback)
|
||||
|| (ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel))
|
||||
continue;
|
||||
|
||||
// this allow to filter modems, serial, etc.
|
||||
// use 10000000 as a minimum speed for most cases
|
||||
if (ni.Speed < minimumSpeed)
|
||||
continue;
|
||||
|
||||
// discard virtual cards (virtual box, virtual pc, etc.)
|
||||
if (ni.Description.ToLower().Contains("virtual")
|
||||
|| ni.Name.ToLower().Contains("virtual")
|
||||
|| ni.Description.ToLower().Contains("bluethooth")
|
||||
|| ni.Name.ToLower().Contains("bluethooth"))
|
||||
continue;
|
||||
|
||||
// discard "Microsoft Loopback Adapter", it will not show as NetworkInterfaceType.Loopback but as Ethernet Card.
|
||||
if (ni.Description.Equals("Microsoft Loopback Adapter", StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
|
||||
niList.Add(ni);
|
||||
}
|
||||
|
||||
return niList;
|
||||
}
|
||||
|
||||
private static string GetMACAddress(string id)
|
||||
{
|
||||
var macAddress = string.Empty;
|
||||
|
||||
var nics = GetAvailableNetworkInterfaces();
|
||||
|
||||
if (nics == null)
|
||||
return macAddress;
|
||||
|
||||
foreach (var nic in nics)
|
||||
{
|
||||
if (nic.Id != id) continue;
|
||||
var pa = BitConverter.ToString(nic.GetPhysicalAddress().GetAddressBytes());
|
||||
pa = pa.Replace("-", ":");
|
||||
if (string.IsNullOrEmpty(pa)) continue;
|
||||
macAddress = pa;
|
||||
break;
|
||||
}
|
||||
return macAddress;
|
||||
}
|
||||
|
||||
private static bool InvalidNIC(NetworkInterface ni)
|
||||
{
|
||||
return OperationalStatus.Up != ni.OperationalStatus || !ni.SupportsMulticast;
|
||||
}
|
||||
|
||||
public static List<HostInfo> GetAvailableHosts(bool supportMulticastOnly = false)
|
||||
{
|
||||
var nics = GetAvailableNetworkInterfaces();
|
||||
if (nics == null) { return new List<HostInfo>(); }
|
||||
var hosts = new List<HostInfo>();
|
||||
|
||||
foreach (NetworkInterface ni in nics)
|
||||
{
|
||||
if (supportMulticastOnly && InvalidNIC(ni))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//exclude wireshark network interface, it claims it can ping ips lyingly
|
||||
if (ni.Description.Contains("Npcap")) { continue; }
|
||||
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
|
||||
{
|
||||
var addressBytes = ip.Address.GetAddressBytes();
|
||||
if (4 == addressBytes.Length && addressBytes[0] == 169 && addressBytes[1] == 254)
|
||||
{
|
||||
APILogger.Log($"skipping {ni.Name}\\{ni.Description} as it has a 169.254 address");
|
||||
continue;//internal only
|
||||
}
|
||||
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
GetStartAndEndAddress(ip.Address, ip.IPv4Mask, out var startAddress, out var endAddress);
|
||||
hosts.Add(new HostInfo { HostIpAddress = ip.Address.ToString(), HostNetworkId = ni.Id, HostMacAddress = GetMACAddress(ni.Id),
|
||||
StartAddress = startAddress, EndAddress = endAddress
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return hosts;
|
||||
}
|
||||
/// <summary>
|
||||
/// given an IP address and a mask returns a ip address as a string for the first address that is accessible and a string for the last address that is accessible
|
||||
/// anything between the start address and end address after doing a byte-by-byte comparison should be addressable
|
||||
/// will return empty strings if something bad happens. Is designed for 4 byte addresses but isn't necessarily limited.
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <param name="mask"></param>
|
||||
/// <param name="startAddress"></param>
|
||||
/// <param name="endAddress"></param>
|
||||
private static void GetStartAndEndAddress( IPAddress ip, IPAddress mask, out string startAddress, out string endAddress)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ipByte = ip.GetAddressBytes();
|
||||
var maskBytes = mask.GetAddressBytes();
|
||||
|
||||
var startBytes = new byte[ipByte.Length];
|
||||
var endBytes = new byte[ipByte.Length];
|
||||
|
||||
for (var i = 0; i < ipByte.Length; i++)
|
||||
{
|
||||
startBytes[i] = (byte)(ipByte[i] & maskBytes[i]);
|
||||
endBytes[i] = (byte)(ipByte[i] | ~maskBytes[i]);
|
||||
}
|
||||
var startIP = new IPAddress(startBytes);
|
||||
var endIP = new IPAddress(endBytes);
|
||||
startAddress = startIP.ToString();
|
||||
endAddress = endIP.ToString();
|
||||
}
|
||||
catch( Exception ex)
|
||||
{
|
||||
startAddress = string.Empty;
|
||||
endAddress = string.Empty;
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
//FB 25658 Changed the method signature to return bool to determine the connection string has IP in it and it's not USB
|
||||
/// <summary>
|
||||
/// Try to parse connectionString and retrieve the IP address.
|
||||
/// </summary>
|
||||
/// <param name="connectionString"> DAS connectionString which might include the IP address or might be a USB connection string</param>
|
||||
/// <param name="ipAddress">Return the parsed IP address from connectionString</param>
|
||||
/// <returns>Returns true if was able to parse and get the IP otherwise false including the valid USB connection string </returns>
|
||||
public static bool TryParseConnectionString(string connectionString, out string ipAddress)
|
||||
{
|
||||
ipAddress = null;
|
||||
|
||||
if (string.IsNullOrEmpty(connectionString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var uri = new Uri(connectionString);
|
||||
|
||||
if (IPAddress.TryParse(uri.Host, out _))
|
||||
{
|
||||
ipAddress = uri.Host;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
var ip = connectionString.Split(':')[0];
|
||||
|
||||
if (IPAddress.TryParse(ip, out _))
|
||||
{
|
||||
ipAddress = ip;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user