How to get MAC address from ip in winsock

By | July 30, 2020

MAC Address

Mac address (Media Access Control Address) or hardware address is a 48 bit (6 character) wide address assigned to a network interface. It is important for the packet delivery between 2 devices like your computer and the router.

Ethernet protocol uses the mac address to deliver it to the right network node. It looks like this 00-1E-58-B8-D4-69 ( the dash is not relevant).

Mac address of any interface can also be changed (called mac spoofing).

Any network packet that needs to travel from a certain ip address to another needs to know the destination ip's mac address.

On windows there is a iphlpapi.dll file which has a function called SendARP which can be used to get the mac address of a given ip address.

Code - Get MAC address (For Visual C++ 6.0)

In Vc++ 6.0 , where iphlpapi.h and iphlpapi.lib are not available , we can create necessary structures and pointers to functions inside iphlpapi.dll file and use them.

/*
	Find mac address of a given IP address using iphlpapi
*/

#include "winsock2.h"
#include "windows.h"
#include "time.h"
#include "stdio.h"

#pragma comment(lib,"ws2_32.lib") //For winsock

#define MAX_ADAPTER_NAME_LENGTH 256
#define MAX_ADAPTER_DESCRIPTION_LENGTH 128
#define MAX_ADAPTER_ADDRESS_LENGTH 8

//Necessary Structs
typedef struct 
{
	char String[4 * 4];
} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;

typedef struct _IP_ADDR_STRING 
{
	struct _IP_ADDR_STRING* Next;
	IP_ADDRESS_STRING IpAddress;
	IP_MASK_STRING IpMask;
	DWORD Context;
} IP_ADDR_STRING , *PIP_ADDR_STRING;

typedef struct _IP_ADAPTER_INFO 
{ 
    struct _IP_ADAPTER_INFO* Next; 
    DWORD           ComboIndex; 
    char            AdapterName[MAX_ADAPTER_NAME_LENGTH + 4]; 
    char            Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4]; 
    UINT            AddressLength; 
    BYTE            Address[MAX_ADAPTER_ADDRESS_LENGTH]; 
    DWORD           Index; 
    UINT            Type; 
    UINT            DhcpEnabled; 
    PIP_ADDR_STRING CurrentIpAddress; 
    IP_ADDR_STRING  IpAddressList; 
    IP_ADDR_STRING  GatewayList; 
    IP_ADDR_STRING  DhcpServer; 
    BOOL            HaveWins; 
    IP_ADDR_STRING  PrimaryWinsServer; 
    IP_ADDR_STRING  SecondaryWinsServer; 
    time_t          LeaseObtained; 
    time_t          LeaseExpires; 
} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;


//Functions
void loadiphlpapi();
void GetMacAddress(unsigned char * , struct in_addr );

//Loads from Iphlpapi.dll
typedef DWORD (WINAPI* psendarp)(struct in_addr DestIP, struct in_addr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen );
typedef DWORD (WINAPI* pgetadaptersinfo)(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen );

int main() 
{
	unsigned char mac[6];
	struct in_addr srcip;
	char ip_address[32];

	WSADATA firstsock;
	
	if (WSAStartup(MAKEWORD(2,2),&firstsock) != 0) 
	{
		printf("\nFailed to initialise winsock.");
		printf("\nError Code : %d",WSAGetLastError());
		return 1;	//Return 1 on error
	}
	
	loadiphlpapi();
	
	//Ask user to select the device he wants to use
	printf("Enter the ip address : ");
	scanf("%s",ip_address);
	srcip.s_addr = inet_addr(ip_address);

	//Get mac addresses of the ip
	GetMacAddress(mac , srcip);
	printf("Selected device has mac address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
	printf("\n");
			
	return 0;
}

//2 functions
psendarp SendArp;
pgetadaptersinfo GetAdaptersInfo;

void loadiphlpapi() 
{
	HINSTANCE hDll = LoadLibrary("iphlpapi.dll");
		
	GetAdaptersInfo = (pgetadaptersinfo)GetProcAddress(hDll,"GetAdaptersInfo");
	if(GetAdaptersInfo==NULL)
	{
		printf("Error in iphlpapi.dll%d",GetLastError());
	}

	SendArp = (psendarp)GetProcAddress(hDll,"SendARP");
	
	if(SendArp==NULL)
	{
		printf("Error in iphlpapi.dll%d",GetLastError());
	}
}

/*
	Get the mac address of a given ip
*/
void GetMacAddress(unsigned char *mac , struct in_addr destip)
{
	DWORD ret;
	struct in_addr srcip;
	ULONG MacAddr[2];
	ULONG PhyAddrLen = 6;  /* default to length of six bytes */
	int i;

	srcip.s_addr=0;

	//Send an arp packet
	ret = SendArp(destip , srcip , MacAddr , &PhyAddrLen);
	
	//Prepare the mac address
	if(PhyAddrLen)
	{
		BYTE *bMacAddr = (BYTE *) & MacAddr;
		for (i = 0; i < (int) PhyAddrLen; i++)
		{
			mac[i] = (char)bMacAddr[i];
		}
	}
}

Output

Enter the ip address : 192.168.0.1
Selected device has mac address : 00-1E-58-B8-D4-69
Press any key to continue

Code - For Visual C++ 2010 Express Edition

On Visual C++ 2010 Express Edition , the iphlpapi.lib and iphlpapi.h files are available so the code is much simpler and shorter.

/*
Find mac address of a given IP address using iphlpapi
*/

#include "winsock2.h"
#include "iphlpapi.h"	//For SendARP
#include "stdio.h"
#include "conio.h"

#pragma comment(lib , "iphlpapi.lib") //For iphlpapi
#pragma comment(lib , "ws2_32.lib") //For winsock

void GetMacAddress(unsigned char * , struct in_addr );

int main() 
{
	unsigned char mac[6];
	struct in_addr srcip;
	char ip_address[32];

	WSADATA firstsock;
	
	if (WSAStartup(MAKEWORD(2,2),&firstsock) != 0) 
	{
		printf("\nFailed to initialise winsock.");
		printf("\nError Code : %d" , WSAGetLastError() );
		return 1;
	}
	
	//Ask user to select the device he wants to use
	printf("Enter the ip address : ");
	scanf_s("%s",ip_address);
	srcip.s_addr = inet_addr(ip_address);

	//Get mac addresses of the ip
	GetMacAddress(mac , srcip);
	printf("Selected device has mac address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
	printf("\n");
	
	_getch();
	return 0;
}

/*
	Get the mac address of a given ip
*/
void GetMacAddress(unsigned char *mac , struct in_addr destip)
{
	DWORD ret;
	IPAddr srcip;
	ULONG MacAddr[2];
	ULONG PhyAddrLen = 6;  /* default to length of six bytes */
	int i;

	srcip = 0;

	//Send an arp packet
	ret = SendARP((IPAddr) destip.S_un.S_addr , srcip , MacAddr , &PhyAddrLen);
	
	//Prepare the mac address
	if(PhyAddrLen)
	{
		BYTE *bMacAddr = (BYTE *) & MacAddr;
		for (i = 0; i < (int) PhyAddrLen; i++)
		{
			mac[i] = (char)bMacAddr[i];
		}
	}
}

Output

Enter the ip address : 192.168.0.101
Selected device has mac address : 02-10-0C-98-E9-E2

Conclusion

The mac address is useful if you are constructing raw packets with Ethernet headers. The ethernet headers are usually added by low level networking libraries in the kernel.

The MAC address is unique for all devices on a network. To find the mac address of all networks on a node you can use some arp utility program. Arp scanner programs can find all machines on a network and their associated ip and mac addresses.

About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

4 Comments

How to get MAC address from ip in winsock
  1. Colson

    when I input ip address like 59.69.123.13(WHICH IS MY FRIENDS’ PC’S IP),the mac address output is CC-CC-CC-CC-CC-CC.

    1. Bruce

      Are you sure that their devices are open? ARP socket packet can’t get response data, thus no information containing the MAC address will be sent to your machine. There’s another reason why you can’t get the true MAC address, that is the router will only send the MAC of itself but not the MAC of your friends’ devices’ MAC addresses.

Leave a Reply

Your email address will not be published. Required fields are marked *