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

Pages: 123
I have a client server program using UPD created in MFC. In the server there are two listboxes. The first one displays the ip addresses of the connected clients.
I want the second listbox to display the MAC address when i click the ip address from the listbox.

So how can I display the MAC address of the client by clicking the ip address in the first listbox?
also would it be better to use the ip address control the toolbox in visual studios provides or is a listbox ok?
Last edited on
The MAC address, by TCP/IP standards, is never communicated outside of the local-area network to which it pertains -- routers beyond that LAN don't even get the information you're trying to record.
so there's no way to get the MAC address?
in a TCP or UDP program?
is your question about getting the MAC address or about the GUI to represent it?

You can get the MAC address with IP_ADAPTER_INFO. See
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366062%28v=vs.85%29.aspx

example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  CBuffer result;

  IP_ADAPTER_INFO adapter_info[16];       // Allocate information
                                         // for up to 16 NICs
  DWORD buf_len = sizeof(adapter_info);  // Save memory size of buffer

  const DWORD status = GetAdaptersInfo(      // Call Getadapter_info
    adapter_info,                 // [out] buffer to receive data
    &buf_len);                  // [in] size of receive data buffer

  if(ERROR_SUCCESS == status)  // Verify return value is
  {                                      // valid, no buffer overflow
    for(PIP_ADAPTER_INFO ai = adapter_info; ai != null; ai = ai->Next)
    {
      if(MIB_IF_TYPE_ETHERNET == ai->Type)
      { // At this point you know it's an ethernet adapter. Now you can check if it's the ip-address you want via 'CurrentIpAddress' 
        result.SetData(ai->Address, ai->AddressLength);
        break;
      }
    }
  }
  return result;


So how can I display the MAC address of the client by clicking the ip address in the first listbox?
also would it be better to use the ip address control the toolbox in visual studios provides or is a listbox ok?
This depends on how your GUI is organized. You may also consider a combobox
i asked 2 questions, sorry if i wasn't clear enough.
yes i want to get the MAC address - thanks for the code
then i want to display it in the second listbox when i click the ip address from the first list box.

This depends on how your GUI is organized

what do you mean by this?

if listbox is not a good option then should a use a textbox or ip address control?
what do you mean by this?
You don't know what 'organized' mean?


What kind of gui element you use depends on what you want to do with the data.

then i want to display it in the second listbox when i click the ip address from the first list box.
If that is what you want then do it.

Or are you asking whether it's feasible? Yes it is
its a simple GUI with 2 listboxes - one for the ip addresses one for the mac address.

yes i know its feasible but how is it done?
does the code to find the mac address go into the event handler for the listbox?
so i used this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
IP_ADAPTER_INFO AdapterInfo[16];			// Allocate information for up to 16 NICs
	DWORD dwBufLen = sizeof(AdapterInfo);		// Save the memory size of buffer

	DWORD dwStatus = GetAdaptersInfo(			// Call GetAdapterInfo
		AdapterInfo,							// [out] buffer to receive data
		&dwBufLen);								// [in] size of receive data buffer
	assert(dwStatus == ERROR_SUCCESS);			// Verify return value is valid, no buffer overflow

	PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;// Contains pointer to current adapter info
	do {
		PrintMACaddress(pAdapterInfo->Address);	// Print MAC address
		pAdapterInfo = pAdapterInfo->Next;		// Progress through linked list
	}
	while(pAdapterInfo);						// Terminate if last adapter
}


and i just put this code in a button event handler (just for testing)

now what do i do to make the mac address appear when i click an ip address from the first listbox?
also when i press the button it displays the current computer's mac address so how do i change it so get the mac of the ip address i click?
Last edited on
someone please help
I'm not too sure what your problem is.

What you need is to find the MAC address that correlates with the ip address. Please follow the link above. You will find certain members of the IP_ADAPTER_INFO struct. There's also an additional example.

now what do i do to make the mac address appear when i click an ip address from the first listbox?
You need to compare the selected ip address from your ip listbox with the ip address(es) from the pAdapterInfo. If you have a match you add the MAC address to the MAC listbox

also when i press the button it displays the current computer's mac address so how do i change it so get the mac of the ip address i click?
It's nearly the same as getting the ip address, jut compare the MAC addresses and you have the ip addresses.

It's all there you just have to add a few lines
I'm not too sure what your problem is.
the problem is how to get the MAC address of another computer

the link you provided contains a lot of code and i am not sure what code to add. i understand that i need to compare i just don't know how.

It's all there you just have to add a few lines
can you show me these lines?
Last edited on
Something like this:
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
bool GetMACFromIP(BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH], const std::string &selected_ip_adr)
{
IP_ADAPTER_INFO AdapterInfo[16];			// Allocate information for up to 16 NICs
	DWORD dwBufLen = sizeof(AdapterInfo);		// Save the memory size of buffer

	DWORD dwStatus = GetAdaptersInfo(			// Call GetAdapterInfo
		AdapterInfo,							// [out] buffer to receive data
		&dwBufLen);								// [in] size of receive data buffer
	assert(dwStatus == ERROR_SUCCESS);			// Verify return value is valid, no buffer overflow

	PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;// Contains pointer to current adapter info
	bool found = false;
	do {
		const IP_ADDR_STRING *addr_str = &pAdapterInfo->IpAddressList; // use the address list instead of CurrentIpAddress (which is often NULL)
		while(addr_str != null)
		{
		  if(selected_ip_adr == addr_str->IpAddress.String) // This compares the selected ip address with an associated Adapter ip address
		  {
		    found = true;
		    break;
		  }
		}
		if(found)
		{
		  memcpy(Address, pAdapterInfo->Address, MAX_ADAPTER_ADDRESS_LENGTH); // copy the adapters MAC address
		  break;
		}
		else
		  pAdapterInfo = pAdapterInfo->Next;		// Progress through linked list
	}
	while(pAdapterInfo);						// Terminate if last adapter
	return found; // This determines whether the provided ip address is associated with a MAC address
}
thanks for the code. can i call this function from the list box event handler?
1
2
3
4
void CmfcServerDlg::OnLbnSelchangeListClientaddr()
{
     //function here?
}

also you didn't put the line PrintMACaddress(pAdapterInfo->Address); int the code so where in the code should the MAC address be printed?
Last edited on
yes, the only issue would be speed, but I don't think that it matters. Just check it out
ok i put bool GetMACFromIP(BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH], const std::string &selected_ip_adr); into the list box event handler.

but i need to put the line PrintMACaddress(pAdapterInfo->Address); into the code so it prints the MAC address but i get the compile error error C3861: 'PrintMACaddress': identifier not found

this is the print MAC function and it worked in the old code so i don't know why its causing a problem now
1
2
3
4
5
6
void CmfcServerDlg::PrintMACaddress(unsigned char MACData[])
{
   CString strText;
strText.Format("%02X-%02X-%02X-%02X-%02X-%02X\n",MACData[0], MACData[1], MACData[2], MACData[3], MACData[4], MACData[5]);
       m_ClientIdList.AddString(strText); 
}
The reason is this

void CmfcServerDlg::PrintMACaddress(unsigned char MACData[])

PrintMACaddress is part of that class. You have at least 2 options:

1. remove PrintMACaddress from the class (as a global function)
2. make GetMACFromIP part of that class

By the way: you may CString instead of std::string. That may be no difference
i added GetMACFromIP to the class:
bool CmfcServerDlg::GetMACFromIP(BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH], const std::string &selected_ip_adr)

but i am not sure where to put PrintMACaddress(pAdapterInfo->Address); in the code. nothing happens when i click the ip address

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
bool CmfcServerDlg::GetMACFromIP(BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH], const std::string &selected_ip_adr)
{
IP_ADAPTER_INFO AdapterInfo[16];			// Allocate information for up to 16 NICs
	DWORD dwBufLen = sizeof(AdapterInfo);		// Save the memory size of buffer

	DWORD dwStatus = GetAdaptersInfo(			// Call GetAdapterInfo
		AdapterInfo,							// [out] buffer to receive data
		&dwBufLen);								// [in] size of receive data buffer
	assert(dwStatus == ERROR_SUCCESS);			// Verify return value is valid, no buffer overflow

	PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;// Contains pointer to current adapter info
	bool found = false;
	do {
		const IP_ADDR_STRING *addr_str = &pAdapterInfo->IpAddressList; // use the address list instead of CurrentIpAddress (which is often NULL)
		while(addr_str != NULL)
		{
		  if(selected_ip_adr == addr_str->IpAddress.String) // This compares the selected ip address with an associated Adapter ip address
		  {
		    found = true;
		    break;
		  }
		}
		if(found)
		{
		  memcpy(Address, pAdapterInfo->Address, MAX_ADAPTER_ADDRESS_LENGTH); // copy the adapters MAC address
		  PrintMACaddress(pAdapterInfo->Address);
		  break;
		}
		else
		  pAdapterInfo = pAdapterInfo->Next;		// Progress through linked list
			PrintMACaddress(pAdapterInfo->Address);
	}
	while(pAdapterInfo);						// Terminate if last adapter
	return found; // This determines whether the provided ip address is associated with a MAC address
}
my original function was designed to be stand alone. If you want to use it like so you may rename GetMACFromIP like so:

void CmfcServerDlg::PrintMACFromIP(const std::string &selected_ip_adr)

remove line 25 and 31


So did you check if PrintMACaddress works at all? MFC is often tricky to use.
Also the provided ip address might not exists within the adapter.
This would be good time to start debugging...
yes PrintMACaddress just work with the old code i had.

could I just add a line of code in GetMACFromIP to print the MAC address instead of having a separate function? would that work?
could I just add a line of code in GetMACFromIP to print the MAC address instead of having a separate function? would that work?
yes.

you may add (just for debugging purposes) after line 16:

m_ClientIdList.AddString(addr_str->IpAddress.String); // Just to see what ip addresses the adapter has!

You know that IP_ADAPTER_INFO contains all the things of your system network settings. Just go and play with it. For instance print after line 13

m_ClientIdList.AddString(pAdapterInfo->AdapterName);


That might give you more of an idea what you're doing.
Last edited on
Pages: 123