Re: How to retrieve clients MAC address?



If you ping the IP addresss, then the MAC address for that IP will be
stored in an ARP table on your machine. You can see this by typing
"ARP -a" at a command prompt. You can access this table through an API
call to GetIPNetTable() in the IpHlpApi.dll. I'm not sure if the
IP-MAC address will be on your server if someone hits your web
application, but if it's not you can just ping the IP address since you
do have that information and then the MAC should be in the ARP table on
your machine. Here is the C# code needed to pull the MAC out of the
table by IP address.

//Setup
#region GetIpNetTable interop
// The max number of physical addresses.
const int MAXLEN_PHYSADDR = 8;

// Define the MIB_IPNETROW structure.
[StructLayout(LayoutKind.Sequential)]
struct MIB_IPNETROW
{
[MarshalAs(UnmanagedType.U4)]
public int dwIndex;
[MarshalAs(UnmanagedType.U4)]
public int dwPhysAddrLen;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAXLEN_PHYSADDR)]
public byte[] bPhysAddr;
[MarshalAs(UnmanagedType.U4)]
public int dwAddr;
[MarshalAs(UnmanagedType.U4)]
public int dwType;
}

// Declare the GetIpNetTable function.
[DllImport("IpHlpApi.dll")]
[return: MarshalAs(UnmanagedType.U4)]
static extern int GetIpNetTable(
IntPtr pIpNetTable,
[MarshalAs(UnmanagedType.U4)]
ref int pdwSize,
bool bOrder);

// The insufficient buffer error.
const int ERROR_INSUFFICIENT_BUFFER = 122;

#endregion

/// <summary>
/// Pulls the MAC address for a given IP address out of the ARP table
on the machine executing this code.
/// </summary>
/// <param name="ip">IP address to lookup</param>
/// <returns>The MAC address for the given IP address or null if the
MAC is not found.</returns>
public string ResolveMAC(string ip)
{
// The number of bytes needed.
int bytesNeeded = 0;

// The result from the API call.
int result = GetIpNetTable(IntPtr.Zero, ref bytesNeeded, false);

// Call the function, expecting an insufficient buffer.
if (result != ERROR_INSUFFICIENT_BUFFER)
{
// Throw an exception.
throw new Win32Exception(result);
}

// Allocate the memory, do it in a try/finally block, to ensure
// that it is released.
IntPtr buffer = IntPtr.Zero;

try
{
// Allocate the memory.
buffer = Marshal.AllocCoTaskMem(bytesNeeded);

// Make the call again. If it did not succeed, then
// raise an error.
result = GetIpNetTable(buffer, ref bytesNeeded, false);

// If the result is not 0 (no error), then throw an exception.
if (result != 0)
{
// Throw an exception.
throw new Win32Exception(result);
}

// Now we have the buffer, we have to marshal it. We can read
// the first 4 bytes to get the length of the buffer.
int entries = Marshal.ReadInt32(buffer);

// Increment the memory pointer by the size of the int.
IntPtr currentBuffer = new IntPtr(buffer.ToInt64() +
Marshal.SizeOf(new int()));

// Allocate an array of entries.
MIB_IPNETROW[] table = new MIB_IPNETROW[entries];

// Cycle through the entries.
for (int index = 0; index < entries; index++)
{
// Call PtrToStructure, getting the structure information.
table[index] = (MIB_IPNETROW) Marshal.PtrToStructure(new
IntPtr(currentBuffer.ToInt64() + (index *
Marshal.SizeOf(typeof(MIB_IPNETROW)))), typeof(MIB_IPNETROW));
}

byte[] macBytes = null;
for (int i = 0; i < entries; i++)
{
string tableIP = String.Format("{0}.{1}.{2}.{3}",
table[i].dwAddr & 0x000000ff,
(table[i].dwAddr & 0x0000ff00) >> 8,
(table[i].dwAddr & 0x00ff0000) >> 16,
(table[i].dwAddr & 0xff000000) >> 24);

if(tableIP == ip)
{
macBytes = table[i].bPhysAddr;
break;
}
}



string mac = "";

for(int i = 0; i < 6; i++)
{
string hexTet = macBytes[i].ToString("X", new NumberFormatInfo());

if(hexTet.Length == 1)
{
hexTet = "0" + hexTet;
}

mac += hexTet;

if(i < 5)
{
mac += ":";
}

}

return mac;
}
catch
{
return null;
}
finally
{
// Release the memory.
Marshal.FreeCoTaskMem(buffer);
}
}

.



Relevant Pages

  • Re: Translate MAC address to IP address
    ... >> I have some MAC addresses from a local Ethernet segment. ... a broadcast ping to the specified MAC address (not to the broadcast ... This causes an ARP exchange for any such address not ...
    (freebsd-net)
  • Re: [SLE] ethereal
    ... ARP is "address resolution protocol". ... ethernet connections are between hardware or MAC addresses, ... address of your ethernet card -- and obviously (I hope it's obvious ... most often consisting only of your gateway. ...
    (SuSE)
  • Re: Problem with Bridging ... and bge devices under FreeBSD 7.x?
    ... while arp -a also shows the 52:54 MAC, although MACs for the ifconfig -a are, ... Can you ping from A to C? ...
    (freebsd-net)
  • Re: Problem with Bridging ... and bge devices under FreeBSD 7.x?
    ... while arp -a also shows the 52:54 MAC, although MACs for the ifconfig -a are, ... Can you ping from A to C? ...
    (freebsd-stable)
  • Re: Pure IP & ARP broadcasts
    ... It actually communicates via the MAC address of the Nics (aka Layer2 ... what the ARP request does. ... A host has a packet to send, it has the IP# and nothing else. ... But if the owner of the IP# is not on that segment then the Router replies ...
    (microsoft.public.windows.server.networking)