Created
December 1, 2018 05:13
-
-
Save bpmooch/e8316532fbb66f9bb58c0da3cb2ac833 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Net; | |
| using System.Net.NetworkInformation; | |
| using System.Net.Sockets; | |
| using System.Runtime.InteropServices; | |
| namespace yeeticus | |
| { | |
| internal static class NetworkInterfaceEx | |
| { | |
| /// <summary> | |
| /// Gets a list of network adapter interfaces that are of type ethernet or wireless, and are operational. | |
| /// </summary> | |
| /// <returns>IEnumerable of network interfaces.</returns> | |
| public static IEnumerable<NetworkInterface> GetActiveNICs() | |
| => NetworkInterface.GetAllNetworkInterfaces() | |
| .Where(x => x.OperationalStatus == OperationalStatus.Up) | |
| .Where(x => x.NetworkInterfaceType == NetworkInterfaceType.Ethernet || x.NetworkInterfaceType == NetworkInterfaceType.Wireless80211); | |
| /// <summary> | |
| /// Retrieves all Gateway Addresses for all Network Interfaces | |
| /// </summary> | |
| /// <returns>IEnumerable containing IPv4 addresses as strings</returns> | |
| public static IEnumerable<string> GetIPv4GatewayAddresses() | |
| => NetworkInterface.GetAllNetworkInterfaces() | |
| .SelectMany(x => x.GetIPProperties().GatewayAddresses) | |
| .Where(x => x.Address.AddressFamily == AddressFamily.InterNetwork) | |
| .Select(x => x.Address.ToString()); | |
| /// <summary> | |
| /// Gets the name of the network adapter. | |
| /// </summary> | |
| /// <param name="ip">IP address of the local network interface to query.</param> | |
| /// <returns>The name of the network interface if found, otherwise "Unknown NIC" is returned.</returns> | |
| public static string GetNICName(string ip) | |
| => GetActiveNICs().SingleOrDefault(x => x.GetIPProperties() | |
| .UnicastAddresses | |
| .Select(y => y.Address.ToString()) | |
| .Contains(ip))? | |
| .Name ?? "Unknown NIC"; | |
| /// <summary> | |
| /// Determines if an IP/NIC address pair are reachable | |
| /// </summary> | |
| /// <param name="ip">IP to check</param> | |
| /// <param name="nic">NIC to send data through</param> | |
| /// <returns>True if destination is reachable, false otherwise</returns> | |
| public static bool IsReachable(string ip, string nic) | |
| { | |
| var success = IPAddress.TryParse(ip, out IPAddress addr); | |
| if (!success) return false; | |
| if (!CanArpSuccessfully(nic)) return false; | |
| if (!IsMulticastIP(ip) && !CanArpSuccessfully(ip, nic)) return false; | |
| return true; | |
| } | |
| /// <summary> | |
| /// Sends ARP request | |
| /// </summary> | |
| /// <param name="DestIP">[In] Destination IP</param> | |
| /// <param name="SrcIP">[In] Optional parameter for source IP. 0 for INADDR_ANY</param> | |
| /// <param name="pMacAddr">[Out] Mac Address of Destination IP</param> | |
| /// <param name="PhyAddrLen">[In, Out] Buffer max size. On return, set to amount of buffer used</param> | |
| /// <returns>Returns 0 if successful, error code otherwise</returns> | |
| [DllImport("iphlpapi.dll", ExactSpelling = true)] | |
| public static extern int SendARP(int DestIP, | |
| int SrcIP, | |
| byte[] pMacAddr, | |
| ref uint PhyAddrLen); | |
| /// <summary> | |
| /// Determines if an IP is the loopback address | |
| /// </summary> | |
| /// <param name="ip">IP to check</param> | |
| /// <returns>True if IP Address is loopback</returns> | |
| public static bool IsLoopback(IPAddress ip) => ip == IPAddress.Loopback; | |
| /// <summary> | |
| /// Sends ARP to determine if IP is reachable | |
| /// </summary> | |
| /// <param name="ip">IP to check</param> | |
| /// <returns>Returns true if ARP request was successful, false otherwise</returns> | |
| public static bool CanArpSuccessfully(string ip) | |
| { | |
| if (IPAddress.TryParse(ip, out IPAddress addr)) | |
| { | |
| return CanArpSuccessfully(addr); | |
| } | |
| else return false; | |
| } | |
| /// <summary> | |
| /// Sends ARP to determine if IP is reachable | |
| /// </summary> | |
| /// <param name="ip">IP to check</param> | |
| /// <returns>True if ARP was successful, false otherwise</returns> | |
| /// <remarks> | |
| /// Replaces IsHostOnLocalNetwork and IsComputerAlive | |
| /// </remarks> | |
| public static bool CanArpSuccessfully(IPAddress ip) | |
| { | |
| if (IsLoopback(ip)) return true; | |
| var addr = BitConverter.ToUInt32(ip.GetAddressBytes(), 0); | |
| uint macLen = 6; | |
| return SendARP((int)addr, 0, new byte[macLen], ref macLen) == 0; | |
| } | |
| /// <summary> | |
| /// Sends ARP to determine if IP is reachable | |
| /// </summary> | |
| /// <param name="ip">IP to check</param> | |
| /// <param name="nic">NIC to send ARP through</param> | |
| /// <returns>Returns true if ARP request was successful, false otherwise</returns> | |
| public static bool CanArpSuccessfully(string ip, string nic) | |
| { | |
| var success = IPAddress.TryParse(ip, out IPAddress addr); | |
| if (!success) return false; | |
| success = IPAddress.TryParse(nic, out IPAddress nicAddr); | |
| if (!success) return false; | |
| return CanArpSuccessfully(addr, nicAddr); | |
| } | |
| /// <summary> | |
| /// Sends ARP to determine if IP is reachable | |
| /// </summary> | |
| /// <param name="ip">IP to check</param> | |
| /// <param name="nic">NIC to send ARP through</param> | |
| /// <returns>True if ARP was successful, false otherwise</returns> | |
| /// <remarks> | |
| /// Replaces IsHostOnLocalNetwork and IsComputerAlive | |
| /// </remarks> | |
| public static bool CanArpSuccessfully(IPAddress ip, IPAddress nic) | |
| { | |
| if (IsLoopback(ip)) return true; | |
| var addr = BitConverter.ToUInt32(ip.GetAddressBytes(), 0); | |
| var nicAddr = BitConverter.ToUInt32(nic.GetAddressBytes(), 0); | |
| uint macLen = 6; | |
| return SendARP((int)addr, (int)nicAddr, new byte[macLen], ref macLen) == 0; | |
| } | |
| /// <summary> | |
| /// Determines if an IP address is a Multicast address | |
| /// </summary> | |
| /// <param name="ip">string containing IP Address</param> | |
| /// <returns>True if ip is multicast, false otherwise</returns> | |
| public static bool IsMulticastIP(string ip) | |
| { | |
| try | |
| { | |
| var octets = ip.Split('.').Select(x => Convert.ToInt32(x)); | |
| if (octets.Count() != 4) return false; | |
| return octets.All(x => Enumerable.Range(0, 256).Contains(x)) && | |
| Enumerable.Range(224, 239).Contains(octets.First()); | |
| } | |
| catch { return false; } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment