Showing posts with label ARP. Show all posts
Showing posts with label ARP. Show all posts

Sunday, August 28, 2016

Get IP address by MAC address in C#. Updating ARP table.

Recently I have written article about getting IP address of connected to the network device using it MAC address, you can find it using the following link Get IP address by MAC address in C#. It seemed to me that the solution was good until I figured out that it requires some time for ARP table being updated.
To reproduce such situation you just need to reboot your computer or execute command:
arp -d

Run cmd.exe as administrator, type command text and hit enter. Now the code provided in the previous article does not work as expected.

Fixing the issue


The device should be on the same sub-network as running computer. So we need to ping all the IP addresses int the sub-network, e.g. (192.168.1.1 - 192.168.1.255) to update the ARP table. I have updated IpFinder class with necessary code.

IpFinder.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace SftpDownloader.Core
{
    public class IpFinder
    {
        public string FindIpAddressByMacAddress(string macAddress, string currentIpAddress)
        {
            Parallel.ForEach(GetListOfSubnetIps(currentIpAddress), delegate (string s)
            {
                DeviceScanner.IsHostAccessible(s);
            });

            var arpEntities = new ArpHelper().GetArpResult();
            var ip = arpEntities.FirstOrDefault(
                a => string.Equals(
                    a.MacAddress,
                    macAddress,
                    StringComparison.CurrentCultureIgnoreCase))?.Ip;

            return ip;
        }

        private List<string> GetListOfSubnetIps(string currentIp)
        {
            var a = currentIp.Split('.');
            var lst = new List<string>();

            for (int i = 1; i <= 255; i++)
            {
                lst.Add($"{a[0]}.{a[1]}.{a[2]}.{i}");
            }

            lst.Remove(currentIp);

            return lst;
        }
    }
}

DeviceScanner.cs


using System.Net.NetworkInformation;

namespace SftpDownloader.Core
{
    public class DeviceScanner
    {
        public static bool IsHostAccessible(string hostNameOrAddress)
        {
            Ping ping = new Ping();
            PingReply reply = ping.Send(hostNameOrAddress, 1000);

            return reply != null && reply.Status == IPStatus.Success;
        }
    }
}

Monday, August 15, 2016

Get IP address by MAC address in C#

Sometimes it happens that you need to access device in the network by IP address. But unfortunately, it is not every time possible, e.g the device does not have static IP. In such case you can use device's MAC address to find it in the network.

Address Resolution Protocol 

Displays and modifies entries in the Address Resolution Protocol (ARP) cache, which contains one or more tables that are used to store IP addresses and their resolved Ethernet or Token Ring physical addresses. There is a separate table for each Ethernet or Token Ring network adapter installed on your computer.
So we are going to use following arp-command to get all the entries and filter them by specified MAC address.

arp -a

For more option use following link ARP Documentation.

.NET implementation


ArpEntity.cs


namespace ArpExample
{
    public class ArpEntity
    {
        public string Ip { get; set; }

        public string MacAddress { get; set; }

        public string Type { get; set; }
    }
}

ArpHelper.cs


using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;

namespace ArpExample
{
    public class ArpHelper
    {
        public List<ArpEntity> GetArpResult()
        {
            var p = Process.Start(new ProcessStartInfo("arp", "-a")
            {
                CreateNoWindow = true,
                UseShellExecute = false,
                RedirectStandardOutput = true
            });

            var output = p?.StandardOutput.ReadToEnd();
            p?.Close();

            return ParseArpResult(output);
        }

        private List<ArpEntity> ParseArpResult(string output)
        {
            var lines = output.Split('\n').Where(l => !string.IsNullOrWhiteSpace(l));

            var result =
                (from line in lines
                 select Regex.Split(line, @"\s+")
                    .Where(i => !string.IsNullOrWhiteSpace(i)).ToList()
                    into items
                 where items.Count == 3
                 select new ArpEntity()
                 {
                     Ip = items[0],
                     MacAddress = items[1],
                     Type = items[2]
                 });

            return result.ToList();
        }
    }
}

IpFinder.cs


using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace ArpExample
{
    public class IpFinder
    {
        public string FindIpAddressByMacAddress(string macAddress)
        {
            List<ArpEntity> arpEntities = new ArpHelper().GetArpResult();

            return arpEntities.FirstOrDefault(a => a.MacAddress == macAddress)?.Ip;
        }
    }
}

Troubleshooting 

Recently I figured out that the solution described in the article sometimes might fail. I wrote the article with the fix. Please find it using the link Get IP address by MAC address in C#. Updating ARP table