В общем такая проблема: Вызываю NdisRequest, чтобы карточка перешла в прослушивающий режим. В колбэк функции ProtocolRequestComplete приходит ответ STATUS_SUCCESS это значит, что карточка переведена в прослушивающий режим. Однако, колбэки при получении пакета не вызываются, что обычно должно делаться. Пробую разобраться с драйвером ndis.sys однако, не понятно за что зацепиться, так как ndis.sys возвращает статус ок. Что подскажете? Хотелось бы поковыряться в ndis.sys, таким образом решить вопрос принципиально.
У тебя свой протокольный фильтр, или ты перехватываешь методы существующего протокола? Какая версия ОС? Покажи фрагмент кода, где вызывается NdisRequest.
Мой собственный протокольный драйвер, на базе кстати работающего от winpcap. Есть разница, winpcap переводит карточку в прослушивающий режим в функции IO_control, команда поступает из юзерленда, меня это не устраивает, я вызываю перевод карточки в DriverEntry, не уверен насколько это критично. Ok. Регистрация протокола, здесь все ок. Код (Text): NdisRegisterProtocol( &Status, &g_NdisProtocolHandle, &ProtocolChar, sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); if (Status != NDIS_STATUS_SUCCESS) { TRACE_MESSAGE(PACKET_DEBUG_INIT,"Failed to register protocol with NDIS"); TRACE_EXIT(); return Status; } Затем я получаю имя своего адаптера, здесь имя совпадает, тут без проблем и открываю его, здесь тоже нет проблем Код (Text): NdisOpenAdapter( &Status, &ErrorStatus, &Open->AdapterHandle, &Open->Medium, MediumArray, NUM_NDIS_MEDIA, g_NdisProtocolHandle, Open, &AdaptName, 0, NULL); TRACE_MESSAGE1(PACKET_DEBUG_LOUD,"Opened the device, Status=%x",Status); if (Status == NDIS_STATUS_PENDING) { NdisWaitEvent(&Open->NdisOpenCloseCompleteEvent, 0); if (!NT_SUCCESS(Open->OpenCloseStatus)) { *stat = returnStatus = Open->OpenCloseStatus; } else { *stat = returnStatus = STATUS_SUCCESS; } } Потом переводим карточку в прослушку. Код (Text): ULONG aMode = NDIS_PACKET_TYPE_PROMISCUOUS; // PLIST_ENTRY RequestListEntry; PINTERNAL_REQUEST MaxSizeReq; NDIS_STATUS ReqStatus; TRACE_ENTER(); ASSERT(Open != NULL); //ASSERT(pIrp != NULL); //ASSERT(pMtu != NULL); // Extract a request from the list of free ones //_asm int 3 RequestListEntry = ExInterlockedRemoveHeadList(&Open->RequestList, &Open->RequestSpinLock); if (RequestListEntry == NULL) { // // THIS IS WRONG // // // Assume Ethernet // //*pMtu = 1514; TRACE_EXIT(); return ; } MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement); MaxSizeReq->Request.RequestType = NdisRequestQueryInformation; MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER; MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = &aMode; MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(ULONG); NdisResetEvent(&MaxSizeReq->InternalRequestCompletedEvent); // submit the request _asm int 3 NdisRequest( &ReqStatus, Open->AdapterHandle, &MaxSizeReq->Request); if (ReqStatus == NDIS_STATUS_PENDING) { NdisWaitEvent(&MaxSizeReq->InternalRequestCompletedEvent, 0); ReqStatus = MaxSizeReq->RequestStatus; _asm int 3 } TRACE_EXIT(); в колбэк функции RequestCompleteHandler статус возвращается ок. Код (Text): PINTERNAL_REQUEST pRequest; //_asm int 3 TRACE_ENTER(); pRequest = CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request); //это я чисто для себя проверил. if(NdisRequest->DATA.QUERY_INFORMATION.Oid == OID_GEN_CURRENT_PACKET_FILTER) { _asm int 3 } // // Set the request result // pRequest->RequestStatus = Status; // // and awake the caller // NdisSetEvent(&pRequest->InternalRequestCompletedEvent); TRACE_EXIT(); return; Здесь статус тоже ок, то есть ноль. Соответственно весь код вызывается из DriverEntry, не напрямую конечно, а через функции. Думаю приводит код DriverEntry нет резона, статусы нормальные приходят от всех вышеописанных функций. Еще вопрос, в книге Хоглуда, зачем-то он вызывает колбэк функции в своем же драйвере, в драйвере от winpcap я этого нигде не обнаружил. Нигде драйвер winpcap не вызывает зарегистрированные функции! Но это так, оффтоп. windows xp 2sp
Если речь про 5-й NDIS - то у тебя, скорее всего, неправильно регистрируется драйвер: протокольный фильтр должен через inf-файл ставится, что бы все биндинги протоколов правильно разрезолвились. Если драйвер протокольного фильтра тупо через NtLoadDriver или CreateService/StartService загрузить - то входящие пакеты ловиться не будут.
Да, но я же гружу драйвер динамически от winpcap, и он все отлавливает. мой же драйвер, имеет то же имя что и winpcap npf.sys, это значит что все внутренние имена такие же как и у работающего. Гружу так и свой и winpcap Код (Text): char filePart[MAX_PATH] = {0}; SC_HANDLE hService; SC_HANDLE hSCManager; HANDLE hDevice; char g_driver_path[MAX_PATH]; //pseudo-code //Open SCManager hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE); if(NULL == hSCManager) return GetLastError(); //GetName of the driver GetFullPathName("npf.sys",sizeof(g_driver_path), g_driver_path,(LPSTR*)filePart); //CreateService hService = CreateService(hSCManager,"npf", "\\Device\\npf",SERVICE_START | DELETE, SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE,(LPCSTR)g_driver_path,NULL, NULL, NULL, NULL, NULL); int lastErr; if(NULL == hService) { char _s[256]; lastErr = GetLastError(); itoa(lastErr,_s,10); //::MessageBoxA(NULL,_s,"cREATE SERVICE FAILED",MB_OK); if(ERROR_SERVICE_EXISTS == lastErr) { hService = OpenService(hSCManager,"npf",STANDARD_RIGHTS_REQUIRED | \ SERVICE_QUERY_CONFIG | \ SERVICE_QUERY_STATUS | \ SERVICE_START); if(NULL == hService) { lastErr = GetLastError(); itoa(lastErr,_s,10); ::MessageBoxA(NULL,_s,"Open SERVICE FAILED",MB_OK); return false; } }else { itoa(lastErr,_s,10); ::MessageBoxA(NULL,_s,"Some SERVICE FAILE error",MB_OK); return true; } } //StartService if(!StartService(hService,0,NULL)) { lastErr = GetLastError(); return false; }
У меня есть решение, конечно, переводить карточку в прослушку в IO_control как делает это драйвер winpcap , без юзерленда и с минимумом вмешательства в код, но хотелось бы разобраться в принципе.
дружище, вы не в потоке, о фильтрах никто не говорил. Прощу прощения, нехорошо сказал, вы наверное имели ввиду ndisprot.
Я не совсем понял, но вот этот код: Код (Text): MaxSizeReq->Request.RequestType = NdisRequestQueryInformation; MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER; запрашивает, а не устанавливает фильтр. Может быть имелось в виду NdisRequestSetInformation?
Блин!!!!!!!!!!! Глаз настолько замылился с кучей драйверов. Конечно вы правы, я выдрал не ту ветку в рабочем драйвер, все поля поправил, кроме этого. Сейчас все заработало!!! Куда высылать ящик пива? Большое спасибо, а то я уже на завтра запланировал экскурсию в недра ядра.