Нужен универсальный способ определения MAC адреса
От: toypaul Удмуртия http://www.1csql.ru
Дата: 24.02.02 08:04
Оценка:
Под универсальностью я понимаю во-первых работу в среде Вынь (95,98,NT,XP). Во-вторых надежность работы на каждой их этих платформ.

Известно, что имеется несколько способов определения номера сетевой
карты или MAC адреса. Но. Каждый из них обладает своими недостатками.
Мне известны несколько способов (не все знаю как реализовать):

1. С помощью NetBIOS
2. С помощью WinSocket
3. С помощью SNMP
4. С помощью GetAdapterInfo
5. Из реестра

Мне известно , что только с помощью п. 1 можно
определить адрес удаленной машины. Но и у этого способа есть
недостаток. Во-первых — нужно правильно определить LANA удаленной
машины. Функция NCBENUM похоже может определить номера LANA только
у локальной машины. Во-вторых, неизвестно как отличить сетевую карту
от других адаптеров. И в-третьих (но это не так страшно) NetBIOS может
быть отключен.

Методы 2.,3. и 4. могут (не утверждаю на все 100%) определить номер только
локальной машины

Метод 4. примерно такой же как 2. — 4. (даже еще хуже).

Всвязи с этим появился данный сабж, который мне очень необходим.

З.Ы.
Уже излазил кучу сайтов как наших так и забугорных — результат 1.-5.,
но сабжа так и не нашел.
Re: Нужен универсальный способ определения MAC адреса
От: ServerMouse Беларусь  
Дата: 24.02.02 18:03
Оценка:
А ещё можно прочитать MAC из таблицы MAC<->IP (конечно только для IP-семейства протоколов).
В NT есть SendARP. В 9х нет. Универсальный способ для такого случая заключается IMHO в такой последовательности:

1. По известному IP-адресу шлём какой-нибудь пакет (не принципиально UDP, TCP, ICMP,etc). Для доставки пакета система ДОЛЖНА знать MAC. И обязательно определит его, занеся в ARP-таблицу соответствие IP<->MAC.
2. Убедившись что пакет ГОТОВ к отправке (блокирующие сокеты например) мы спокойненько забираем MAC из ARP-таблицы. Там будет лежать MAC хоста или шлюза к нему.
Из ARP-таблицы вытягиваем примерно так:

bool GetHostMAC(void *MAC, DWORD _ip)
{    
  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)
      {
         memcpy(MAC,pIpNetTable->table[i].bPhysAddr,6);
         delete[] pIpNetTable;
         return true;
      }
    }
    delete[] pIpNetTable;
  }    
 return false;
}
Если человек программист, то это надолго.
Re[2]: Нужен универсальный способ определения MAC адреса
От: toypaul Удмуртия http://www.1csql.ru
Дата: 25.02.02 07:23
Оценка:
А как послать пакет? У тебя есть рабочий исходник, в котором есть все? Буду очень признателен. И еще — если мне нужен MAC не шлюза, а именно хоста, то как быть?
Re[3]: Нужен универсальный способ определения MAC адреса
От: ServerMouse Беларусь  
Дата: 25.02.02 16:52
Оценка:
Здравствуйте toypaul, Вы писали:

T>А как послать пакет?


Сокеты. Создаёшь UDP сокет и вперёд... Инфы по этому полно.

Т>У тебя есть рабочий исходник, в котором есть все?


С собой нет. Если найду, принесу. Давно такое писалось....

T>И еще — если мне нужен MAC не шлюза, а именно хоста, то как быть?


Хм. IMHO никак. Это др. подсеть и по идее шлюз для того и стоит что бы их разделять. На физическом уровне ты шлёш пакет на МАС шлюза с указанием IP из др. подсети. У шлюза имеется своя таблица IP<->МАС плюс табл. маршрутизации. В соотв. с этим он и отправляет твой пакет дальше по другому МАС, даже не зная, оконечный там хост или ещё один маршрутизатор.

Простейшая проверка технологии из консоли:
1. Делаешь ping HOST_IP
2. Делаешь arp -a
и наблюдаешь HOST_IP HOST_MAC (или GATEWAY_MAC :) )

Кстати техника определения абсолютно не зависит от открытости/установлености NetBIOS.
И абсолютно неважно, примет ли удалённый хост твой пакет или проигнорирует его. Для того что бы убедится в этом проделай примерно следующую последовательность:
1. arp -d HOST_IP удаляем из таблицы, если запись там случайно осталась.
2. telnet
3. open HOST_IP
4. получаем Could not open a connection to host: Connect failed. Это потому, что там порт такой вообще закрыт и соединение невозможно в принципе. НО! Нам важно что пакет был ОТОСЛАН!
5. arp -a и видим HOST_IP HOST_MAC Так вот.

Локальная таблица со временем устаревает (от 1 до 30 мин) потому забирать надо сразу.
Если человек программист, то это надолго.
Re[4]: Нужен универсальный способ определения MAC адреса
От: Аноним  
Дата: 26.02.02 14:19
Оценка:
Пожалуйста, если найдешь исходник кинь мне на мыло toypaul@udmnet.ru. Еще мне нужны заголовочный файл и библиотека, про которую шла речь в "том длинном обсуждении" — ну которые ты обозвал либина и хэндл ;)
Re[2]: Нужен универсальный способ определения MAC адреса
От: Andryu  
Дата: 04.05.06 12:53
Оценка:
Здравствуйте, ServerMouse, Вы писали:

SM>А ещё можно прочитать MAC из таблицы MAC<->IP (конечно только для IP-семейства протоколов).

SM>В NT есть SendARP. В 9х нет. Универсальный способ для такого случая заключается IMHO в такой последовательности:

SM>1. По известному IP-адресу шлём какой-нибудь пакет (не принципиально UDP, TCP, ICMP,etc). Для доставки пакета система ДОЛЖНА знать MAC. И обязательно определит его, занеся в ARP-таблицу соответствие IP<->MAC.

SM>2. Убедившись что пакет ГОТОВ к отправке (блокирующие сокеты например) мы спокойненько забираем MAC из ARP-таблицы. Там будет лежать MAC хоста или шлюза к нему.
SM>Из ARP-таблицы вытягиваем примерно так:

SM>
SM>bool GetHostMAC(void *MAC, DWORD _ip)
SM>{    
SM>  MIB_IPNETTABLE * pIpNetTable = (MIB_IPNETTABLE *) new char[0xFFFF];
SM>  ULONG cbIpNetTable = 0xFFFF;
SM>  if (NO_ERROR == GetIpNetTable (pIpNetTable, &cbIpNetTable, TRUE))
SM>  {
SM>    for (DWORD i = 0; i < pIpNetTable->dwNumEntries; i++)
SM>    {
SM>      if(pIpNetTable->table[i].dwAddr==_ip&&pIpNetTable->table[i].dwType!=2)
SM>      {
SM>         memcpy(MAC,pIpNetTable->table[i].bPhysAddr,6);
SM>         delete[] pIpNetTable;
SM>         return true;
SM>      }
SM>    }
SM>    delete[] pIpNetTable;
SM>  }    
SM> return false;
SM>}
SM>

А как быть в том случае если нужен MAC локального компа, отсылаешь пакет сам себе, а в таблице MAC адреса нет...не подскажите что делать?
Re: Нужен универсальный способ определения MAC адреса
От: aset  
Дата: 04.05.06 13:27
Оценка:
Здравствуйте, toypaul, Вы писали:

...


const char *MACaddress = "00:01:02:03:04:05";


Работать будет везде.
А для более серьезных вещей, советую определить набор исходных данных.
Re: Нужен универсальный способ определения MAC адреса
От: Maxim S. Shatskih Россия  
Дата: 04.05.06 16:59
Оценка:
Для локальной машины GetAdaptersInfo лучше всех. Скоро год, как у нас бегает код, пользующийся им — ни единой проблемы ни у кого.
Занимайтесь LoveCraftом, а не WarCraftом!
Re: Нужен универсальный способ определения MAC адреса
От: c-smile Канада http://terrainformatica.com
Дата: 05.05.06 05:06
Оценка:
Здравствуйте, toypaul, Вы писали:

T>1. С помощью NetBIOS

T>2. С помощью WinSocket
T>3. С помощью SNMP
T>4. С помощью GetAdapterInfo
T>5. Из реестра

6,

unsigned char* get_mac_address(void)
{
  static unsigned char mac[6] = {0};
  static bool mac_fetched = false;

  if(!mac_fetched)
  {
    UUID uuid;
    UuidCreateSequential( &uuid ); 
    for (int i=2; i<8; i++)  
      mac[i - 2] = uuid.Data4[i];
    mac_fetched = true;
  }
  return mac;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.