Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / C#
Tip/Trick

Retrieving IP and MAC addresses for a LAN

Rate me:
Please Sign up or sign in to vote.
4.85/5 (24 votes)
2 Apr 2012CPOL 148.8K   31   38
Getting the IP and MAC for your PC is pretty simple, but what if you need those on your local network? It's not as simple as it sounds...

Introduction

Getting the IP and MAC for your PC is pretty simple, but what if you need those on your local network? It's not as simple as it sounds... in fact it's a complete pain, and most of the internet articles that Google finds return the MAC for the current PC only. This returns the network list. 

Using the code

C#
// Get my PC IP address
Console.WriteLine("My IP : {0}", GetIPAddress());
// Get My PC MAC address
Console.WriteLine("My MAC: {0}", GetMacAddress());
// Get all devices on network
Dictionary<IPAddress, PhysicalAddress> all = GetAllDevicesOnLAN();
foreach (KeyValuePair<IPAddress, PhysicalAddress> kvp in all)
{
    Console.WriteLine("IP : {0}\n MAC {1}", kvp.Key, kvp.Value);
}

The code that does the work

C#
/// <summary>
/// MIB_IPNETROW structure returned by GetIpNetTable
/// DO NOT MODIFY THIS STRUCTURE.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
struct MIB_IPNETROW
{
    [MarshalAs(UnmanagedType.U4)]
    public int dwIndex;
    [MarshalAs(UnmanagedType.U4)]
    public int dwPhysAddrLen;
    [MarshalAs(UnmanagedType.U1)]
    public byte mac0;
    [MarshalAs(UnmanagedType.U1)]
    public byte mac1;
    [MarshalAs(UnmanagedType.U1)]
    public byte mac2;
    [MarshalAs(UnmanagedType.U1)]
    public byte mac3;
    [MarshalAs(UnmanagedType.U1)]
    public byte mac4;
    [MarshalAs(UnmanagedType.U1)]
    public byte mac5;
    [MarshalAs(UnmanagedType.U1)]
    public byte mac6;
    [MarshalAs(UnmanagedType.U1)]
    public byte mac7;
    [MarshalAs(UnmanagedType.U4)]
    public int dwAddr;
    [MarshalAs(UnmanagedType.U4)]
    public int dwType;
}

/// <summary>
/// GetIpNetTable external method
/// </summary>
/// <param name="pIpNetTable"></param>
/// <param name="pdwSize"></param>
/// <param name="bOrder"></param>
/// <returns></returns>
[DllImport("IpHlpApi.dll")]
[return: MarshalAs(UnmanagedType.U4)]
static extern int GetIpNetTable(IntPtr pIpNetTable, 
      [MarshalAs(UnmanagedType.U4)] ref int pdwSize, bool bOrder);

/// <summary>
/// Error codes GetIpNetTable returns that we recognise
/// </summary>
const int ERROR_INSUFFICIENT_BUFFER = 122;
/// <summary>
/// Get the IP and MAC addresses of all known devices on the LAN
/// </summary>
/// <remarks>
/// 1) This table is not updated often - it can take some human-scale time 
///    to notice that a device has dropped off the network, or a new device
///    has connected.
/// 2) This discards non-local devices if they are found - these are multicast
///    and can be discarded by IP address range.
/// </remarks>
/// <returns></returns>
private static Dictionary<IPAddress, PhysicalAddress> GetAllDevicesOnLAN()
{
    Dictionary<IPAddress, PhysicalAddress> all = new Dictionary<IPAddress, PhysicalAddress>();
    // Add this PC to the list...
    all.Add(GetIPAddress(), GetMacAddress());
    int spaceForNetTable = 0;
    // Get the space needed
    // We do that by requesting the table, but not giving any space at all.
    // The return value will tell us how much we actually need.
    GetIpNetTable(IntPtr.Zero, ref spaceForNetTable, false);
    // Allocate the space
    // We use a try-finally block to ensure release.
    IntPtr rawTable = IntPtr.Zero;
    try
    {
        rawTable = Marshal.AllocCoTaskMem(spaceForNetTable);
        // Get the actual data
        int errorCode = GetIpNetTable(rawTable, ref spaceForNetTable, false);
        if (errorCode != 0)
        {
            // Failed for some reason - can do no more here.
            throw new Exception(string.Format(
              "Unable to retrieve network table. Error code {0}", errorCode));
        }
        // Get the rows count
        int rowsCount = Marshal.ReadInt32(rawTable);
        IntPtr currentBuffer = new IntPtr(rawTable.ToInt64() + Marshal.SizeOf(typeof(Int32)));
        // Convert the raw table to individual entries
        MIB_IPNETROW[] rows = new MIB_IPNETROW[rowsCount];
        for (int index = 0; index < rowsCount; index++)
        {
            rows[index] = (MIB_IPNETROW)Marshal.PtrToStructure(new IntPtr(currentBuffer.ToInt64() +
                                        (index * Marshal.SizeOf(typeof(MIB_IPNETROW)))
                                       ),
                                        typeof(MIB_IPNETROW));
        }
        // Define the dummy entries list (we can discard these)
        PhysicalAddress virtualMAC = new PhysicalAddress(new byte[] { 0, 0, 0, 0, 0, 0 });
        PhysicalAddress broadcastMAC = new PhysicalAddress(new byte[] { 255, 255, 255, 255, 255, 255 });
        foreach (MIB_IPNETROW row in rows)
        {
            IPAddress ip = new IPAddress(BitConverter.GetBytes(row.dwAddr));
            byte[] rawMAC = new byte[] { row.mac0, row.mac1, row.mac2, row.mac3, row.mac4, row.mac5 };
            PhysicalAddress pa = new PhysicalAddress(rawMAC);
            if (!pa.Equals(virtualMAC) && !pa.Equals(broadcastMAC) && !IsMulticast(ip))
            {
                //Console.WriteLine("IP: {0}\t\tMAC: {1}", ip.ToString(), pa.ToString());
                if (!all.ContainsKey(ip))
                {
                    all.Add(ip, pa);
                }
            }
        }
    }
    finally
    {
        // Release the memory.
        Marshal.FreeCoTaskMem(rawTable);
    }
    return all;
}

/// <summary>
/// Gets the IP address of the current PC
/// </summary>
/// <returns></returns>
private static IPAddress GetIPAddress()
{
    String strHostName = Dns.GetHostName();
    IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
    IPAddress[] addr = ipEntry.AddressList;
    foreach (IPAddress ip in addr)
    {
        if (!ip.IsIPv6LinkLocal)
        {
            return (ip);
        }
    }
    return addr.Length > 0 ? addr[0] : null;
}

/// <summary>
/// Gets the MAC address of the current PC.
/// </summary>
/// <returns></returns>
private static PhysicalAddress GetMacAddress()
{
    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
    {
        // Only consider Ethernet network interfaces
        if (nic.NetworkInterfaceType == NetworkInterfaceType.Ethernet &&
            nic.OperationalStatus == OperationalStatus.Up)
        {
            return nic.GetPhysicalAddress();
        }
    }
    return null;
}

/// <summary>
/// Returns true if the specified IP address is a multicast address
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
private static bool IsMulticast(IPAddress ip)
{
    bool result = true;
    if (!ip.IsIPv6Multicast)
    {
        byte highIP = ip.GetAddressBytes()[0];
        if (highIP < 224 || highIP > 239)
        {
            result = false;
        }
    }
    return result;
}

History

Original version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO
Wales Wales
Born at an early age, he grew older. At the same time, his hair grew longer, and was tied up behind his head.
Has problems spelling the word "the".
Invented the portable cat-flap.
Currently, has not died yet. Or has he?

Comments and Discussions

 
QuestionIPs from Repeater Pin
Member 1132669312-Feb-19 3:45
Member 1132669312-Feb-19 3:45 
QuestionRetrieve only computers mac addresses and not router mac address? Pin
MomciloM13-Sep-18 16:37
MomciloM13-Sep-18 16:37 
QuestionFor everyone who wants a source code for a program like wnetwatcher and angry scanner (WiFi Scanner) Pin
Member 1303711810-Oct-17 18:45
professionalMember 1303711810-Oct-17 18:45 
QuestionProblem: Code only finding the computer that the program is running on. Pin
Member 118496914-Dec-15 14:51
Member 118496914-Dec-15 14:51 
AnswerRe: Problem: Code only finding the computer that the program is running on. Pin
BornToBeRoot21-Mar-17 2:57
BornToBeRoot21-Mar-17 2:57 
QuestionOWN MAC Pin
Jeddi khan24-Mar-15 9:07
Jeddi khan24-Mar-15 9:07 
AnswerRe: OWN MAC Pin
Siderite Zackwehdex14-Jul-15 16:52
Siderite Zackwehdex14-Jul-15 16:52 
QuestionIs it possible to disable/enable any system in LAN using MAC address? Pin
Member 866666911-Aug-14 0:55
Member 866666911-Aug-14 0:55 
AnswerRe: Is it possible to disable/enable any system in LAN using MAC address? Pin
OriginalGriff11-Aug-14 1:15
mveOriginalGriff11-Aug-14 1:15 
GeneralRe: Is it possible to disable/enable any system in LAN using MAC address? Pin
Member 866666911-Aug-14 1:40
Member 866666911-Aug-14 1:40 
QuestionFind static IP of all system in a LAN Pin
Member 866666910-Aug-14 23:54
Member 866666910-Aug-14 23:54 
AnswerRe: Find static IP of all system in a LAN Pin
OriginalGriff10-Aug-14 23:56
mveOriginalGriff10-Aug-14 23:56 
GeneralRe: Find static IP of all system in a LAN Pin
Member 866666911-Aug-14 0:41
Member 866666911-Aug-14 0:41 
GeneralRe: Find static IP of all system in a LAN Pin
Jeddi khan24-Mar-15 8:46
Jeddi khan24-Mar-15 8:46 
QuestionCan you do this in Visual Studio? Pin
Member 1049386323-Feb-14 5:23
Member 1049386323-Feb-14 5:23 
AnswerRe: Can you do this in Visual Studio? Pin
OriginalGriff23-Feb-14 5:30
mveOriginalGriff23-Feb-14 5:30 
QuestionC# or C++? Pin
Joe Sweeney17-Sep-13 15:09
Joe Sweeney17-Sep-13 15:09 
AnswerRe: C# or C++? Pin
PIEBALDconsult17-Sep-13 16:24
mvePIEBALDconsult17-Sep-13 16:24 
AnswerRe: C# or C++? Pin
OriginalGriff17-Sep-13 21:50
mveOriginalGriff17-Sep-13 21:50 
GeneralRe: C# or C++? Pin
Joe Sweeney10-Jan-14 8:18
Joe Sweeney10-Jan-14 8:18 
GeneralRe: C# or C++? Pin
OriginalGriff10-Jan-14 8:36
mveOriginalGriff10-Jan-14 8:36 
AnswerRe: C# or C++? Pin
Jeddi khan24-Mar-15 9:06
Jeddi khan24-Mar-15 9:06 
QuestionRetrieving IP and MAC addresses for a LAN Pin
Member 1008603430-May-13 23:01
Member 1008603430-May-13 23:01 
AnswerRe: Retrieving IP and MAC addresses for a LAN Pin
OriginalGriff30-May-13 23:21
mveOriginalGriff30-May-13 23:21 
GeneralRe: Retrieving IP and MAC addresses for a LAN Pin
Member 1008603430-May-13 23:58
Member 1008603430-May-13 23:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.