UINT CopyPacketToBuffer( PCHAR DstData, PNDIS_PACKET SrcPacket, UINT SrcOffset, UINT Length) /* * FUNCTION: Copies data from an NDIS packet to a buffer * ARGUMENTS: * DstData = Pointer to destination buffer * SrcPacket = Pointer to source NDIS packet * SrcOffset = Source start offset * Length = Number of bytes to copy * RETURNS: * Number of bytes copied to destination buffer * NOTES: * The number of bytes copied may be limited by the source * buffer size */ { PNDIS_BUFFER FirstBuffer; PVOID Address; UINT FirstLength; UINT TotalLength; TI_DbgPrint(DEBUG_PBUFFER, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData, SrcPacket, SrcOffset, Length)); NdisGetFirstBufferFromPacket(SrcPacket, &FirstBuffer, &Address, &FirstLength, &TotalLength); return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length); }
void netgSendToMiniportComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pNdisPacket, IN NDIS_STATUS Status) { PIRP pIrp; PIO_STACK_LOCATION pIrpSp; PADAPT pAdapt; POPEN_CONTEXT pOpenContext; PNDIS_BUFFER pNdisBuffer; PVOID VirtualAddr; UINT BufferLength; UINT TotalLength; DBGPRINT(("==> netgSendToMiniportComplete\n")); pAdapt = (PADAPT)ProtocolBindingContext; pOpenContext = pAdapt->pOpenContext; pIrp = (((PNPROT_SEND_PACKET_RSVD)&((pNdisPacket)->ProtocolReserved[0]))->pIrp); // Free buffer NdisGetFirstBufferFromPacket(pNdisPacket, &pNdisBuffer, &VirtualAddr, &BufferLength, &TotalLength); NdisFreeBuffer(pNdisBuffer); // Free packet if (NdisInterlockedDecrement((PLONG)&((PNPROT_SEND_PACKET_RSVD)&((pNdisPacket)->ProtocolReserved[0]))->RefCount) == 0) { \ NdisFreePacket(pNdisPacket); } CompleteTheIRP: // Complete the Write IRP with the right status. pIrpSp = IoGetCurrentIrpStackLocation(pIrp); if (Status == NDIS_STATUS_SUCCESS) { pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length; pIrp->IoStatus.Status = STATUS_SUCCESS; } else { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; } IoCompleteRequest(pIrp, IO_NO_INCREMENT); DBGPRINT(("<== netgSendToMiniportComplete\n")); }
INT LpxProtocolReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ){ PDEVICE_CONTEXT deviceContext; PNDIS_BUFFER ndisFirstBuffer; PVOID firstBuffer; UINT firstBufferSize; UINT totalBufferSize; USHORT protocol; PNDIS_PACKET packet = NULL; NDIS_STATUS status; INT pktReferenceCount = 0; UINT addiLlcHeaderSize = 0; PLPX_HEADER lpxHeader; USHORT lpxHeaderSize; UINT lpxPayload; UINT rawDataOffset; DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") ); deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext; // // Check to see if the device context is initialized. // ASSERT( deviceContext->NdisBindingHandle ); if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) { DebugPrint( 4,("Device is not initialized. Drop packet\n") ); return 0; } // // validation // NdisGetFirstBufferFromPacket( Packet, &ndisFirstBuffer, &firstBuffer, &firstBufferSize, &totalBufferSize); if (firstBufferSize < ETHERNET_HEADER_LENGTH) { DebugPrint( 1, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) ); return 0; } protocol = ((PETHERNET_HEADER)firstBuffer)->Type; // // Discard 802.2 LLC SNAP field. // // if Ether Type less than 0x0600 ( 1536 ) // if (NTOHS(protocol) < 0x0600 && NTOHS(protocol) != 0x0060 && // LOOP: Ethernet Loopback NTOHS(protocol) != 0x0200 && // PUP : Xerox PUP packet NTOHS(protocol) != 0x0201) { // PUPAP: Xerox PUP address trans packet protocol = *(PUSHORT)((PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2); if(firstBufferSize >= LENGTH_8022LLCSNAP) firstBufferSize -= LENGTH_8022LLCSNAP; else { DebugPrint( 1, ("ProtocolReceivePacket: Too small first buffer\n") ); return 0; } if(totalBufferSize >= LENGTH_8022LLCSNAP) totalBufferSize -= LENGTH_8022LLCSNAP; else { DebugPrint( 1, ("ProtocolReceivePacket: Too small total buffer\n") ); return 0; } addiLlcHeaderSize = LENGTH_8022LLCSNAP; } if (protocol != HTONS(ETH_P_LPX)) { DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", protocol) ); return 0; } if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) { DebugPrint( 1, ("ProtocolReceivePacket: too small packet(1).\n")); return 0; } // // Extract LPX header information // // lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize); lpxHeaderSize = sizeof(LPX_HEADER); lpxPayload = NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize; #if __LPX_OPTION_ADDRESSS__ if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } #endif if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) { DebugPrint( 1, ("ProtocolReceivePacket: too small packet(2).\n")); return 0; } // // DROP PACKET for DEBUGGING!!!! // #if 1 //DBG // Enabled for testing if (PacketRxDropRate) { PacketRxCountForDrop++; if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) { PLPX_HEADER lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize); #if 0 if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) DebugPrint( 1, ("[Drop(%x,%x,%x))]\n", NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) ); #endif DebugPrint( 1, ("D\n") ); return 0; } } #endif ASSERT( addiLlcHeaderSize == 0 ); DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n", totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) ); // // If the miniport is out of resources, we can't queue // this packet - make a copy if this is so. // if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES) { UINT bytesCopied; DebugPrint( 1, ("ProtocolReceivePacket: Miniport reported low packet resources.\n")); status = RcvPacketAlloc( deviceContext, lpxPayload, &packet ); if (status == STATUS_SUCCESS) { ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); // // Copy lpx payload. payload contains only data. // NdisCopyFromPacketToPacket( packet, 0, lpxPayload, Packet, ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize, &bytesCopied); ASSERT(lpxPayload == bytesCopied); } rawDataOffset = 0; pktReferenceCount = 0; } else { PLPX_RESERVED externalReserved; // // No need to allocate new NDIS packet and copy data to the new NDIS packet. // But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context. // We should allocate our own. // packet = Packet; status = NdisAllocateMemoryWithTag(&externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED); if(status == NDIS_STATUS_SUCCESS) { RtlZeroMemory(externalReserved, sizeof(LPX_RESERVED)); // By setting the external reserved field, RESERVED() uses external reserved context automatically. ((PLPX_RESERVED)packet->ProtocolReserved)->ExternalReserved = externalReserved; // Initialize LPX reserved context instead of RcvPacketAlloc(). RESERVED(packet)->Cloned = 0; RESERVED(packet)->Type = LPX_PACKET_TYPE_RECEIVE; RESERVED(packet)->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT; // set data offset // Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data. rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize; lpxPayload += rawDataOffset; // return one reference count indicating LPX will call NdisReturnPackets() once. pktReferenceCount = 1; } } if (status != NDIS_STATUS_SUCCESS) { return 0; } // // Init LPX reserved context // LpxCopyEthLpxHeadersToLpxReserved(packet, firstBuffer, protocol, lpxHeader, lpxHeaderSize); RESERVED(Packet)->Packet = packet; RESERVED(Packet)->RecvTime = CurrentTime(); RESERVED(Packet)->PacketRawDataLength = lpxPayload; RESERVED(Packet)->PacketRawDataOffset = rawDataOffset; // // Queue to the device context. // ExInterlockedInsertTailList( &deviceContext->PacketInProgressList, &(RESERVED(Packet)->ListEntry), &deviceContext->PacketInProgressQSpinLock ); return pktReferenceCount; }
VOID NdisProtSendComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pNdisPacket, IN NDIS_STATUS Status ) /*++ Routine Description: NDIS entry point called to signify completion of a packet send. We pick up and complete the Write IRP corresponding to this packet. NDIS 5.1: Arguments: ProtocolBindingContext - pointer to open context pNdisPacket - packet that completed send Status - status of send Return Value: None --*/ { PIRP pIrp; PIO_STACK_LOCATION pIrpSp; PNDISPROT_OPEN_CONTEXT pOpenContext; pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext; NPROT_STRUCT_ASSERT(pOpenContext, oc); pIrp = NPROT_IRP_FROM_SEND_PKT(pNdisPacket); if (pOpenContext->bRunningOnWin9x) { // // We would have attached our own NDIS_BUFFER. Take it out // and free it. // #ifndef NDIS51 PNDIS_BUFFER pNdisBuffer; PVOID VirtualAddr; UINT BufferLength; UINT TotalLength; #endif #ifdef NDIS51 NPROT_ASSERT(FALSE); // NDIS 5.1 not on Win9X! #else NdisGetFirstBufferFromPacket( pNdisPacket, &pNdisBuffer, &VirtualAddr, &BufferLength, &TotalLength); NPROT_ASSERT(pNdisBuffer != NULL); NdisFreeBuffer(pNdisBuffer); #endif } #ifdef NDIS51 IoSetCancelRoutine(pIrp, NULL); NPROT_ACQUIRE_LOCK(&pOpenContext->Lock); NPROT_REMOVE_ENTRY_LIST(&pIrp->Tail.Overlay.ListEntry); NPROT_RELEASE_LOCK(&pOpenContext->Lock); #endif // // We are done with the NDIS_PACKET: // NPROT_DEREF_SEND_PKT(pNdisPacket); // // Complete the Write IRP with the right status. // pIrpSp = IoGetCurrentIrpStackLocation(pIrp); if (Status == NDIS_STATUS_SUCCESS) { pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length; pIrp->IoStatus.Status = STATUS_SUCCESS; } else { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; } DEBUGP(DL_INFO, ("SendComplete: packet %p/IRP %p/Length %d " "completed with status %x\n", pNdisPacket, pIrp, pIrp->IoStatus.Information, pIrp->IoStatus.Status)); IoCompleteRequest(pIrp, IO_NO_INCREMENT); NdisInterlockedDecrement((PLONG)&pOpenContext->PendedSendCount); NPROT_DEREF_OPEN(pOpenContext); // send complete - dequeued send IRP }
UINT CopyPacketToBufferChain( PNDIS_BUFFER DstBuffer, UINT DstOffset, PNDIS_PACKET SrcPacket, UINT SrcOffset, UINT Length) /* * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain * ARGUMENTS: * DstBuffer = Pointer to destination NDIS buffer * DstOffset = Destination start offset * SrcPacket = Pointer to source NDIS packet * SrcOffset = Source start offset * Length = Number of bytes to copy * RETURNS: * Number of bytes copied to destination buffer * NOTES: * The number of bytes copied may be limited by the source and * destination buffer sizes */ { PNDIS_BUFFER SrcBuffer; PCHAR DstData, SrcData; UINT DstSize, SrcSize; UINT Count, Total; TI_DbgPrint(DEBUG_PBUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length)); /* Skip DstOffset bytes in the destination buffer chain */ NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1) return 0; /* Skip SrcOffset bytes in the source packet */ NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID)&SrcData, &SrcSize, &Total); if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1) return 0; /* Copy the data */ for (Total = 0;;) { /* Find out how many bytes we can copy at one time */ if (Length < SrcSize) Count = Length; else Count = SrcSize; if (DstSize < Count) Count = DstSize; RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count); Total += Count; Length -= Count; if (Length == 0) break; DstSize -= Count; if (DstSize == 0) { /* No more bytes in destination buffer. Proceed to the next buffer in the destination buffer chain */ NdisGetNextBuffer(DstBuffer, &DstBuffer); if (!DstBuffer) break; NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); } SrcSize -= Count; if (SrcSize == 0) { /* No more bytes in source buffer. Proceed to the next buffer in the source buffer chain */ NdisGetNextBuffer(SrcBuffer, &SrcBuffer); if (!SrcBuffer) break; NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); } } return Total; }
//* SRPacketFromPkt // // Parses an LQSR packet into an SRPacket. // NDIS_STATUS SRPacketFromPkt( MiniportAdapter *VA, NDIS_PACKET *Packet, SRPacket **pSRP) { uchar MAC[LQSR_MAC_LENGTH]; SRPacket *SRP; void *OrigHeader; EtherHeader *OrigEther; LQSRHeader *OrigLQSR; NDIS_BUFFER *OrigBuffer; uint OrigBufferLength; uint HeaderLength; uint OrigPacketLength; InternalRouteRequest *Req; InternalRouteReply *Rep; InternalRouteError *Err; InternalAcknowledgementRequest *AckReq; InternalAcknowledgement *Ack; InternalSourceRoute *SR; InternalInfoRequest *InfoReq; InternalInfoReply *InfoRep; InternalProbe *Pro; InternalProbeReply *ProRep; InternalLinkInfo *LI; // // NB: Below code assumes the entire LQSR header is contiguous. // NdisGetFirstBufferFromPacket(Packet, &OrigBuffer, &OrigHeader, &OrigBufferLength, &OrigPacketLength); ASSERT(OrigBufferLength <= OrigPacketLength); if (OrigBufferLength < sizeof(EtherHeader) + sizeof(LQSRHeader)) return NDIS_STATUS_BUFFER_TOO_SHORT; OrigEther = (EtherHeader *) OrigHeader; OrigLQSR = (LQSRHeader *) (OrigEther + 1); HeaderLength = (sizeof(EtherHeader) + sizeof(LQSRHeader) + OrigLQSR->HeaderLength); if (OrigBufferLength < HeaderLength) return NDIS_STATUS_BUFFER_TOO_SHORT; // // Verify the MAC. // SRPacketMAC(VA, MAC, Packet); if (! RtlEqualMemory(MAC, OrigLQSR->MAC, LQSR_MAC_LENGTH)) { InterlockedIncrement((PLONG)&VA->CountRecvBadMAC); return NDIS_STATUS_INVALID_PACKET; } SRP = ExAllocatePool(NonPagedPool, sizeof *SRP); if (SRP == NULL) return NDIS_STATUS_RESOURCES; RtlZeroMemory(SRP, sizeof *SRP); // // Parse the LQSR header options. // SRP = FillSRPacket(SRP, OrigLQSR); if (SRP == NULL) { // // Illegal packet format. FillSRPacket freed SRP. // return NDIS_STATUS_INVALID_PACKET; } // // Extract virtual source/destination addresses from the LQSR header. // if (SRP->sr != NULL) { uint Hops = SOURCE_ROUTE_HOPS(SRP->sr->opt.optDataLen); RtlCopyMemory(SRP->Source, SRP->sr->opt.hopList[0].addr, SR_ADDR_LEN); RtlCopyMemory(SRP->Dest, SRP->sr->opt.hopList[Hops - 1].addr, SR_ADDR_LEN); } else if (SRP->req != NULL) { RtlCopyMemory(SRP->Source, SRP->req->opt.hopList[0].addr, SR_ADDR_LEN); RtlCopyMemory(SRP->Dest, SRP->req->opt.targetAddress, SR_ADDR_LEN); } else if ((SRP->ack != NULL) || (SRP->Probe != NULL) || (SRP->ProbeReply != NULL)) { // // We don't have virtual source/destination addresses. // RtlZeroMemory(SRP->Source, SR_ADDR_LEN); RtlZeroMemory(SRP->Dest, SR_ADDR_LEN); } else { KdPrint(("MCL!Packet missing RR/SR/Ack!\n")); SRPacketFree(SRP); return NDIS_STATUS_INVALID_PACKET; } // // Acknowledgement Requests need a Source Route. // if ((SRP->ackreq != NULL) && (SRP->sr == NULL)) { KdPrint(("MCL!Packet with AckReq missing SR!\n")); SRPacketFree(SRP); return NDIS_STATUS_INVALID_PACKET; } // // Save information about the original packet. // NB: Calling SRPacketFree after doing this // and before our caller initializes SRP->FreePacket // will cause a bugcheck. // SRP->Packet = Packet; SRP->PacketLength = OrigPacketLength; SRP->PayloadOffset = HeaderLength; // // Save some info for later. // RtlCopyMemory(SRP->EtherDest, OrigEther->Dest, SR_ADDR_LEN); RtlCopyMemory(SRP->EtherSource, OrigEther->Source, SR_ADDR_LEN); RtlCopyMemory(SRP->IV, OrigLQSR->IV, LQSR_IV_LENGTH); // // Increment our counters. // for (Req = SRP->req; Req != NULL; Req = Req->next) InterlockedIncrement((PLONG)&VA->CountRecvRouteRequest); for (Rep = SRP->rep; Rep != NULL; Rep = Rep->next) InterlockedIncrement((PLONG)&VA->CountRecvRouteReply); for (Err = SRP->err; Err != NULL; Err = Err->next) InterlockedIncrement((PLONG)&VA->CountRecvRouteError); for (AckReq = SRP->ackreq; AckReq != NULL; AckReq = AckReq->next) InterlockedIncrement((PLONG)&VA->CountRecvAckRequest); for (Ack = SRP->ack; Ack != NULL; Ack = Ack->next) InterlockedIncrement((PLONG)&VA->CountRecvAck); for (SR = SRP->sr; SR != NULL; SR = SR->next) InterlockedIncrement((PLONG)&VA->CountRecvSourceRoute); for (InfoReq = SRP->inforeq; InfoReq != NULL; InfoReq = InfoReq->next) InterlockedIncrement((PLONG)&VA->CountRecvInfoRequest); for (InfoRep = SRP->inforep; InfoRep != NULL; InfoRep = InfoRep->next) InterlockedIncrement((PLONG)&VA->CountRecvInfoReply); for (Pro = SRP->Probe; Pro != NULL; Pro = Pro->Next) InterlockedIncrement((PLONG)&VA->CountRecvProbe); for (ProRep = SRP->ProbeReply; ProRep != NULL; ProRep = ProRep->Next) InterlockedIncrement((PLONG)&VA->CountRecvProbeReply); for (LI = SRP->LinkInfo; LI != NULL; LI = LI->Next) InterlockedIncrement((PLONG)&VA->CountRecvLinkInfo); *pSRP = SRP; return NDIS_STATUS_SUCCESS; }
//* CheckPacket // // This is a combination of SRPacketFromPkt and FillSRPacket // that just sanity-checks the packet, for debugging purposes. // NDIS_STATUS CheckPacket( MiniportAdapter *VA, NDIS_PACKET *Packet) { uchar MAC[LQSR_MAC_LENGTH]; void *OrigHeader; EtherHeader *OrigEther; LQSRHeader *OrigLQSR; NDIS_BUFFER *OrigBuffer; uint OrigBufferLength; uint HeaderLength; uint OrigPacketLength; LQSROption *Walk; uint Left; // // NB: Below code assumes the entire LQSR header is contiguous. // NdisGetFirstBufferFromPacket(Packet, &OrigBuffer, &OrigHeader, &OrigBufferLength, &OrigPacketLength); ASSERT(OrigBufferLength <= OrigPacketLength); if (OrigBufferLength < sizeof(EtherHeader) + sizeof(LQSRHeader)) { KdPrint(("MCL!CheckPacket: header truncated\n")); return NDIS_STATUS_BUFFER_TOO_SHORT; } OrigEther = (EtherHeader *) OrigHeader; OrigLQSR = (LQSRHeader *) (OrigEther + 1); HeaderLength = (sizeof(EtherHeader) + sizeof(LQSRHeader) + OrigLQSR->HeaderLength); if (OrigBufferLength < HeaderLength) { KdPrint(("MCL!CheckPacket: options truncated\n")); return NDIS_STATUS_BUFFER_TOO_SHORT; } // // Verify the MAC. // SRPacketMAC(VA, MAC, Packet); if (! RtlEqualMemory(MAC, OrigLQSR->MAC, LQSR_MAC_LENGTH)) { KdPrint(("MCL!CheckPacket: bad MAC\n")); return NDIS_STATUS_INVALID_PACKET; } // // Walk the options and verify them. // Walk = (LQSROption *)(OrigLQSR + 1); Left = OrigLQSR->HeaderLength; while (Left != 0) { // // Verify that we have enough data to match what the option // itself claims is present. // if ((Left < sizeof *Walk) || (Left < sizeof *Walk + Walk->optDataLen)) { KdPrint(("MCL!CheckPacket: bad option length\n")); return NDIS_STATUS_INVALID_PACKET; } switch (Walk->optionType) { case LQSR_OPTION_TYPE_REQUEST: // // Route Request options must have at least one hop, // because the sending node includes itself. // if (Walk->optDataLen < ROUTE_REQUEST_LEN(1)) { KdPrint(("MCL!CheckPacket: bad request\n")); return NDIS_STATUS_INVALID_PACKET; } break; case LQSR_OPTION_TYPE_REPLY: // // Route Replies must have at least two hops. // if (Walk->optDataLen < ROUTE_REPLY_LEN(2)) { KdPrint(("MCL!CheckPacket: bad reply\n")); return NDIS_STATUS_INVALID_PACKET; } break; case LQSR_OPTION_TYPE_ERROR: if (Walk->optDataLen != ROUTE_ERROR_LENGTH) { KdPrint(("MCL!CheckPacket: bad error\n")); return NDIS_STATUS_INVALID_PACKET; } break; case LQSR_OPTION_TYPE_SOURCERT: // // Source Routes must have at least two hops. // if (Walk->optDataLen < SOURCE_ROUTE_LEN(2)) { KdPrint(("MCL!CheckPacket: bad SR\n")); return NDIS_STATUS_INVALID_PACKET; } // // Sanity-check segmentsLeft. // if ((((SourceRoute *)Walk)->segmentsLeft == 0) || (((SourceRoute *)Walk)->segmentsLeft >= SOURCE_ROUTE_HOPS(Walk->optDataLen))) { KdPrint(("MCL!CheckPacket: bad segmentsLeft\n")); return NDIS_STATUS_INVALID_PACKET; } break; case LQSR_OPTION_TYPE_ACKREQ: if (Walk->optDataLen != ACK_REQUEST_LEN) { KdPrint(("MCL!CheckPacket: bad ack req\n")); return NDIS_STATUS_INVALID_PACKET; } break; case LQSR_OPTION_TYPE_ACK: if (Walk->optDataLen != ACKNOWLEDGEMENT_LEN) { KdPrint(("MCL!CheckPacket: bad ack\n")); return NDIS_STATUS_INVALID_PACKET; } break; case LQSR_OPTION_TYPE_INFOREQ: if (Walk->optDataLen != INFO_REQUEST_LEN) { KdPrint(("MCL!CheckPacket: bad info req\n")); return NDIS_STATUS_INVALID_PACKET; } break; case LQSR_OPTION_TYPE_INFO: if (Walk->optDataLen != INFO_REPLY_LEN) { KdPrint(("MCL!CheckPacket: bad info reply\n")); return NDIS_STATUS_INVALID_PACKET; } break; case LQSR_OPTION_TYPE_PROBE: // // First, make sure that we have enough // data left to read ProbeType correctly. // if (Walk->optDataLen < PROBE_LEN) { KdPrint(("MCL!CheckPacket: bad probe\n")); return NDIS_STATUS_INVALID_PACKET; } switch (((Probe *)Walk)->ProbeType) { case METRIC_TYPE_RTT: if (Walk->optDataLen != PROBE_LEN) { KdPrint(("MCL!CheckPacket: bad rtt\n")); return NDIS_STATUS_INVALID_PACKET; } break; case METRIC_TYPE_PKTPAIR: if (Walk->optDataLen != PROBE_LEN) { KdPrint(("MCL!CheckPacket: bad pktpair\n")); return NDIS_STATUS_INVALID_PACKET; } break; case METRIC_TYPE_ETX: if (Walk->optDataLen != PROBE_LEN + sizeof(EtxProbe)) { KdPrint(("MCL!CheckPacket: bad etx\n")); return NDIS_STATUS_INVALID_PACKET; } break; default: KdPrint(("MCL!CheckPacket: bad probe type\n")); return NDIS_STATUS_INVALID_PACKET; } break; case LQSR_OPTION_TYPE_PROBEREPLY: // // First, make sure that we have enough // data left to read ProbeType correctly. // if (Walk->optDataLen < PROBE_REPLY_LEN) { KdPrint(("MCL!CheckPacket: bad probe reply\n")); return NDIS_STATUS_INVALID_PACKET; } switch (((Probe *)Walk)->ProbeType) { case METRIC_TYPE_RTT: if (Walk->optDataLen != PROBE_REPLY_LEN) { KdPrint(("MCL!CheckPacket: bad rtt reply\n")); return NDIS_STATUS_INVALID_PACKET; } case METRIC_TYPE_PKTPAIR: if (Walk->optDataLen != PROBE_REPLY_LEN + sizeof(PRPktPair)) { KdPrint(("MCL!CheckPacket: bad pktpair reply\n")); return NDIS_STATUS_INVALID_PACKET; } break; default: KdPrint(("MCL!CheckPacket: bad probe reply type\n")); return NDIS_STATUS_INVALID_PACKET; } break; case LQSR_OPTION_TYPE_LINKINFO: // // LinkInfo options must contain at least one entry. // if (Walk->optDataLen < LINKINFO_LEN(1)) { KdPrint(("MCL!CheckPacket: bad linkinfo\n")); return NDIS_STATUS_INVALID_PACKET; } break; default: KdPrint(("MCL!CheckPacket: bad option type\n")); return NDIS_STATUS_INVALID_PACKET; } // // Move on to the next option (if any). // Left -= sizeof(LQSROption) + Walk->optDataLen; (uchar *)Walk += sizeof(LQSROption) + Walk->optDataLen; } return NDIS_STATUS_SUCCESS; }
INT LpxProtocolReceivePacket ( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ) { PDEVICE_CONTEXT deviceContext; PLPX_RESERVED reserved = NULL; PNDIS_BUFFER ndisFirstBuffer; PVOID firstBuffer; UINT firstBufferSize; UINT totalBufferSize; PNDIS_PACKET packet = NULL; NDIS_STATUS status; INT pktReferenceCount = 0; UINT addiLlcHeaderSize = 0; PLPX_HEADER lpxHeader; USHORT lpxHeaderSize; UINT lpxPayload; UINT rawDataOffset; ETHERNET_HEADER ethernetHeader; DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") ); deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext; // Check to see if the device context is initialized. if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) { DebugPrint( 1, ("Device is not initialized. Drop packet\n") ); return NDIS_STATUS_NOT_RECOGNIZED; } NDAS_ASSERT( deviceContext->NdisBindingHandle ); // validation #ifndef NTDDI_VERSION NdisGetFirstBufferFromPacket( Packet, &ndisFirstBuffer, &firstBuffer, &firstBufferSize, &totalBufferSize ); #else firstBufferSize = 0; NdisGetFirstBufferFromPacketSafe( Packet, &ndisFirstBuffer, &firstBuffer, &firstBufferSize, &totalBufferSize, HighPagePriority ); #endif if (firstBufferSize < ETHERNET_HEADER_LENGTH) { NDAS_ASSERT(FALSE); DebugPrint( 2, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) ); return 0; } RtlCopyMemory( ðernetHeader, firstBuffer, ETHERNET_HEADER_LENGTH ); if (ethernetHeader.DestinationAddress[5] != 0xFF) { DebugPrint( 3, ("LpxProtocolReceivePacket: Type = %X\n", ethernetHeader.Type) ); } // Discard 802.2 LLC SNAP field. // // if Ether Type less than 0x0600 ( 1536 ) if (NTOHS(ethernetHeader.Type) < 0x0600 && NTOHS(ethernetHeader.Type) != 0x0060 && // LOOP: Ethernet Loopback NTOHS(ethernetHeader.Type) != 0x0200 && // PUP : Xerox PUP packet NTOHS(ethernetHeader.Type) != 0x0201) { // PUPAP: Xerox PUP address trans packet RtlCopyMemory( ðernetHeader, (PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2, ETHERNET_HEADER_LENGTH ); if (firstBufferSize >= LENGTH_8022LLCSNAP) { firstBufferSize -= LENGTH_8022LLCSNAP; } else { DebugPrint( 2, ("ProtocolReceivePacket: Too small first buffer\n") ); return 0; } if (totalBufferSize >= LENGTH_8022LLCSNAP) { totalBufferSize -= LENGTH_8022LLCSNAP; } else { DebugPrint( 2, ("ProtocolReceivePacket: Too small total buffer\n") ); return 0; } addiLlcHeaderSize = LENGTH_8022LLCSNAP; NDAS_ASSERT( ethernetHeader.Type != HTONS(ETH_P_LPX) ); } if (ethernetHeader.Type != HTONS(ETH_P_LPX)) { DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", ethernetHeader.Type) ); return 0; } if (totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) { DebugPrint( 2, ("ProtocolReceivePacket: too small packet(1).\n")); return 0; } // DROP PACKET for DEBUGGING!!!! if (PacketRxDropRate) { PacketRxCountForDrop++; if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) { PLPX_HEADER lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize); if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) { DebugPrint( 6, ("[Drop(%x,%x,%x))]\n", NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) ); } DebugPrint( 2, ("D\n") ); return 0; } } if (!(RtlEqualMemory(ethernetHeader.DestinationAddress, deviceContext->LocalAddress.Address, ETHERNET_ADDRESS_LENGTH) || RtlEqualMemory(ethernetHeader.DestinationAddress, LpxBroadcastAddress, ETHERNET_ADDRESS_LENGTH))) { DebugPrint( 4, ("LpxProtocolReceivePacket, %02x%02x%02x%02x%02x%02x\n", deviceContext->LocalAddress.Address[0], deviceContext->LocalAddress.Address[1], deviceContext->LocalAddress.Address[2], deviceContext->LocalAddress.Address[3], deviceContext->LocalAddress.Address[4], deviceContext->LocalAddress.Address[5]) ); DebugPrint( 4, ("LpxProtocolReceivePacket, %02x%02x%02x%02x%02x%02x\n", ethernetHeader.DestinationAddress[0], ethernetHeader.DestinationAddress[1], ethernetHeader.DestinationAddress[2], ethernetHeader.DestinationAddress[3], ethernetHeader.DestinationAddress[4], ethernetHeader.DestinationAddress[5]) ); return 0; } // Extract LPX header information lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize); lpxHeaderSize = sizeof(LPX_HEADER); lpxPayload = NTOHS((UINT16)(lpxHeader->PacketSize & ~LPX_TYPE_MASK)) - lpxHeaderSize; if (lpxHeader->DestinationPort == NTOHS(LPXRP_HIX_PORT)) { DebugPrint( 1, ("[LPX] LpxProtocolReceivePacket: DataGram packet arrived.\n") ); } #if __LPX_OPTION_ADDRESSS__ if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } #endif if (totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) { DebugPrint( 2, ("ProtocolReceivePacket: too small packet(2).\n") ); return 0; } NDAS_ASSERT( addiLlcHeaderSize == 0 ); DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n", totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) ); // If the miniport is out of resources, we can't queue // this packet - make a copy if this is so. NDAS_ASSERT( sizeof(ZeroProtocolReserved) == PROTOCOL_RESERVED_OFFSET ); if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES || !RtlEqualMemory(&Packet->ProtocolReserved[PROTOCOL_RESERVED_OFFSET], ZeroProtocolReserved, sizeof(ZeroProtocolReserved))) { UINT bytesCopied; INT i; for (i=0; i<16; i++) { DebugPrint( 1, ("Packet->ProtocolReserved[%d] = %d\n", i, Packet->ProtocolReserved[i]) ); } NDAS_ASSERT(FALSE); DebugPrint( 2, ("ProtocolReceivePacket: Miniport reported low packet resources.\n") ); status = RcvPacketAlloc( deviceContext, lpxPayload, &packet ); if (status == STATUS_SUCCESS) { NDAS_ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); // Copy lpx payload. payload contains only data. NdisCopyFromPacketToPacket( packet, 0, lpxPayload, Packet, ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize, &bytesCopied ); NDAS_ASSERT( lpxPayload == bytesCopied ); } rawDataOffset = 0; pktReferenceCount = 0; } else { PLPX_RESERVED externalReserved; // No need to allocate new NDIS packet and copy data to the new NDIS packet. // But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context. // We should allocate our own. packet = Packet; status = NdisAllocateMemoryWithTag( &externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED ); if (status == NDIS_STATUS_SUCCESS) { RtlZeroMemory( externalReserved, sizeof(LPX_RESERVED) ); // By setting the external reserved field, LpxGetReserved() uses external reserved context automatically. ((PLPX_RESERVED)(&packet->ProtocolReserved[PROTOCOL_RESERVED_OFFSET]))->ExternalReserved = externalReserved; reserved = LpxGetReserved(packet); // Initialize LPX reserved context instead of RcvPacketAlloc(). reserved->Cloned = 0; reserved->Type = LPX_PACKET_TYPE_RECEIVE; reserved->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT; // set data offset // Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data. rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize; lpxPayload += rawDataOffset; // return one reference count indicating LPX will call NdisReturnPackets() once. pktReferenceCount = 1; } } if (status != NDIS_STATUS_SUCCESS) { DebugPrint( 2, ("ProtocolReceivePacket: status != NDIS_STATUS_SUCCESS\n") ); return 0; } // Init LPX reserved context LpxCopyEthLpxHeadersToLpxReserved( packet, firstBuffer, ethernetHeader.Type, lpxHeader, lpxHeaderSize ); reserved = LpxGetReserved(packet); reserved->Packet = packet; reserved->RecvTime = NdasCurrentTime(); reserved->PacketRawDataLength = lpxPayload; reserved->PacketRawDataOffset = rawDataOffset; // Queue to the device context. ExInterlockedInsertTailList( &deviceContext->PacketInProgressList, &(reserved->ListEntry), &deviceContext->PacketInProgressQSpinLock ); return pktReferenceCount; }
VOID SecLabFreeReceivePacket( PADAPT pAdapt, IN PNDIS_PACKET pNdisPacket ) /*++ Routine Description: 释放所有与接收包相关的资源。如果这是一个本地拷贝,将此包释放到接收包池 。否则释放到miniport. Arguments: pNdisPacket - 指向要释放的包的指针 Return Value: None --*/ { PNDIS_BUFFER pNdisBuffer; UINT TotalLength; UINT BufferLength; PUCHAR pCopyData; if (NdisGetPoolFromPacket(pNdisPacket) ==pAdapt->RecvPacketPoolHandle) { // // This is a local copy. // #ifdef NDIS51 NdisGetFirstBufferFromPacketSafe( pNdisPacket, &pNdisBuffer, (PVOID *)&pCopyData, &BufferLength, &TotalLength, NormalPagePriority); #else NdisGetFirstBufferFromPacket( pNdisPacket, &pNdisBuffer, (PVOID *)&pCopyData, &BufferLength, &TotalLength); #endif if(BufferLength != TotalLength || pNdisBuffer==NULL || pCopyData==NULL) { DbgPrint("Error! Failed in Free a Packet"); DbgBreakPoint(); } NdisFreePacket(pNdisPacket); NdisFreeBuffer(pNdisBuffer); NdisFreeMemory(pCopyData,0,0); } else { NdisReturnPackets(&pNdisPacket, 1); } }