Доброго времени суток. Появилась необходимость в passthru(DDK) отправлять дополнительный пакет при обработке в MPSendPackets. Возможно ли это сделать? Возникает еще один вопрос: при изменении длины исходного пакета путем Unchain(chain) и adjustbufferlength ДДК предостерегает о том, что эту длину перед отправкой пакета надо вернуть в исходную; есть ли способ изменить исходный пакет и отправить его без создания дополнительных пакетов?
Конечно можно. Сделай allocation и setup новому NDIS_PACKET и скорми NDIS-у. Сложность будет в том как определить свой/passthrough пакет в callback-e. Трогать чужие пакеты ни в коем случае нельзя. Скопируй данные в новый пакет а этот можешь просто вернуть (drop).
Там есть резервные поля в которых можно вставить маркер, который будет проверяться в коллбеке. Это например.
Создаю пакет, копирую в него информацию из оригинального, создаю на него копию и пытаюсь отправить с помощью NdisSend, получается BSOD DRIVER_IRQL_NOT_LESS_OR_EQUAL, который вываливается после вызова NdisMSendComplete в функции PtSendComplete. Сначала пытался просто отправлять пакет, но прочитал, что отправлять надо копию: результат получался такой же. Вот код: Код (Text): PUCHAR FirstBuf; PUCHAR SecondBuf; ULONG nOffset = 0; ULONG lpNumberOfBytesRead; PNDIS_BUFFER CurrentBuffer; UINT TotalPacketLength; UCHAR IpLen; UINT nBufferCount; UINT CurrentLength; UINT Length; PUCHAR VirtualAddress; NDIS_STATUS Status; PNDIS_BUFFER FirstPacketBuffer; PVOID MediaSpecificInfo = NULL; UINT MediaSpecificInfoSize = 0; // Считывание информации об оригинальном пакете NdisQueryPacket( Packet, NULL, &nBufferCount, &CurrentBuffer, &TotalPacketLength ); FirstBuf = (PUCHAR)ExAllocateFromNPagedLookasideList( &ListHeader ); SecondBuf = (PUCHAR)ExAllocateFromNPagedLookasideList( &ListHeader ); // Считывание данных из оригинального пакета ReadPacket( Packet, FirstBuf, TotalPacketLength, nOffset, &lpNumberOfBytesRead ); // Для создания пакета я сам создаю хэндл пула NdisAllocatePacket( &Status, &FirstPacket, PktPoolHandle ); if (Status == NDIS_STATUS_SUCCESS) { NdisAllocateBuffer( &Status, &FirstPacketBuffer, PoolHandle, SecondBuf, TotalPacketLength ); NdisChainBufferAtBack( FirstPacket, FirstPacketBuffer ); NdisQueryPacket( FirstPacket, NULL, &nBufferCount, &CurrentBuffer, &TotalPacketLength ); NdisQueryBufferSafe( CurrentBuffer, &VirtualAddress, &CurrentLength, NormalPagePriority ); NdisMoveMemory( VirtualAddress, FirstBuf, CurrentLength ); } ExFreeToNPagedLookasideList( &ListHeader, FirstBuf ); ExFreeToNPagedLookasideList( &ListHeader, SecondBuf ); // Создание копии пакета, аналог присваивания Packet = PacketArray[i] MyPacket = *(PPNDIS_PACKET)(&FirstPacket); // Пакет для отправки NdisAllocatePacket( &Status,&SecPacket, pAdapt->SendPacketPoolHandle ); if (Status == NDIS_STATUS_SUCCESS) { PNDIS_PACKET_EXTENSION Old, New; Rsvd = (PRSVD)(SecPacket->ProtocolReserved); Rsvd->OriginalPkt = FirstPacket; SecPacket->Private.Flags = NdisGetPacketFlags(MyPacket); SecPacket->Private.Head = MyPacket->Private.Head; SecPacket->Private.Tail = MyPacket->Private.Tail; NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(SecPacket), NDIS_OOB_DATA_FROM_PACKET(MyPacket), sizeof(NDIS_PACKET_OOB_DATA)); NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket, &MediaSpecificInfo, &MediaSpecificInfoSize); if (MediaSpecificInfo || MediaSpecificInfoSize) { NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(SecPacket, MediaSpecificInfo, MediaSpecificInfoSize); } NdisSend( &Status, pAdapt->BindingHandle, SecPacket ); }
То есть мне надо самому освобождать пакет, а в PtSendComplete() просто проверить мой или нет и, если мой, ничего с ним не делать?
В SendComplete() ты должен освобождать (free) свои пакеты и переправлять (forward the callback) чужих, которые ты не трогал.
С посылкой разобрался, спасибо Теперь неплохо бы понять как работает прием, по аналогии если, то мы тоже создаем свой пакет в PtReceivePackets(...), делаем с ним что надо и обрабатываем в MpReturnPacket(...).
Разобрался с приемом и отправкой, на виртуальной машине все без проблем работает, но на физических компьютерах, соединенных просто кроссом пакеты не доходят, может у кого есть идеи? Возможно косяк кроется в превышении длины ethernet пакета, то есть превышении 1514 байт. По идее это же не задача ndis драйвера разбивать пакет на 2 в таком случае?
ты добавляешь что-то своё к пакету? надо уменьшить размер на это что-то. например так: Код (Text): RequestComplete(... ) { ... switch (NdisRequest->RequestType) { case NdisRequestQueryInformation: if ( (Oid == OID_GEN_MAXIMUM_FRAME_SIZE) || (Oid == OID_GEN_MAXIMUM_TOTAL_SIZE) ) *(PULONG)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer -= MyAddedSize; ....
Доходят только пакеты с нетронутой длинной. Может быть еще дело во флагах создаваемого пакета? Контрольную сумму пересчитываю.
Пакеты с добавленной длинной один раз приходят с Retransmission, а потом приходит множество запросов (Out-of-order) и ответов на них в виде пакета (Dup ACK) с длиной данных, равных добавленной.
amn, ты редактируешь TCP packets? Если так, то ты вообще представляешь как работает протокол? Sequence numbers, checksum...