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 { /// /// returns true if the network interface is up, false otherwise /// stolen from FWTU /// /// /// 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; } /// /// Indicates whether any network connection is available. /// Filter connections below a specified speed, as well as virtual network cards. /// /// The minimum speed required. Passing 0 will not filter connection using speed. /// /// true if a network connection is available; otherwise, false. /// private static List GetAvailableNetworkInterfaces(long minimumSpeed = 10000000) { if (!NetworkInterface.GetIsNetworkAvailable()) return null; var niList = new List(); 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 GetAvailableHosts(bool supportMulticastOnly = false) { var nics = GetAvailableNetworkInterfaces(); if (nics == null) { return new List(); } var hosts = new List(); 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; } /// /// 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. /// /// /// /// /// 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 /// /// Try to parse connectionString and retrieve the IP address. /// /// DAS connectionString which might include the IP address or might be a USB connection string /// Return the parsed IP address from connectionString /// Returns true if was able to parse and get the IP otherwise false including the valid USB connection string 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; } } }