Проблема с IRQL при вызове NdisMIndicateReceivePacket

Тема в разделе "WASM.NETWORKS", создана пользователем kilgur, 19 июн 2006.

  1. kilgur

    kilgur New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    13
    Адрес:
    Russia
    // Прошу прощения за дубли... случайно закрыл тему...

    Всем привет.

    Возникла такая задача: написАть IM NDIS драйвер для того, чтобы получать из приложения сетевые пакеты и передавать "наверх" протоколам, как будто они пришли от сетевухи.

    Решил переделать PassThru, с NDIS-драйверами ранее дела не имел - изучаю по-ходу....

    В обработчике IRP_MJ_DEVICE_CONTROL нужного кода формирую NDIS-пакет, а когда вызываю NdisMIndicateReceivePacket получаю BSOD IRQL_NOT_LESS_THAN_OR_EQUAL. В DDK написано, что "Serialized callers of NdisMIndicateReceivePacket must run at IRQL DISPATCH_LEVEL". Проверил - обработчик вызывается на PASSIVE_LEVEL. Пробовал поднимать IRQL для вызова функции - результат тот же...

    Знающие, помогите, а..

    // сильно ногами не бейте - я еще только учусь 8-)
     
  2. Son of God

    Son of God New Member

    Публикаций:
    0
    Регистрация:
    11 сен 2005
    Сообщения:
    125
    Код в студию.
     
  3. kilgur

    kilgur New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    13
    Адрес:
    Russia
  4. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    Неудивительно, что у тебя бсод, если ты сразу же освобождаешь пакет и пул и все ресурсы. Читай внимательно MSDN:


    Код (Text):
    1. A deserialized miniport driver must save the Status member of the out-of-band data block in a local variable before indicating up the packet descriptor. As explained in more detail below, when NdisMIndicateReceivePacket returns, a deserialized miniport driver must check the saved packet Status to determine whether it can immediately reclaim the packet descriptor and the associated buffers.
    2. If a serialized miniport driver does not set a packet's Status member to NDIS_STATUS_RESOURCES, the call to NdisMIndicateReceivePacket gives interested protocols exclusive, read-only access to the buffers chained to each packet. The miniport driver regains ownership of the packet descriptor and the associated buffers as follows:
    3.  
    4. If the Status in the out-of-band data block is set to NDIS_STATUS_SUCCESS on return from NdisMIndicateReceivePacket, the miniport driver immediately regains ownership of the packet descriptor and all buffers chained to the packet. It can prepare these descriptors for reuse in subsequent receive indications.
    5. If the Status is set to NDIS_STATUS_PENDING on return from NdisMIndicateReceivePacket, the miniport driver regains ownership of the packet descriptor and all buffers chained to the packet when NDIS subsequently calls the miniport driver's MiniportReturnPacket function. It can then prepare these descriptors for reuse in subsequent receive indications.
    6.  
     
  5. kilgur

    kilgur New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    13
    Адрес:
    Russia
    2 Ms Rem

    Минуточку... :derisive:

    Я ведь установил NDIS_STATUS_RESOURCES. в DDK пишут, что это должно заставить обработчик протокола СКОПИРОВАТЬ пакет в СВОЮ память и прямо написано, что, в этом случае, сразу после вызова NdisMIndicateReceivePacket можно освобождать буферы и пакет...

    // у меня не просто бсод, а IRQL_NOT_LESS_OR_EQUAL. Вот я и подумал, что проблема именно в IRQL

    Вот что меня смущает, так это то, что не могу найти, где читал про "если установлен NDIS_STATUS_RESOURCES, то нет необходимости обрабатывать MiniportReturnPacket, п.ч. ответа NDIS_STATUS_PENDING не будет..." то бишь либо SUCCESS либо ошибка... никаких отложенных обработок...

    И еще не понимаю, что такое "serialized miniport" и "deserialized ..." ... в чем отличия и где это указать/настроить?...
     
  6. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    > у меня не просто бсод, а IRQL_NOT_LESS_OR_EQUAL

    Ну так это значит, что было исключение при обращении к неподкачиваемому пулу (скорее всего к пакету).

    А была отложеная обработка или нет - это следует определять по наличию NDIS_STATUS_PENDING в выходном пакете. По своему опыту скажу - не все драйвера минипортов/протоколов корректно работают с NDIS_STATUS_RESOURCES.

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

    Пример рабочего драйвера минипорта смотри в сорцах OpenVpn.





    Где указать:
    Код (Text):
    1. A deserialized miniport driver must identify itself as such to NDIS during initialization. Its MiniportInitialize function must call NdisMSetAttributesEx with the NDIS_ATTRIBUTES_DESERIALIZE flag set in the AttributeFlags.




    Отличия читай в мсдн (Deserialized NDIS Miniport Drivers.)
     
  7. kilgur

    kilgur New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    13
    Адрес:
    Russia
    Ms Rem

    Действительно... убрал освобождение пакетов и буферов - первый раз срабатывает гарантированно :derisive:

    Странно... а ведь сам драйвер passthru делает именно так и даже не смотрит статус после вызова - сразу освобождает пакет. Правда он не создает пакет "с нуля"... может дело в атрибутах?

    А есть где-то рабочие сорцы, где бы пакеты создавались "с нуля" ?
     
  8. kilgur

    kilgur New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    13
    Адрес:
    Russia
    Ms Rem

    Попробовал не освобождать пакеты - помогло... :derisive:

    Есть где-то рабочий пример, в котором создается пакет "с нуля", а не копированием из имеющегося?

    В ДДК вот чего написано:

    A deserialized miniport driver must not examine the Status of indicated packets on return of NdisMIndicateReceivePacket. Instead, a deserialized miniport driver must save a packet's Status in a local variable before indicating up the packet descriptor. When NdisMIndicateReceivePacket returns, the miniport driver should check the saved packet Status. If the miniport driver set the packet's Status to NDIS_STATUS_RESOURCES before indicating up the packet descriptor, it should reclaim the packet descriptor immediately after NdisMIndicateReceivePacket returns, preferably by calling its own MiniportReturnPacket function. In this case, NDIS does not call the miniport driver's MiniportReturnPacket function to return the packet descriptor. If the miniport driver set the packet's Status to NDIS_STATUS_SUCCESS before indicating up the packet descriptor, the miniport driver must not reclaim the packet descriptor until NDIS subsequently returns the packet descriptor to the miniport driver's MiniportReturnPacket function.



    Минипорт у меня deserialized

    Если я правильно понял, тут написано, что если я указал NDIS_STAUS_RESOURCE, то ДОЛЖЕН после вызова функции освободить (или заюзать по новой) пакет, а соответственно и буферы... Но что-то я видимо делаю не так... может какие атрибуты у нового пакета выставить забываю?
     
  9. kilgur

    kilgur New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    13
    Адрес:
    Russia
    Попробовал указать в статусе NDIS_STATUS_SUCCESS - бсода нет, но не вызывается MiniportReturnPacket и снифер не видит моих пакетов....

    Народ! Дайте, пожалуйста, рабочий пример создания сетевого пакета "с нуля"!
     
  10. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    Е.п.р.с.т, я же тебе сказал - смотри сорцы OpenVpn.

    Там есть уже готовый драйвер под трою задачу.
     
  11. kilgur

    kilgur New Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    13
    Адрес:
    Russia
    Ms Rem

    Посмотрел сорцы OpenVPN - сначала сделал поиск строки NdisMIndicateReceivePacket, ничего не нашлось и я хотел по-возмущаться хреновым предложением 8-) за что извинияюсь.

    В tap драйвере намного более элегантный способ решения моей проблемы:
    Код (Text):
    1. ioBuffer = Irp->AssociatedIrp.SystemBuffer;
    2. ioBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    3. pAdapt = pAdaptList;
    4. NdisMEthIndicateReceive(
    5.   pAdapt->MiniportHandle,
    6.   pAdapt,
    7.   ioBuffer,
    8.   ETHERNET_HEADER_SIZE,
    9.   ioBuffer + ETHERNET_HEADER_SIZE,
    10.   ioBufferLength - ETHERNET_HEADER_SIZE,
    11.   ioBufferLength - ETHERNET_HEADER_SIZE
    12. );
    13. NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);
    14. Irp->IoStatus.Status = STATUS_SUCCESS;
    15. Irp->IoStatus.Information = ioBufferLength;