How to get a Mac-Address from a local network IP using . NET Core on Linux?

Asked

Viewed 619 times

4

I already have tools that can identify the Mac-Address of my network devices, since the 'server' or the application is running on Windows and . NET Framework.

I’ve been using the following:

using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Yordi.Ferramentas
{
    /// <summary>
    /// Ferramentas para rede local
    /// </summary>
    public static class Rede
    {
        private static string _erro;
        public static string ErrorMessage { get { return _erro; } }
        [DllImport("iphlpapi.dll", ExactSpelling = true)]
        public static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen);
        /// <summary>
        /// Recupera o MAC Address de um equipamento na rede local baseado em seu IP
        /// </summary>
        /// <param name="ip">IP em formato string (Ex: 192.168.0.10)</param>
        /// <returns>String com o MAC Address no formato XX-XX-XX-XX-XX</returns>
        public static string TryGetMacAddress(string ip)
        {
            try
            {
                IPAddress IP = IPAddress.Parse(ip);
                byte[] macAddr = new byte[6];
                uint macAddrLen = (uint)macAddr.Length;
                if (SendARP((int)IP.Address, 0, macAddr, ref macAddrLen) != 0)
                {
                    _erro = "Não foi possível executar comando ARP";
                    return String.Empty;
                }
                string[] str = new string[(int)macAddrLen];
                for (int i = 0; i < macAddrLen; i++)
                    str[i] = macAddr[i].ToString("x2");
                return string.Join("-", str);
            }
            catch (Exception e)
            {
                _erro = e.Message;
            }
            return String.Empty;
        }
        /// <summary>
        /// Dado um ip que pertença a mesma rede, o MAC Address será dado 
        /// </summary>
        /// <param name="ip">IP que pertença à rede</param>
        /// <returns>string com os bytes separados por hífen</returns>
        public static string GetMyMacAddress(string ip)
        {
            NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface adapter in nics)
            {
                foreach (UnicastIPAddressInformation unip in adapter.GetIPProperties().UnicastAddresses)
                {
                    if (unip.Address.AddressFamily == AddressFamily.InterNetwork)
                    {
                        if (unip.Address.ToString() == ip)
                        {
                            PhysicalAddress address = adapter.GetPhysicalAddress();
                            return BitConverter.ToString(address.GetAddressBytes());
                        }
                    }
                }
            }
            return null;
        }
    }
}

The way to get the Mac-Address from the machine itself is to use the Networkinterface class of . NET (in use in the Getmymacaddress(ip string) method). To try to get the Mac-Address from another device on the local network is by using the command arp.
To call it in Windows I have to import a dll from the system: [DllImport("iphlpapi.dll", ExactSpelling = true)] I refer to it: public static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen); And the use here: SendARP((int)IP.Address, 0, macAddr, ref macAddrLen)

How I’m porting the application to. NET Core, to run on a Raspberry PI 3 on Linux, I want to know how to do the same process on Linux (if this is the right way to do on this system).

The Networkinterface class also exists in . NET Core, under the namespace System.Net.Networkinformation.

But how to get Mac-Address from an IP from another machine (on Linux with . NET Core)?

1 answer

2


Friend, please do not know how to answer on . NET but in linux you can discover the mac from an ip with the command arping.

Syntax: arping -S -w2000 -i -C1 -R -r | Tail -n1

arping -S 192.168.0.8 192.168.0.170 -w2000 -i eth0 -C1 -R -r | tail -n1

Where "IP1" is the ip of the machine that is sending the request, and IP2 is the target machine. With the above syntax you will have the result below

9c:2a:83:21:4e:91 192.168.0.170

Read the link below to adjust the command according to your need.

https://github.com/ThomasHabets/arping

Create an auxiliary class as follows:

using System;
using System.Diagnostics;
    public static class ShellHelper
    {
        public static string Bash(this string cmd)
        {
            var escapedArgs = cmd.Replace("\"", "\\\"");

            var process = new Process()
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = "/bin/bash",
                    Arguments = $"-c \"{escapedArgs}\"",
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                }
            };
            process.Start();
            string result = process.StandardOutput.ReadToEnd();
            process.WaitForExit();
            return result;
        }
    }

Now you can execute any command in bash as follows

var output = "arping -S 192.168.0.8 192.168.0.170 -w2000 -i eth0 -C1 -R -r | tail -n1".Bash();

That should work.

  • From what I read, the 'Arp' commands in Linux are relatively similar to those in Windows. But to send these commands in . NET Core, I need to identify which OS library to call. Under Windows is iphlpapi.dll. Under Linux is the same principle? Is there a library that handles network commands that I can refer to or call? Or is it another way, as if the command shell is responsible for locating and forwarding these commands?

  • I’ll edit my answer, stop getting better to understand.

  • Perfect!! I made some adjustments to use the common 'Arp' because, sorry for that, I don’t know how to install the arping in Raspberry. But the concept was fundamental. I don’t want to draw attention to another answer, since this was enough. But for those who want more details, I posted some methods here [https://stackoverflow.com/a/47022680/1873402]. I think I made the proper and deserved reference at the beginning.

  • Ball show you got. arping has the same concept of ping, only instead of using the icmp protocol it uses Arp protocol. I suggest that one more insisted on arping, because it has hosts that for security block the Arp protocol. From a look at the for on it https://github.com/ThomasHabets/arping

  • A friend is having a huge difficulty doing exactly that proposed in the topic, but without using arping or bash.. told him to use Unmanaged code and C.. :| some idea ?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.