Проблемка с Ethernet

Тема в разделе "WASM.WIN32", создана пользователем Wereww, 12 июл 2010.

  1. Wereww

    Wereww Дмитрий

    Публикаций:
    0
    Регистрация:
    13 июн 2009
    Сообщения:
    55
    День добрый, пишу небольшую программку и споткнулся о проблему, суть программы: определить сетевой адаптер типа Ethernet (Wireless должен игнорироваться), к которому был подключен кабель (в случае если их несколько).

    1. К сожалению определять тип адаптера не получается, ни через GetAdaptersInfo (даже если подключение виртуальное - например Hamachi - то всеравно PIP_ADAPTER_INFO->Type = MIB_IF_TYPE_ETHERNET), ни через GetIfTable (аналогичная картина - PMIB_IFROW->dwType = IF_TYPE_ETHERNET_CSMACD), единственное что пришло в голову так это определять тип энумератора через SetupDiGetDeviceRegistryProperty (если в буфере лежит "PCI" - значит сетевуха установлена физически), но опять же - тип адаптера не известен - Ethernet или Wireless...где то видел буржуи предлагают установить DDK и использовать NDIS и далее проверять каждый адаптер на совместимые OID_SCOPE...сюда я покачто не лез...

    2. Может быть есть другой подход, но более ничего в голову не пришло как определять подключен кабель или нет, суть идеи такова: когда кабель отсутствует то PIP_ADAPTER_INFO->IpAddressList = 0.0.0.0 (при условии что DHCP включен), тоесть когда будет получен PIPA IP то это и есть искомая сетевуха, но есть и свои затыки - например отключено несколько связанных служб и получение адреса может идти "бесконечно" (либо по другим причинам), так что в этом месте тоже непонятки, как лучше сделать...

    У кого-нибудь есть идеи на этот счёт ?..
     
  2. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    Определить подключен ли сетевой кабель можно с точностью в 100%
    вот таким способом (код древний и на паскале, но там сплошное апи):
    Код (Text):
    1.  66   MAX_ADAPTER_NAME_LENGTH        = 256;
    2.  67   MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
    3.  68   MAX_ADAPTER_ADDRESS_LENGTH     = 8;
    4.  69
    5.  70   MAX_INTERFACE_NAME_LEN = $100;
    6.  71   MAXLEN_IFDESCR = $100;
    7.  72   MIB_IF_ADMIN_STATUS_UP = 1;
    8.  73   MIB_IF_ADMIN_STATUS_DOWN = 2;
    9.  74   MIB_IF_ADMIN_STATUS_TESTING = 3;
    10.  75   MIB_IF_OPER_STATUS_NON_OPERATIONAL = 0;
    11.  76   MIB_IF_OPER_STATUS_UNREACHABLE = 1;
    12.  77   MIB_IF_OPER_STATUS_DISCONNECTED = 2;
    13.  78   MIB_IF_OPER_STATUS_CONNECTING = 3;
    14.  79   MIB_IF_OPER_STATUS_CONNECTED = 4;
    15.  80   MIB_IF_OPER_STATUS_OPERATIONAL = 5;
    16.  81   MIB_IF_TYPE_OTHER = 1;
    17.  82   MIB_IF_TYPE_ETHERNET = 6;
    18.  83   MIB_IF_TYPE_TOKENRING = 9;
    19.  84   MIB_IF_TYPE_FDDI = 15;
    20.  85   MIB_IF_TYPE_PPP = 23;
    21.  86   MIB_IF_TYPE_LOOPBACK = 24;
    22.  87   MIB_IF_TYPE_SLIP = 28;
    23.  88
    24.  89 type
    25.  90   TMac = array [0..MAX_ADAPTER_ADDRESS_LENGTH-1] of byte;
    26.  91   _MIB_IFROW = packed record
    27.  92     wszName: array [0..MAX_INTERFACE_NAME_LEN-1] of WCHAR;
    28.  93     dwIndex,
    29.  94     dwType,
    30.  95     dwMtu,
    31.  96     dwSpeed,
    32.  97     dwPhysAddrLen: DWORD;
    33.  98     bPhysAddr: TMac;
    34.  99     dwAdminStatus,
    35. 100     dwOperStatus,
    36. 101     dwLastChange,
    37. 102     dwInOctets,
    38. 103     dwInUcastPkts,
    39. 104     dwInNUcastPkts,
    40. 105     dwInDiscards,
    41. 106     dwInErrors,
    42. 107     dwInUnknownProtos,
    43. 108     dwOutOctets,
    44. 109     dwOutUcastPkts,
    45. 110     dwOutNUcastPkts,
    46. 111     dwOutDiscards,
    47. 112     dwOutErrors,
    48. 113     dwOutQLen,
    49. 114     dwDescrLen: DWORD;
    50. 115     bDescr: array [0..MAXLEN_IFDESCR-1] of char;
    51. 116   end;
    52. 117   MIB_IFROW = _MIB_IFROW;
    53. 118   PMIB_IFROW = ^MIB_IFROW;
    54. 119
    55. 120   _MIB_IFTABLE = packed record
    56. 121     dwNumEntries: DWORD;
    57. 122     table: array [0..0] of MIB_IFROW;
    58. 123   end;
    59. 124   MIB_IFTABLE = _MIB_IFTABLE;
    60. 125   PMIB_IFTABLE = ^MIB_IFTABLE;
    61. ...
    62. 306 function GetAdapterError(MAC: TMac): DWORD;stdcall;
    63. 307 var
    64. 308   IFTABLESIZE: DWORD;
    65. 309   IFTABLE: PMIB_IFTABLE;
    66. 310 begin
    67. 311   IFTABLESIZE := 0;
    68. 312   Result := 0;
    69. 313   GetIfTable(nil,@IFTABLESIZE,true);
    70. 314   if IFTABLESIZE = 0 then exit;
    71. 315   GetMem(IFTABLE,IFTABLESIZE);
    72. 316   ZeroMemory(IFTABLE,IFTABLESIZE);
    73. 317   if GetIfTable(IFTABLE,@IFTABLESIZE,true) = 0 then
    74. 318   begin
    75. 319     while (IFTABLE^.dwNumEntries > 0) and
    76. 320           (not CompareMem(@IFTABLE^.table[IFTABLE^.dwNumEntries-1].bPhysAddr,
    77. 321           @Mac,IFTABLE^.table[IFTABLE^.dwNumEntries-1].dwPhysAddrLen)) do dec(IFTABLE^.dwNumEntries);
    78. 322     if IFTABLE^.dwNumEntries > 0 then
    79. 323       Result := IFTABLE^.table[IFTABLE^.dwNumEntries-1].dwOperStatus;
    80. 324   end;
    81. 325   FreeMem(IFTABLE);
    82. 326 end;
    Если возвращает: MIB_IF_OPER_STATUS_DISCONNECTED то сетевой не подключен
    P.S. Кажется и MIB_IF_OPER_STATUS_NON_OPERATIONAL указывает на не подключенность сетевого кабеля.
     
  3. Wereww

    Wereww Дмитрий

    Публикаций:
    0
    Регистрация:
    13 июн 2009
    Сообщения:
    55
    Хмм...есть мнение, что этот код будет возвращать MIB_IF_OPER_STATUS_DISCONNECTED и в том случае если адаптер просто отключен....
    Как на работу приду - перепишу и посмотрим, спасибо за отклик )
     
  4. Wereww

    Wereww Дмитрий

    Публикаций:
    0
    Регистрация:
    13 июн 2009
    Сообщения:
    55
    Проверил, на 2003 Server / XP - проблем нет, работает, а вот на висте и семёрке почему то...не могу запустить GetIfTable, возвращает ERROR_INSUFFICIENT_BUFFER...

    Вот что пишет по этому поводу msdn:
    Самое интересное в том, что в хидере, описания на GetIfTable2 я так и не нашёл...опять гемморой.....
     
  5. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    На висте такое вполне работает:
    Код (Text):
    1.     ULONG bsz=0;
    2.     GetIfTable(NULL,&bsz,false);
    3.     char* buf=malloc(bsz);
    4.     GetIfTable((PMIB_IFTABLE)buf,&bsz,false);
     
  6. Wereww

    Wereww Дмитрий

    Публикаций:
    0
    Регистрация:
    13 июн 2009
    Сообщения:
    55
    Делаю аналогично:

    Код (Text):
    1.     PMIB_IFTABLE pTable = NULL;
    2.     DWORD dwSize = 0;
    3.     if ( GetIfTable( pTable, &dwSize, FALSE ) == ERROR_INSUFFICIENT_BUFFER )
    4.     {
    5.  
    6.         pTable = PMIB_IFTABLE(LocalAlloc(LMEM_ZEROINIT, dwSize));
    7.         if ( !GetIfTable( pTable, &dwSize, TRUE ) )
    8.         {...
    GetIfTable возвращает код 87, ничего не понятно, буду ковырять...
     
  7. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Wereww
    Может для случая когда последний параметр TRUE требуется больше памяти чем для FALSE? хотя конечно маразм.
     
  8. Wereww

    Wereww Дмитрий

    Публикаций:
    0
    Регистрация:
    13 июн 2009
    Сообщения:
    55
    Маразм...
    Без разницы, последний параметр отвечает за сортировку помойму, менял их и true и false и наоборот, - менялся только порядок перечисления интерфейсов...

    Даже так сделал:
    Код (Text):
    1.     PMIB_IFTABLE pTable = NULL;
    2.     DWORD dwSize = 0;
    3.  
    4.         GetIfTable( NULL, &dwSize, FALSE );
    5.  
    6.     if (dwSize != 0)
    7.     {
    8.  
    9.         pTable = PMIB_IFTABLE(LocalAlloc(LMEM_ZEROINIT, dwSize));
    10.         if ( !GetIfTable( pTable, &dwSize, FALSE ) )
    11.         {
    Результат один и тот же, затык именно на первой GetIfTable, что то с размером не так...

    Код (Text):
    1.     ULONG bsz=0;
    2.     GetIfTable(NULL,&bsz,false);
    3.     char* buf=malloc(bsz);
    4.     GetIfTable((PMIB_IFTABLE)buf,&bsz,false);
    5.  
    6.     [C++ Error] iphlpapi.cpp(26): E2034 Cannot convert 'void *' to 'char *'
    Сразу оговорюсь, что компилятор Borland, пишу на CB6.
     
  9. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Wereww
    А если заранее попробовать выделить много памяти?
    Код (Text):
    1. DWORD bsz = 0x100000;
    2. char buf[0x100000];
    3. GetIfTable((PMIB_IFTABLE)buf,&bsz,false);
     
  10. Wereww

    Wereww Дмитрий

    Публикаций:
    0
    Регистрация:
    13 июн 2009
    Сообщения:
    55
    Пффф...заработало, сделал через GetProcAddress (GetIfTable2, GetIfTable)
    Оказывается такая проблема не только у меня

    Так нельзя делать, exception будет, функция не проверяет размер буфера
     
  11. Wereww

    Wereww Дмитрий

    Публикаций:
    0
    Регистрация:
    13 июн 2009
    Сообщения:
    55
    Теперь осталась одна проблемка, надо отличить Ethernet адаптер от Wireless, как найду чего-нибудь, отпишусь...
     
  12. Wereww

    Wereww Дмитрий

    Публикаций:
    0
    Регистрация:
    13 июн 2009
    Сообщения:
    55
  13. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    То есть мой код рабочий???? :)))
     
  14. Wereww

    Wereww Дмитрий

    Публикаций:
    0
    Регистрация:
    13 июн 2009
    Сообщения:
    55
    Рабочий ) правда писал на С++ и немного по другому )

    Насчёт NDIS ) аналогичная ситуация )))))) проверял на нескольких ноутбуках ))) когда делаю запрос OID_GEN_MEDIA_IN_USE то в буфере всеравно лежит 0, тоесть NdisMedium802_3, тоесть Ethernet ) простите за тавтологию ) но всеравно вышел из ситуации - делаю повторный запрос OID_802_11_NETWORK_TYPE_IN_USE и разумеется если это не вай фай то получу на выходе ноль )
     
  15. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    Ну на С, не на С там АПИ в основном потому тут на язык грубо говоря по...й.
    Сам когда-то перерыл кучу форумов, в том числе и Васм...