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

Pages: 123
Mar 22, 2013 at 9:54am
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 Mar 22, 2013 at 1:53pm
Mar 22, 2013 at 10:22am
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.
Mar 22, 2013 at 10:29am
so there's no way to get the MAC address?
in a TCP or UDP program?
Mar 22, 2013 at 10:36am
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
Mar 22, 2013 at 10:42am
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?
Mar 22, 2013 at 11:40am
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
Mar 22, 2013 at 11:50am
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?
Mar 22, 2013 at 1:30pm
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 Mar 22, 2013 at 1:31pm
Mar 22, 2013 at 2:58pm
someone please help
Mar 25, 2013 at 9:02am
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
Mar 25, 2013 at 9:38am
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 Mar 25, 2013 at 10:06am
Mar 25, 2013 at 11:55am
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
}
Mar 25, 2013 at 12:14pm
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 Mar 25, 2013 at 12:21pm
Mar 25, 2013 at 12:21pm
yes, the only issue would be speed, but I don't think that it matters. Just check it out
Mar 25, 2013 at 12:30pm
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); 
}
Mar 25, 2013 at 12:41pm
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
Mar 25, 2013 at 12:50pm
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
}
Mar 25, 2013 at 1:16pm
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...
Mar 25, 2013 at 1:31pm
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?
Mar 25, 2013 at 2:30pm
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 Mar 25, 2013 at 2:30pm
Pages: 123