//* SRPacketToPkt // // Converts the SRPacket to an NDIS packet that can be transmitted. // The NDIS packet should be deallocated with NdisFreePacketClone. // // If the packet will be transmitted via a single physical adapter, // then PC(Packet)->PA is initialized. // NDIS_STATUS SRPacketToPkt( MiniportAdapter *VA, const SRPacket *SRP, NDIS_PACKET **pPacket) { uint HeaderLength = SROptionLength(SRP); NDIS_PACKET *Packet; #if DBG uint PacketLength; #endif void *CloneHeader; EtherHeader *CloneEther; LQSRHeader *CloneLQSR; LQSROption *Walk; NDIS_STATUS Status; const uchar *Dest; LQSRIf OutIf; LQSRIf InIf; ProtocolAdapter *PA; if (SRP->Packet == NULL) { ASSERT(SRP->PayloadOffset == 0); Status = MiniportMakeEmptyPacket(VA, sizeof(EtherHeader) + sizeof(LQSRHeader) + HeaderLength, &Packet, &CloneHeader); } else { void *OrigHeader; Status = MiniportClonePacket(VA, SRP->Packet, SRP->PayloadOffset, (sizeof(EtherHeader) + sizeof(LQSRHeader) + HeaderLength), 0, // No lookahead needed. &OrigHeader, &Packet, &CloneHeader); } if (Status != NDIS_STATUS_SUCCESS) return Status; #if DBG // // Check that we are not exceeding the physical link MTU. // The basic LQSR header fits in PROTOCOL_MIN_FRAME_SIZE (1500) - // MINIPORT_MAX_FRAME_SIZE (1280) bytes, and // the piggy-backing code will avoid adding too many options. // NdisQueryPacketLength(Packet, &PacketLength); ASSERT(PacketLength <= sizeof(EtherHeader) + PROTOCOL_MIN_FRAME_SIZE); #endif CloneEther = (EtherHeader *) CloneHeader; CloneLQSR = (LQSRHeader *) (CloneEther + 1); Walk = (LQSROption *) (CloneLQSR + 1); CloneEther->Type = ETYPE_MSFT; CloneLQSR->Code = LQSR_CODE; // CloneLQSR->MAC computed below. RtlCopyMemory(CloneLQSR->IV, SRP->IV, LQSR_IV_LENGTH); CloneLQSR->HeaderLength = (ushort) HeaderLength; // // Figure out the packet's destination. // if (SRP->sr != NULL) { uint Index = (SOURCE_ROUTE_HOPS(SRP->sr->opt.optDataLen) - SRP->sr->opt.segmentsLeft - 1); Dest = SRP->sr->opt.hopList[Index + 1].addr; // // If override is on, select the interface // based on RTT's advice. Otherwise use the // static route. // if ((VA->MetricType == METRIC_TYPE_RTT) && VA->MetricParams.Rtt.OutIfOverride) { RttSelectOutIf(VA, Dest, &OutIf, &InIf); SRP->sr->opt.hopList[Index].outif = OutIf; SRP->sr->opt.hopList[Index+1].inif = InIf; } else { OutIf = SRP->sr->opt.hopList[Index].outif; InIf = SRP->sr->opt.hopList[Index+1].inif; } } else if (SRP->Probe != NULL) { if (SRP->Probe->Opt.ProbeType == METRIC_TYPE_ETX) { PA = NULL; goto LinkLayerBroadcastPacket; } Dest = SRP->Probe->Opt.To; OutIf = SRP->Probe->Opt.OutIf; InIf = SRP->Probe->Opt.InIf; } else if (SRP->ProbeReply != NULL) { Dest = SRP->ProbeReply->Opt.To; OutIf = SRP->ProbeReply->Opt.OutIf; InIf = SRP->ProbeReply->Opt.InIf; } else { ASSERT(SRP->req != NULL); PA = NULL; goto LinkLayerBroadcastPacket; } // // Find the physical adapter with this index, // then check the neighbor cache. // PA = FindPhysicalAdapterFromIndex(VA, OutIf); if ((PA == NULL) || ! NeighborFindPhysical(&VA->NC, Dest, InIf, CloneEther->Dest)) { // // We do not have a physical destination address. // Broadcast the packet on the physical link. // LinkLayerBroadcastPacket: RtlFillMemory(CloneEther->Dest, IEEE_802_ADDR_LENGTH, (uchar)0xff); } PC(Packet)->PA = PA; // // Reassembly order doesn't matter. // InsertOptions(&Walk, SRP->sr, LQSR_OPTION_TYPE_SOURCERT); InsertOptions(&Walk, SRP->req, LQSR_OPTION_TYPE_REQUEST); InsertOptions(&Walk, SRP->rep, LQSR_OPTION_TYPE_REPLY); InsertOptions(&Walk, SRP->err, LQSR_OPTION_TYPE_ERROR); InsertOptions(&Walk, SRP->ackreq, LQSR_OPTION_TYPE_ACKREQ); InsertOptions(&Walk, SRP->ack, LQSR_OPTION_TYPE_ACK); InsertOptions(&Walk, SRP->inforeq, LQSR_OPTION_TYPE_INFOREQ); InsertOptions(&Walk, SRP->inforep, LQSR_OPTION_TYPE_INFO); InsertOptions(&Walk, SRP->Probe, LQSR_OPTION_TYPE_PROBE); InsertOptions(&Walk, SRP->ProbeReply, LQSR_OPTION_TYPE_PROBEREPLY); InsertOptions(&Walk, SRP->LinkInfo, LQSR_OPTION_TYPE_LINKINFO); // // Compute the MAC. // SRPacketMAC(VA, CloneLQSR->MAC, Packet); *pPacket = Packet; return NDIS_STATUS_SUCCESS; }
NTSTATUS NdisuioDoFastRead( IN PNDISUIO_OPEN_CONTEXT pOpenContext, IN PIRP pIrp ) /*++ Routine Description: Utility routine to copy received data into user buffers and complete READ IRPs. Arguments: pOpenContext - pointer to open context Return Value: None --*/ { PNDIS_PACKET pRcvPacket; PLIST_ENTRY pRcvPacketEntry; PUCHAR pSrc, pDst; ULONG BytesRemaining; // at pDst PNDIS_BUFFER pNdisBuffer; ULONG BytesAvailable; PPACKET_GROUP pGroup; CCHAR PriorityBoost = IO_NETWORK_INCREMENT; DEBUGP(DL_VERY_LOUD, ("FastRead: open %p/%x\n", pOpenContext, pOpenContext->Flags)); if (NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue)) return STATUS_UNSUCCESSFUL; // // Copy as much data as possible from the receive packet to // the IRP MDL. // #ifndef WIN9X pGroup = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); NUIO_ASSERT(pGroup != NULL); // since it was already mapped #else pGroup = MmGetSystemAddressForMdl(pIrp->MdlAddress); // Win9x #endif BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress); // // Get the first queued receive packet // pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink; pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry); do { NUIO_REMOVE_ENTRY_LIST(pRcvPacketEntry); pOpenContext->RecvPktCount--; NUIO_RELEASE_LOCK(&pOpenContext->Lock); NUIO_DEREF_OPEN(pOpenContext); // Service: dequeue rcv packet pNdisBuffer = pRcvPacket->Private.Head; pDst = pGroup->Data; BytesRemaining -= sizeof(PACKET_GROUP); while (BytesRemaining && (pNdisBuffer != NULL)) { #ifndef WIN9X NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority); if (pSrc == NULL) { DEBUGP(DL_FATAL, ("FastRead: Open %p, QueryBuffer failed for buffer %p\n", pOpenContext, pNdisBuffer)); break; } #else NdisQueryBuffer(pNdisBuffer, &pSrc, &BytesAvailable); #endif if (BytesAvailable) { ULONG BytesToCopy = MIN(BytesAvailable, BytesRemaining); NUIO_COPY_MEM(pDst, pSrc, BytesToCopy); BytesRemaining -= BytesToCopy; pDst += BytesToCopy; } NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer); } ndisuioFreeReceivePacket(pOpenContext, pRcvPacket); pGroup->Length = pDst - pGroup->Data; pGroup = (PPACKET_GROUP)pDst; NUIO_ACQUIRE_LOCK(&pOpenContext->Lock); if (NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue)) { PriorityBoost = IO_NO_INCREMENT; break; } pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink; pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry); NdisQueryPacketLength(pRcvPacket, &BytesAvailable); if (BytesRemaining < BytesAvailable + sizeof(PACKET_GROUP)) break; } while (TRUE); NUIO_RELEASE_LOCK(&pOpenContext->Lock); // // Complete the IRP. // pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining; DEBUGP(DL_INFO, ("FastRead: Open %p, IRP %p completed with %d bytes\n", pOpenContext, pIrp, pIrp->IoStatus.Information)); IoCompleteRequest(pIrp, PriorityBoost); return STATUS_SUCCESS; }
VOID WSCatcherPacketCallback(PVOID pb) { PNDIS_PACKET pPacket = (PNDIS_PACKET)pb; ULONG uPacketLen =0, ulbytes_copied=0; PUCHAR pBuffer = NULL; PIO_WORKITEM pWorkItem = NULL; PWorkItemContext pWIC =NULL; if (!g_bAlreadyPatchWS) { return ; } if (g_pNpfProtocolBlock==NULL) { kprintf("g_pNpfProtocolBlock==NULL in WSCatcherPacketCallback()\n"); return; } do { NdisQueryPacketLength(pPacket, &uPacketLen); if (uPacketLen<sizeof(Dlc_Header))// { //less than eth header,bufer too small,ignore return ; } pBuffer = kmalloc(uPacketLen); GetPktPayload(pPacket, pBuffer, uPacketLen, &ulbytes_copied); if (g_CtlDevice==NULL) { kprintf("g_CtlDevice==NULL\n"); break; } pWorkItem = IoAllocateWorkItem(g_CtlDevice); if (pWorkItem==NULL) { kprintf("IoAllocateWorkItem()==NULL\n"); break; } pWIC = kmalloc(sizeof(WorkItemContext)); if (pWIC==NULL) { kprintf("kmalloc(sizeof(WorkItemContext()==NULL\n"); break; } pWIC->pBuffer = pBuffer; pWIC->pWorkItem = pWorkItem; pWIC->uBufferLen = uPacketLen; IoQueueWorkItem(pWorkItem, WSWorkThread, DelayedWorkQueue, pWIC); pBuffer =NULL;//pBuffer在workitem中再释放 pWorkItem =NULL; pWIC = NULL; } while (0); if (pBuffer!=NULL) { kfree(pBuffer); } if (pWIC) { kfree(pWIC); } if (pWorkItem) { IoFreeWorkItem(pWorkItem); } return ; }