Определение MAC-адреса

Для определения MAC-адреса удалённого компьютера можно использовать NetBios:
NCB SNcb;     // Структура для работы с NetBios
UCHAR rc = 0;     //Код возврата
UCHAR Status[256]; // Буфер для получения данных
UCHAR HostName[]=_T("SomeHost"); // Имя удалённого компа
BYTE MAC[6];    //Буфер для нашего MAC-адреса.

memset( &SNcb, 0, sizeof(SNcb) );
SNcb.ncb_command = NCBRESET;
SNcb.ncb_lana_num = 0;
rc=Netbios( &SNcb ); //Сбрасываем NetBios

//Если HostName вдруг больше 15 символов его надо обрезать.
while( lstrlen(HostName) - 15)
   
lstrcat(HostName, " ");

memset(&SNcb, 0, sizeof(NCB));
SNcb.ncb_command = NCBASTAT;
SNcb.ncb_buffer = (unsigned char*)Status;
SNcb.ncb_length = 256;
lstrcpy((char*)SNcb.ncb_callname, HostName);
SNcb.ncb_lana_num = 0;    //Сетевой адаптор по умалчанию
rc = Netbios( &SNcb );
if(rc==NRC_GOODRET) //Если всё ОК
memcpy(MAC, Status, 6);
Declared in Nb30.h
Use Netapi32.lib


НО! На машине NetBios может быть и выключен. Тогда можно вытащить его из таблицы IPMAC если хост вообще использует IP-протокол. Технология следующая: мы посыалем хосту любой IP-пакет, например по UDP. Система обязательно широковещательным ARP-пакетом запросит его MAC-адрес и если получит, занесёт его в таблицу IPMAC. Откуда мы его и заберём. Абсолютно неважно, какой IP-based протокол будет использован, и будет ли он установлен и/или принят удалённым хостом. Важно лишь то, что система захочет отослать IP-пакет, а для этого она обязательно должна узнать его MAC.
Пример консольного приложения:
//--------stdafx.h-------- 
#include <stdio.h>
#include <windows.h>
#include <Winsock2.h>
//Use Ws2_32.lib
#include <Iphlpapi.h>
//Use Iphlpapi.lib (in SDK)
////====================

////-------- cpp-файл ----------

#include "stdafx.h"
char ip[]="192.168.100.1";

int main(int argc, char* argv[])
{
//Будем использовать сокеты
   
WSADATA WsaData;
   
DWORD _ip=inet_addr(ip);
   
if (WSAStartup(0x0202, &WsaData)==NULL)    
       
printf("WSA Starup OK!\n");

//Создаём UDP-сокет и отсылаем по нему любые данные
   
SOCKET udp_s;
   
SOCKADDR_IN udp_sin;
   
udp_s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
   
if(udp_s!=SOCKET_ERROR)
   {
       
udp_sin.sin_family = AF_INET;
       
udp_sin.sin_port = htons(5232); //Шлём на любой порт.
       
udp_sin.sin_addr.s_addr = _ip;
       
if(sendto(udp_s, "TEST", 5, NULL, (SOCKADDR*)&udp_sin, sizeof(udp_sin))>0)
       {
//Пакет отослан. Вытаскиваем MAC-адрес из системы
           
MIB_IPNETTABLE * pIpNetTable = (MIB_IPNETTABLE *) new char[0xFFFF];
           
ULONG cbIpNetTable = 0xFFFF;
           
if (NO_ERROR == GetIpNetTable (pIpNetTable, &cbIpNetTable, TRUE))
           {
               
for (DWORD i = 0; i < pIpNetTable->dwNumEntries; i++)
               {
                   
if(pIpNetTable->table[i].dwAddr==_ip&&pIpNetTable->table[i].dwType!=2)
                   {
                       
printf("IP:%s MAC:%X-%X-%X-%X-%X-%X\n", ip,
                                   
pIpNetTable->table[i].bPhysAddr[0],
                                   
pIpNetTable->table[i].bPhysAddr[1],
                                   
pIpNetTable->table[i].bPhysAddr[2],
                                   
pIpNetTable->table[i].bPhysAddr[3],
                                   
pIpNetTable->table[i].bPhysAddr[4],
                                   
pIpNetTable->table[i].bPhysAddr[5]);
                                   
delete[] pIpNetTable;
                                   
closesocket(udp_s);
                        
WSACleanup();
                        
return 0;
                   }
            }
            
printf("MAC-address not found\n");
            
delete[] pIpNetTable;
           }
           
else printf("ERROR Open IPMAC table\n");
       }
       
else printf("Send data ERROR!\n");

       
closesocket(udp_s);
   }
   
else printf("ERROR open socket\n");

   
WSACleanup();         //Освобождаем ресурсы
   
return 0;
}
PS: Последний способ действует только для той подсети, где сам находишься. Если использовать HOST_IP из др. подсети, то в IPMAC таблице будет находится IP и MAC шлюза к HOST_IP.

PPS: MAC-адрес этто физический адрес устройства, и в общем случае
может иметь длинну отличную от 6 байт.
 
« Предыдущая статья   Следующая статья »