how to get MAC address of another computer and display in a listbox?

Pages: 123
So if you receive a TCP/IP packet you're theoretically able to extract the MAC address? How?

Every packet you get is going to have a destination and source MAC address. If you strip off the layer 3 (TCP/IP) header, you'll be left with the layer 2 header which will contain MAC addresses. It will have the destination (your) MAC address, along with the source which will just be sending device. This doesn't mean it will be the sending host MAC address though. If this packet went through a router, it will be the MAC address for the inside interface of that router.
so what do i need to do?
here is the current code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void CmfcServerDlg:: PrintMACFromIP(const CString &selected_ip_adr)
{
	IP_ADAPTER_INFO AdapterInfo[16];			
	DWORD dwBufLen = sizeof(AdapterInfo);		

	DWORD dwStatus = GetAdaptersInfo(			
		AdapterInfo,							
		&dwBufLen);								
	assert(dwStatus == ERROR_SUCCESS);			

	PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;
	bool found = false;
	do {
		const IP_ADDR_STRING *addr_str = &pAdapterInfo->IpAddressList; 

		if (addr_str != NULL)
		{
			if (selected_ip_adr == addr_str->IpAddress.String)
			{
				PrintMACaddress(pAdapterInfo->Address);
			}              
		}   

		pAdapterInfo = pAdapterInfo->Next; 
		
	}
	while(pAdapterInfo);					
}
replacing the GetAdaptersInfo function with this:
1
2
3
4
5
6

	DWORD SendARP(
		IPAddr DestIP,
		IPAddr SrcIP,
		PULONG pMacAddr,
		PULONG PhyAddrLen );


hasn't help. is there something else i need to add?
Last edited on
please help. i know its so close to working..
well, ARP isn't useful in this case due to the router problem (you don't get the MAC of your computer but ther router)

Have you ever transmitted data from the client to the server using the function send() and recv()?

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740149%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121%28v=vs.85%29.aspx

This is what you have to do:

On the client side:
connect to the server
retrieve the MAC address with the adapter info
send() the MAC address to the server

On the server side:
Wait for a connect (accept)
recv() the MAC address
store the MAC address. I'd recommend using a map

http://cplusplus.com/reference/map/map/?kw=map
this code works. i hope it is the correct why of doing it

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
void CmfcServerDlg::PrintMACFromIP(const CString &selected_ip_adr)
{
	DWORD dwRetVal;
	IPAddr DestIp = 0;
	IPAddr SrcIp = 0;       /* default for src ip */
	ULONG MacAddr[2];       /* for 6-byte hardware addresses */
	ULONG PhysAddrLen = 6;  /* default to length of six bytes */

	char *SrcIpString = NULL;

	BYTE *bPhysAddr;

	DestIp = inet_addr(CT2A(selected_ip_adr));

	memset(&MacAddr, 0xff, sizeof (MacAddr));

	dwRetVal = SendARP(DestIp, SrcIp, &MacAddr, &PhysAddrLen);

	if (dwRetVal == NO_ERROR) {
		bPhysAddr = (BYTE *) & MacAddr;
		if (PhysAddrLen) {
			CString theMac;
			theMac.Format(_T("%.2X-%.2X-%.2X-%.2X-%.2X-%.2X"), (int) bPhysAddr[0],
				(int) bPhysAddr[1],(int) bPhysAddr[2],(int) bPhysAddr[3],(int) bPhysAddr[4],
				(int) bPhysAddr[5]);
			PrintMACaddress(theMac);
		} else
			printf
			("Warning: SendArp completed successfully, but returned length=0\n");

	} else {
		printf("Error: SendArp failed with error: %d", dwRetVal);
		switch (dwRetVal) {
	case ERROR_GEN_FAILURE:
		printf(" (ERROR_GEN_FAILURE)\n");
		break;
	case ERROR_INVALID_PARAMETER:
		printf(" (ERROR_INVALID_PARAMETER)\n");
		break;
	case ERROR_INVALID_USER_BUFFER:
		printf(" (ERROR_INVALID_USER_BUFFER)\n");
		break;
	case ERROR_BAD_NET_NAME:
		printf(" (ERROR_GEN_FAILURE)\n");
		break;
	case ERROR_BUFFER_OVERFLOW:
		printf(" (ERROR_BUFFER_OVERFLOW)\n");
		break;
	case ERROR_NOT_FOUND:
		printf(" (ERROR_NOT_FOUND)\n");
		break;
	default:
		printf("\n");
		break;
		}
	}
}

void CmfcServerDlg::PrintMACaddress(CString& strText)
{
    m_ClientIdList.AddString(strText); 
}
one other problem: i need to clear the listbox when the user clicks another ip address because the MAC address from when the first ip address is still displayed.
i know to delete items from a listbox is m_ClientIdList.ResetContent(); i just don't know where is the correct place to put it
Last edited on
The place would be at the start of OnLbnSelchangeListClientaddr()

You need to be aware that SendARP() will return the wrong ip address when a router comes into play. When you communicate via Internet
You need to be aware that SendARP() will return the wrong ip address when a router comes into play. When you communicate via Internet
is there something else i could use then?
Last edited on
did you ever establish a communication between client and server?

How do you get the ip address from the client?
yes i am using a UDP connection

here is the code i used to create the server:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
int port = 7171;
	if (param)
		port = reinterpret_cast<short>(param);

	SOCKET s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
	if (s == -1)
	{
		closesocket(s);
		return 1;
	}

	sockaddr_in addr_in;
	addr_in.sin_family = AF_INET;
	addr_in.sin_addr.s_addr = INADDR_ANY;
	addr_in.sin_port = htons(port);
	int bind_ret = bind(s, (sockaddr*)&addr_in, sizeof(addr_in));           
	if (bind_ret == -1)
	{
		closesocket(s);
		return 1;
	}


	while (true)
	{
		char buf[1024];
		sockaddr_in client_addr;
		int len = sizeof(client_addr);

		ClientInfo info;

		int n = recvfrom(s, buf, 1024, 0, (struct sockaddr *)&client_addr, &len);

		info.addr = inet_ntoa(client_addr.sin_addr);

        if (n<0) 
		{
			perror("recvfrom");
		}
    
        n = sendto(s, "Got your message\n",17,0,(struct sockaddr *)&client_addr,len);
        if (n<0)
		{
			perror("sendto");
		}


		{
			Mutex<CriticalSection>::Lock lock(client_cs);
			clients.push_back(info);
		}
		
	}

	closesocket(s);
	return 0;
}
So what if the client would send a specific start/end message. Like "Hello"+MAC address as the begin and "Bye" as the end marker?

Currently you push_back() a client anytime you receive something, but what if the same client sends more then just one message?

I'd suggest that you turn clients into a map. The key for this map is the ip address (as a string). And add a member variable that takes the MAC address to your ClientInfo

Whenever you detect that a new client connects to your system (map.find(ip address) == map.end()) you update your listbox (which uses the map)
but the client isn't sending any messages. this isn't a chat application
the reason for this program was to receive the ip and mac address from clients
You can always just write your own message type. Have the sender just put in the MAC address as the payload.
can you show me some code to do that?
Topic archived. No new replies allowed.
Pages: 123