VOID FreeNdisPacket ( PNDIS_PACKET Packet ) /* * FUNCTION: Frees an NDIS packet * ARGUMENTS: * Packet = Pointer to NDIS packet to be freed */ { PNDIS_BUFFER Buffer, NextBuffer; TI_DbgPrint(DEBUG_PBUFFER, ("Packet (0x%X)\n", Packet)); /* Free all the buffers in the packet first */ NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL); for (; Buffer != NULL; Buffer = NextBuffer) { PVOID Data; UINT Length; NdisGetNextBuffer(Buffer, &NextBuffer); NdisQueryBuffer(Buffer, &Data, &Length); TI_DbgPrint(DEBUG_PBUFFER, ("Freeing ndis buffer (0x%X)\n", Buffer)); NdisFreeBuffer(Buffer); TI_DbgPrint(DEBUG_PBUFFER, ("Freeing exal buffer (0x%X)\n", Data)); ExFreePoolWithTag(Data, PACKET_BUFFER_TAG); } /* Finally free the NDIS packet discriptor */ NdisFreePacket(Packet); }
NTSTATUS PacketCancelReadIrps( IN PDEVICE_OBJECT DeviceObject ) { POPEN_INSTANCE open = DeviceObject->DeviceExtension; PLIST_ENTRY thisEntry; PIRP pendingIrp; PNDIS_PACKET myPacket = NULL; PPACKET_RESERVED reserved; PMDL mdl; // DebugPrint(("PacketCancelReadIrps\n")); // Walk through the RcvList and cancel all read IRPs. while( thisEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock )) { reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement); myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); ASSERT(myPacket); pendingIrp = RESERVED(myPacket)->Irp; NdisFreePacket(myPacket); // DebugPrint(("Cancelled : 0%0x\n", pendingIrp)); IoSetCancelRoutine(pendingIrp, NULL); pendingIrp->IoStatus.Information = 0; pendingIrp->IoStatus.Status = STATUS_CANCELLED; IoCompleteRequest(pendingIrp, IO_NO_INCREMENT); IoDecrement(open); } return STATUS_SUCCESS; }
void CAR6KMini::ReturnPacket( IN PNDIS_PACKET Packet) // // After the miniport passes packets up to NDIS via // NdisMIndicateReceivePackets, NDIS will some time later // return those packets (one at a time) to the miniport // by calling this ReturnPacket handler. // { NDIS_BUFFER *pBuffer; A_STATUS status = A_OK; // Remove the NDIS_BUFFER from the packet (should be exactly 1 buffer) NdisUnchainBufferAtFront(Packet, &pBuffer); // Return the NDIS_PACKET to our pool NdisFreePacket(Packet); // Return the pb containing the NDIS_BUFFER to the HTC layer // to receive a new packet ndis_mini_buf_t *pb = (ndis_mini_buf_t *)((PBYTE)pBuffer - offsetof(ndis_mini_buf_t, NdisBuffer)); status = HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb); if ( status != A_OK ) { //HTC did'nt accept the buffer. Free it. a_netbuf_free(pb); } }
/************************************************************ Function called by NDIS to indicate that the data transfer is finished ************************************************************/ VOID NDIS_API PacketSendComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pPacket, IN NDIS_STATUS Status ) { PNDIS_BUFFER pNdisBuffer; PPACKET_RESERVED Reserved = (PPACKET_RESERVED) pPacket->ProtocolReserved; TRACE_ENTER( "SendComplete" ); NdisUnchainBufferAtFront( pPacket, &pNdisBuffer ); if ( pNdisBuffer ) NdisFreeBuffer( pNdisBuffer ); VWIN32_DIOCCompletionRoutine( Reserved->lpoOverlapped->O_Internal ); PacketPageUnlock( Reserved->lpBuffer, Reserved->cbBuffer ); PacketPageUnlock( Reserved->lpcbBytesReturned, sizeof(DWORD) ); PacketPageUnlock( Reserved->lpoOverlapped, sizeof(OVERLAPPED) ); NdisReinitializePacket(pPacket); NdisFreePacket(pPacket); TRACE_LEAVE( "SendComplete" ); return; }
VOID FreeNdisPacketX ( PNDIS_PACKET Packet, PCHAR File, UINT Line ) /* * FUNCTION: Frees an NDIS packet * ARGUMENTS: * Packet = Pointer to NDIS packet to be freed */ { PNDIS_BUFFER Buffer, NextBuffer; TI_DbgPrint(DEBUG_PBUFFER, ("Packet (0x%X)\n", Packet)); /* Free all the buffers in the packet first */ NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL); for (; Buffer != NULL; Buffer = NextBuffer) { PVOID Data; UINT Length; NdisGetNextBuffer(Buffer, &NextBuffer); XNdisQueryBuffer(Buffer, &Data, &Length); UntrackFL(File,Line,Buffer); NdisFreeBuffer(Buffer); exFreePool(Data); } /* Finally free the NDIS packet descriptor */ UntrackFL(File,Line,Packet); NdisFreePacket(Packet); }
VOID ProtocolSendComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pPacket, IN NDIS_STATUS Status ) { OPEN_INSTANCE *pOpen = (OPEN_INSTANCE *)ProtocolBindingContext; PIRP pIrp = RESERVED(pPacket)->pIrp; PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp); // 释放封包 NdisFreePacket(pPacket); // 完成IRP请求 if(Status == NDIS_STATUS_SUCCESS) { pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length; pIrp->IoStatus.Status = STATUS_SUCCESS; DbgPrint(" ProtoDrv: Send data success \n"); } else { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; } IoCompleteRequest(pIrp, IO_NO_INCREMENT); IoDecrement(pOpen); }
VOID MPReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet ) /*++ Routine Description: NDIS Miniport entry point called whenever protocols are done with a packet that we had indicated up and they had queued up for returning later. Arguments: MiniportAdapterContext - pointer to ADAPT structure Packet - packet being returned. Return Value: None. --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; #ifdef NDIS51 // // Packet stacking: Check if this packet belongs to us. // if (NdisGetPoolFromPacket(Packet) != pAdapt->RecvPacketPoolHandle) { // // We reused the original packet in a receive indication. // Simply return it to the miniport below us. // NdisReturnPackets(&Packet, 1); } else #endif // NDIS51 { // // This is a packet allocated from this IM's receive packet pool. // Reclaim our packet, and return the original to the driver below. // PNDIS_PACKET MyPacket; PRECV_RSVD RecvRsvd; RecvRsvd = (PRECV_RSVD)(Packet->MiniportReserved); MyPacket = RecvRsvd->OriginalPkt; NdisFreePacket(Packet); NdisReturnPackets(&MyPacket, 1); } }
void CAR6KMini::car6k_sendEapolKeyMsg (A_UINT8 descType, A_BOOL secure, A_BOOL mic, A_BOOL ack, A_BOOL tx, A_UINT32 index, A_UINT8 isPW, A_BOOL doEncrypt, A_UINT64 keyRSC, const A_UINT8 nonce[], const A_UINT32 keyLength, A_UINT32 keyDataLen, const A_UINT8 *keyData, const A_UINT32 keyBufferLength, A_UINT8 *bssid) { STATION *station; station = GetStation(bssid,0); NDIS_STATUS Status; PNDIS_PACKET pPacket; PNDIS_BUFFER pBuffer; A_UINT32 *magic; A_UINT16 length; memset (m_wpa_buffer, 0 , sizeof (m_wpa_buffer)); crypto_sendEapolKeyMsg ( descType,secure, mic, ack, tx, index, isPW,doEncrypt,keyRSC, nonce,keyLength,keyDataLen, keyData, keyBufferLength, bssid,m_CurrentAddress,m_keyCounter,&replayCtr, station,m_wpa_buffer,&length); NdisAllocatePacket (&Status, &pPacket, m_TxPacketPool); magic = (UINT32 *) pPacket->ProtocolReserved; if (NDIS_STATUS_SUCCESS != Status) { NDIS_DEBUG_PRINTF (ATH_LOG_ERR, "AR6K: ERROR - NdisAllocatePacket failed\n"); return; } NdisAllocateBuffer (&Status, &pBuffer, m_TxBufferPool, m_wpa_buffer, length); if (NDIS_STATUS_SUCCESS != Status) { NdisFreePacket (pPacket); NDIS_DEBUG_PRINTF (ATH_LOG_ERR, "AR6K: ERROR - NdisAllocateBuffer failed\n"); return; } pBuffer->Next = NULL; NdisChainBufferAtFront (pPacket,pBuffer); *(magic) = TAG_WPA_SEND_PCK; SendPackets (&pPacket,1); return; }
NTSTATUS MPIndicatePacket(PHWT_ADAPTER Adapter, PVOID Input, ULONG InputSize, PDEV_RET Output, ULONG OutputSize, PIRP Irp) { PVOID data = NULL; NDIS_STATUS ndis_status = NDIS_STATUS_FAILURE; PNDIS_BUFFER ndis_buffer = NULL; PNDIS_PACKET ndis_packet = NULL; do { data = ExAllocatePoolWithTag(NonPagedPool, InputSize, 'tkpi'); RtlCopyMemory(data, Input, InputSize); NdisAllocateBuffer(&ndis_status, &ndis_buffer, Adapter->AllocateBufferPool, data, InputSize); if (ndis_status != NDIS_STATUS_SUCCESS) break; NdisAllocatePacket(&ndis_status, &ndis_packet, Adapter->AllocatePacketPool); if (ndis_status != NDIS_STATUS_SUCCESS) break; NdisReinitializePacket(ndis_packet); *(PVOID*)ndis_packet->MiniportReserved = data; NdisChainBufferAtBack(ndis_packet, ndis_buffer); NDIS_SET_PACKET_HEADER_SIZE(ndis_packet, sizeof(ETHERNET_HEADER)); NDIS_SET_PACKET_STATUS(ndis_packet, NDIS_STATUS_SUCCESS); NdisMIndicateReceivePacket(Adapter->AdapterHandle, &ndis_packet, 1); Output->hResult = S_OK; ndis_status = NDIS_STATUS_SUCCESS; } while(FALSE); if (ndis_status != NDIS_STATUS_SUCCESS && ndis_status != STATUS_PENDING) { if (ndis_packet) NdisFreePacket(ndis_packet); if (ndis_buffer) NdisFreeBuffer(ndis_buffer); if (data) ExFreePoolWithTag(data, 'tkpi'); } return ndis_status; }
int divert_send_complete(PNDIS_PACKET Pkt) { int rc = 0; lock(); if (NdisGetPoolFromPacket(Pkt) == _packet_pool) { NdisFreePacket(Pkt); rc = 1; } unlock(); return rc; }
/****************************************************************************** * * Name: FreeRxQ() * * Description: Free Rx buffer * * Arguments: PMRVDRV_ADAPTER Adapter * * Return Value: NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE * * Notes: * *****************************************************************************/ NDIS_STATUS FreeRxQ( IN PMRVDRV_ADAPTER Adapter ) { ULONG i; DBGPRINT(DBG_BUF|DBG_RX|DBG_HELP,(L"Free Rx Q\r\n")); for ( i=0; i < MRVDRV_NUM_RX_PKT_IN_QUEUE; i++ ) { if ( Adapter->pRxBufVM[i] != NULL ) { (ULONG)Adapter->pRxBufVM[i] -= MRVDRV_ETH_RX_HIDDEN_HEADER_SIZE; NdisFreeMemory(Adapter->pRxBufVM[i], MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, 0); Adapter->pRxBufVM[i] = NULL; } if ( Adapter->pRxBuffer[i] != NULL ) { NdisFreeBuffer(Adapter->pRxBuffer[i]); Adapter->pRxBuffer[i] = NULL; } if ( Adapter->pRxPacket[i] != NULL ) { NdisFreePacket(Adapter->pRxPacket[i]); Adapter->pRxPacket[i] = NULL; } } if ( Adapter->RxBufferPoolHandle != NULL ) { NdisFreeBufferPool(Adapter->RxBufferPoolHandle); Adapter->RxBufferPoolHandle = NULL; } if ( Adapter->RxPacketPoolHandle != NULL ) { NdisFreePacketPool(Adapter->RxPacketPoolHandle); Adapter->RxPacketPoolHandle = NULL; } return NDIS_STATUS_SUCCESS; }
VOID NDIS_API PacketTransferDataComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pPacket, IN NDIS_STATUS Status, IN UINT BytesTransfered) { // upcall when no more data available POPEN_INSTANCE Open = (POPEN_INSTANCE)ProtocolBindingContext; PPACKET_RESERVED pReserved = (PPACKET_RESERVED)(pPacket->ProtocolReserved); OVERLAPPED * pOverlap = (OVERLAPPED *)(pReserved->lpoOverlapped); PNDIS_BUFFER pNdisBuffer; // free buffer descriptor NdisUnchainBufferAtFront(pPacket, &pNdisBuffer); if (pNdisBuffer) NdisFreeBuffer(pNdisBuffer); // set total bytes returned BytesTransfered += ETHERNET_HEADER_LENGTH; *pReserved->lpcbBytesReturned += BytesTransfered; pOverlap->O_InternalHigh = *(pReserved->lpcbBytesReturned); // The internal member of overlapped structure contains // a pointer to the event structure that will be signalled, // resuming the execution of the waitng GetOverlappedResult // call. VWIN32_DIOCCompletionRoutine(pOverlap->O_Internal); // Unlock buffers PacketPageUnlock(pReserved->lpBuffer, pReserved->cbBuffer); PacketPageUnlock(pReserved->lpcbBytesReturned, sizeof(DWORD)); PacketPageUnlock(pReserved->lpoOverlapped, sizeof(OVERLAPPED)); // recycle the packet NdisReinitializePacket(pPacket); // Put the packet on the free queue NdisFreePacket(pPacket); }
VOID MPReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet) { if (Packet) { PVOID data = NULL; PNDIS_BUFFER ndis_buffer = NULL; data = *(PVOID*)Packet->MiniportReserved; if (data) ExFreePoolWithTag(data, 'tkpi'); while(1) { NdisUnchainBufferAtBack(Packet, &ndis_buffer); if (ndis_buffer) NdisFreeBuffer(ndis_buffer); else break; } NdisFreePacket(Packet); } }
static void shared_free_pkt(ND_PKT* p) { #ifndef NDIS60 PNDIS_BUFFER b; NdisQueryPacket(p, NULL, NULL, &b, NULL); ASSERT(b); NdisFreeBuffer(b); NdisFreePacket(p); #else /* NDIS60 */ PNET_BUFFER nb; PMDL b; nb = NET_BUFFER_LIST_FIRST_NB(p); b = NET_BUFFER_FIRST_MDL(nb); ASSERT(b); NdisFreeMdl(b); NdisFreeNetBufferList(p); #endif /* NDIS60 */ }
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")); }
VOID PacketTransferDataComplete ( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pPacket, IN NDIS_STATUS Status, IN UINT BytesTransfered ) { PIO_STACK_LOCATION irpSp; POPEN_INSTANCE open; PIRP irp; PMDL pMdl; // DebugPrint(("Packet: TransferDataComplete\n")); open = (POPEN_INSTANCE)ProtocolBindingContext; irp = RESERVED(pPacket)->Irp; irpSp = IoGetCurrentIrpStackLocation(irp); pMdl = RESERVED(pPacket)->pMdl; if(pMdl) IoFreeMdl(pMdl); NdisFreePacket(pPacket); if(Status == NDIS_STATUS_SUCCESS) { irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Information = BytesTransfered+ETHERNET_HEADER_LENGTH; } else { irp->IoStatus.Status = STATUS_UNSUCCESSFUL; irp->IoStatus.Information = 0; } // DebugPrint(("BytesTransfered:%d\n", irp->IoStatus.Information)); IoCompleteRequest(irp, IO_NO_INCREMENT); IoDecrement(open); }
VOID MiniportReturnPacket5( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet ) { PADAPTER pAdapt = (PADAPTER)MiniportAdapterContext; // // Packet stacking: Check if this packet belongs to us. // if (MyNdisGetPoolFromPacket(Packet) != pAdapt->RecvPacketPoolHandle) { // // We reused the original packet in a receive indication. // Simply return it to the miniport below us. // NdisReturnPackets(&Packet, 1); } else { // // This is a packet allocated from this IM's receive packet pool. // Reclaim our packet, and return the original to the driver below. // PNDIS_PACKET MyPacket; PRECV_RSVD RecvRsvd; RecvRsvd = (PRECV_RSVD)(Packet->MiniportReserved); MyPacket = RecvRsvd->OriginalPkt; NdisFreePacket(Packet); if(MyPacket) NdisReturnPackets(&MyPacket, 1); } }
// Release the packet buffer void NeoFreePacketBuffer(PACKET_BUFFER *p) { // Validate arguments if (p == NULL) { return; } // Detach the buffer from the packet NdisUnchainBufferAtFront(p->NdisPacket, &p->NdisBuffer); // Release the packet NdisFreePacket(p->NdisPacket); // Release the packet pool NdisFreePacketPool(p->PacketPool); // Release the buffer NdisFreeBuffer(p->NdisBuffer); // Release the memory NeoFree(p->Buf); // Release the buffer pool NdisFreeBufferPool(p->BufferPool); // Release the memory NeoFree(p); }
VOID NDIS_API PacketSendComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pPacket, IN NDIS_STATUS Status) { // upcall on completion of send PNDIS_BUFFER pNdisBuffer; PPACKET_RESERVED Reserved = (PPACKET_RESERVED)pPacket->ProtocolReserved; // free buffer descriptor NdisUnchainBufferAtFront(pPacket, &pNdisBuffer); if (pNdisBuffer) NdisFreeBuffer(pNdisBuffer); // return status Reserved->lpoOverlapped->O_InternalHigh = Status; // The internal member of overlapped structure contains // a pointer to the event structure that will be signalled, // resuming the execution of the waiting GetOverlappedResult // call. VWIN32_DIOCCompletionRoutine(Reserved->lpoOverlapped->O_Internal); // Unlock buffers PacketPageUnlock(Reserved->lpBuffer, Reserved->cbBuffer); PacketPageUnlock(Reserved->lpcbBytesReturned, sizeof(DWORD)); PacketPageUnlock(Reserved->lpoOverlapped, sizeof(OVERLAPPED)); // recycle the packet NdisReinitializePacket(pPacket); // Put the packet back on the free list NdisFreePacket(pPacket); }
INT PacketReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ) { UINT bytesTransfered = 0; POPEN_INSTANCE open; PIRP irp; PNDIS_PACKET myPacket; PLIST_ENTRY packetListEntry; ULONG bufferLength; PPACKET_RESERVED reserved; PIO_STACK_LOCATION irpSp; PMDL mdl; PVOID startAddress; NTSTATUS status; // DebugPrint(("PacketReceivePacket\n")); open = (POPEN_INSTANCE)ProtocolBindingContext; packetListEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock ); if (packetListEntry == NULL) { // DebugPrint(("No pending read, dropping packets\n")); return 0; } reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement); myPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); irp = RESERVED(myPacket)->Irp; irpSp = IoGetCurrentIrpStackLocation(irp); // We don't have to worry about the situation where the IRP is cancelled // after we remove it from the queue and before we reset the cancel // routine because the cancel routine has been coded to cancel an IRP // only if it's in the queue. IoSetCancelRoutine(irp, NULL); // Following block of code locks the destination packet // MDLs in a safe manner. This is a temporary workaround // for NdisCopyFromPacketToPacket that currently doesn't use // safe functions to lock pages of MDL. This is required to // prevent system from bugchecking under low memory resources. // { PVOID virtualAddress; PNDIS_BUFFER firstBuffer, nextBuffer; ULONG totalLength; NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength); while( firstBuffer ) { NdisQueryBufferSafe( firstBuffer, &virtualAddress, &totalLength, NormalPagePriority ); if(!virtualAddress) { status = STATUS_INSUFFICIENT_RESOURCES; goto CleanExit; } NdisGetNextBuffer(firstBuffer, &nextBuffer); firstBuffer = nextBuffer; } } NdisChainBufferAtFront( myPacket, irp->MdlAddress ); bufferLength=irpSp->Parameters.Read.Length; NdisCopyFromPacketToPacket( myPacket, 0, bufferLength, Packet, 0, &bytesTransfered ); CleanExit: NdisFreePacket(myPacket); irp->IoStatus.Status = status; irp->IoStatus.Information = bytesTransfered; IoCompleteRequest(irp, IO_NO_INCREMENT); // DebugPrint(("BytesTransfered:%d\n", bytesTransfered)); IoDecrement(open); return 0; }
VOID MPSendPackets( IN NDIS_HANDLE MiniportAdapterContext, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets ) /*++ Routine Description: Send Packet Array handler. Either this or our SendPacket handler is called based on which one is enabled in our Miniport Characteristics. Arguments: MiniportAdapterContext Pointer to our adapter PacketArray Set of packets to send NumberOfPackets Self-explanatory Return Value: None --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; NDIS_STATUS Status; UINT i; PVOID MediaSpecificInfo = NULL; UINT MediaSpecificInfoSize = 0; for (i = 0; i < NumberOfPackets; i++) { PNDIS_PACKET Packet, MyPacket; ULONG SndFltAction; Packet = PacketArray[i]; // // The driver should fail the send if the virtual miniport is in low // power state // if (pAdapt->MPDeviceState > NdisDeviceStateD0) { NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_FAILURE); continue; } // // Call Send Packet Filter // SndFltAction = FltFilterSendPacket( pAdapt, Packet, FALSE // Caller is running at IRQL <= DISPATCH_LEVEL ); // // Possibly Block (Drop) Packet // ---------------------------- // Lying send. Report SUCCESS, even though it really hasn't // been sent. // if( SndFltAction & ACTION_BLOCK_PACKET ) { NdisMSendComplete( ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_SUCCESS); continue; } #ifdef NDIS51 // // Use NDIS 5.1 packet stacking: // { PNDIS_PACKET_STACK pStack; BOOLEAN Remaining; // // Packet stacks: Check if we can use the same packet for sending down. // pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining); if (Remaining) { // // We can reuse "Packet". // // NOTE: if we needed to keep per-packet information in packets // sent down, we can use pStack->IMReserved[]. // ASSERT(pStack); // // If the below miniport is going to low power state, stop sending down any packet. // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_FAILURE); } else { pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisSend(&Status, pAdapt->BindingHandle, Packet); if (Status != NDIS_STATUS_PENDING) { NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, Status); ADAPT_DECR_PENDING_SENDS(pAdapt); } } continue; } } #endif do { NdisAcquireSpinLock(&pAdapt->Lock); // // If the below miniport is going to low power state, stop sending down any packet. // if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisAllocatePacket(&Status, &MyPacket, pAdapt->SendPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { PSEND_RSVD SendRsvd; SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); SendRsvd->OriginalPkt = Packet; MyPacket->Private.Flags = NdisGetPacketFlags(Packet); MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; #ifdef WIN9X // // Work around the fact that NDIS does not initialize this // to FALSE on Win9x. // MyPacket->Private.ValidCounts = FALSE; #endif // WIN9X // // Copy the OOB data from the original packet to the new // packet. // NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket), NDIS_OOB_DATA_FROM_PACKET(Packet), sizeof(NDIS_PACKET_OOB_DATA)); // // Copy relevant parts of the per packet info into the new packet // #ifndef WIN9X NdisIMCopySendPerPacketInfo(MyPacket, Packet); #endif // // Copy the Media specific information // NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &MediaSpecificInfo, &MediaSpecificInfoSize); if (MediaSpecificInfo || MediaSpecificInfoSize) { NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket, MediaSpecificInfo, MediaSpecificInfoSize); } NdisSend(&Status, pAdapt->BindingHandle, MyPacket); if (Status != NDIS_STATUS_PENDING) { #ifndef WIN9X NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket); #endif NdisFreePacket(MyPacket); ADAPT_DECR_PENDING_SENDS(pAdapt); } } else { // // The driver cannot allocate a packet. // ADAPT_DECR_PENDING_SENDS(pAdapt); } } while (FALSE); if (Status != NDIS_STATUS_PENDING) { NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, Status); } } }
NDIS_STATUS MPSend( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet, IN UINT Flags ) /*++ Routine Description: Send Packet handler. Either this or our SendPackets (array) handler is called based on which one is enabled in our Miniport Characteristics. Arguments: MiniportAdapterContext Pointer to the adapter Packet Packet to send Flags Unused, passed down below Return Value: Return code from NdisSend --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; NDIS_STATUS Status; PNDIS_PACKET MyPacket; PVOID MediaSpecificInfo = NULL; ULONG MediaSpecificInfoSize = 0; ULONG SndFltAction; // // The driver should fail the send if the virtual miniport is in low // power state // if (pAdapt->MPDeviceState > NdisDeviceStateD0) { return NDIS_STATUS_FAILURE; } // // Call Send Packet Filter // SndFltAction = FltFilterSendPacket( pAdapt, Packet, TRUE // Caller is running at IRQL DISPATCH_LEVEL ); // // Possibly Block (Drop) Packet // ---------------------------- // Lying send. Report SUCCESS, even though it really hasn't // been sent. // if( SndFltAction & ACTION_BLOCK_PACKET) { return NDIS_STATUS_SUCCESS; } #ifdef NDIS51 // // Use NDIS 5.1 packet stacking: // { PNDIS_PACKET_STACK pStack; BOOLEAN Remaining; // // Packet stacks: Check if we can use the same packet for sending down. // pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining); if (Remaining) { // // We can reuse "Packet". // // NOTE: if we needed to keep per-packet information in packets // sent down, we can use pStack->IMReserved[]. // ASSERT(pStack); // // If the below miniport is going to low power state, stop sending down any packet. // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); return NDIS_STATUS_FAILURE; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisSend(&Status, pAdapt->BindingHandle, Packet); if (Status != NDIS_STATUS_PENDING) { ADAPT_DECR_PENDING_SENDS(pAdapt); } return(Status); } } #endif // NDIS51 // // We are either not using packet stacks, or there isn't stack space // in the original packet passed down to us. Allocate a new packet // to wrap the data with. // // // If the below miniport is going to low power state, stop sending down any packet. // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); return NDIS_STATUS_FAILURE; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisAllocatePacket(&Status, &MyPacket, pAdapt->SendPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { PSEND_RSVD SendRsvd; // // Save a pointer to the original packet in our reserved // area in the new packet. This is needed so that we can // get back to the original packet when the new packet's send // is completed. // SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); SendRsvd->OriginalPkt = Packet; MyPacket->Private.Flags = Flags; // // Set up the new packet so that it describes the same // data as the original packet. // MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; #ifdef WIN9X // // Work around the fact that NDIS does not initialize this // to FALSE on Win9x. // MyPacket->Private.ValidCounts = FALSE; #endif // // Copy the OOB Offset from the original packet to the new // packet. // NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket), NDIS_OOB_DATA_FROM_PACKET(Packet), sizeof(NDIS_PACKET_OOB_DATA)); #ifndef WIN9X // // Copy the right parts of per packet info into the new packet. // This API is not available on Win9x since task offload is // not supported on that platform. // NdisIMCopySendPerPacketInfo(MyPacket, Packet); #endif // // Copy the Media specific information // NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &MediaSpecificInfo, &MediaSpecificInfoSize); if (MediaSpecificInfo || MediaSpecificInfoSize) { NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket, MediaSpecificInfo, MediaSpecificInfoSize); } NdisSend(&Status, pAdapt->BindingHandle, MyPacket); if (Status != NDIS_STATUS_PENDING) { #ifndef WIN9X NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket); #endif NdisFreePacket(MyPacket); ADAPT_DECR_PENDING_SENDS(pAdapt); } } else { ADAPT_DECR_PENDING_SENDS(pAdapt); // // We are out of packets. Silently drop it. Alternatively we can deal with it: // - By keeping separate send and receive pools // - Dynamically allocate more pools as needed and free them when not needed // } return(Status); }
VOID PacketFree2 ( IN PNDIS_PACKET Packet ) { PLPX_RESERVED reserved = RESERVED(Packet); PUCHAR packetData; PNDIS_BUFFER pNdisBuffer; UINT uiLength; LONG clone; LONG BufferSeq; BOOLEAN allocMiniport = FALSE; PLPX_RESERVED externalReserved; DebugPrint( 3, ("PacketFree reserved->type = %d\n", reserved->Type) ); ASSERT( Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); switch (reserved->Type) { case LPX_PACKET_TYPE_SEND: clone = InterlockedDecrement( &reserved->Cloned ); if(clone >= 0) { return; } pNdisBuffer = NULL; BufferSeq = 0; NdisUnchainBufferAtFront( Packet, &pNdisBuffer ); while (pNdisBuffer) { // // Assuming the first data buffer comes from user application // the others are created in LPX for padding, etc. // Free the memory of the others. // if (BufferSeq == 0) { #if DBG NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); ASSERT( packetData == (PCHAR)&RESERVED(Packet)->EthernetHeader ); #endif } else if (BufferSeq == 1) { // UserBuffer } else if (BufferSeq == 2) { // Padding NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); LpxFreeMemoryWithLpxTag( packetData ); } else { ASSERT( FALSE ); } NdisFreeBuffer( pNdisBuffer ); pNdisBuffer = NULL; NdisUnchainBufferAtFront( Packet, &pNdisBuffer ); BufferSeq ++; } if (reserved->IrpSp != NULL) { PIRP _Irp = IRP_SEND_IRP( reserved->IrpSp ); ASSERT( reserved->NdisStatus == NDIS_STATUS_SUCCESS || reserved->NdisStatus == NDIS_STATUS_NOT_ACCEPTED || !NT_SUCCESS(reserved->NdisStatus) ); if (!NT_SUCCESS(reserved->NdisStatus)) { _Irp->IoStatus.Status = reserved->NdisStatus; } //INC_IRP_RETRANSMITS( _Irp, reserved->Retransmits ); LpxDereferenceSendIrp( "Destroy packet", reserved->IrpSp, RREF_PACKET ); } else { DebugPrint( 3, ("[LPX] PacketFree: No IrpSp\n") ) ; } break; case LPX_PACKET_TYPE_RECEIVE: // // If the packet allocated by NIC miniport, break here. // if(RESERVED(Packet)->RecvFlags & LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT) { allocMiniport = TRUE; break; } pNdisBuffer = NULL; NdisUnchainBufferAtFront( Packet, &pNdisBuffer ); #if __LPX_STATISTICS__ { LARGE_INTEGER systemTime; KeQuerySystemTime( &systemTime ); RESERVED(Packet)->DeviceContext->NumberOfRecvPackets ++; RESERVED(Packet)->DeviceContext->FreeTimeOfRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart; RESERVED(Packet)->DeviceContext->BytesOfRecvPackets.QuadPart += sizeof(LPX_HEADER) + RESERVED(Packet)->PacketRawDataLength; if (RESERVED(Packet)->PacketRawDataLength) { RESERVED(Packet)->DeviceContext->NumberOfLargeRecvPackets ++; RESERVED(Packet)->DeviceContext->FreeTimeOfLargeRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart; RESERVED(Packet)->DeviceContext->BytesOfLargeRecvPackets.QuadPart += sizeof(LPX_HEADER) + RESERVED(Packet)->PacketRawDataLength; } else { RESERVED(Packet)->DeviceContext->NumberOfSmallRecvPackets ++; RESERVED(Packet)->DeviceContext->FreeTimeOfSmallRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart; RESERVED(Packet)->DeviceContext->BytesOfSmallRecvPackets.QuadPart += sizeof(LPX_HEADER); } } #endif if (pNdisBuffer) { NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); LpxFreeMemoryWithLpxTag( packetData ); NdisFreeBuffer( pNdisBuffer ); } break; default: ASSERT(FALSE); return; } // // Free external protocol reserved context. // externalReserved = ((PLPX_RESERVED)(Packet->ProtocolReserved))->ExternalReserved; if(externalReserved) { NdisFreeMemory(externalReserved, sizeof(LPX_RESERVED), 0); } ASSERT( Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); if(allocMiniport) { // // Return the packet allocated by NIC miniport // NdisReturnPackets(&Packet, 1); } else { NdisFreePacket( Packet ); InterlockedDecrement( &NumberOfAllockPackets ); DebugPrint( 3, ("Packet REALLY Freed NumberOfAllockPackets = %d\n", NumberOfAllockPackets) ); } }
NTSTATUS divert_write( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { int rc = STATUS_SUCCESS; PNDIS_PACKET pNdisPacket; PADAPT pa = _pa, pa2; // XXX NDIS_STATUS status; PIO_STACK_LOCATION pIrpSp; NDISPROT_ETH_HEADER UNALIGNED *pEthHeader; pIrpSp = IoGetCurrentIrpStackLocation(pIrp); if (pIrp->MdlAddress == NULL) { rc = STATUS_INSUFFICIENT_RESOURCES; goto Out; } if (!(pEthHeader = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority))) { rc = STATUS_INSUFFICIENT_RESOURCES; goto Out; } lock(); NdisAllocatePacket(&status, &pNdisPacket, _packet_pool); unlock(); if (status != STATUS_SUCCESS) { rc = STATUS_INSUFFICIENT_RESOURCES; goto Out; } NdisChainBufferAtFront(pNdisPacket, pIrp->MdlAddress); if ((pa2 = get_pa(pEthHeader->SrcAddr))) { NdisSendPackets(pa2->BindingHandle, &pNdisPacket, 1); } else { pa2 = get_pa(pEthHeader->DstAddr); if (pa2) pa = pa2; NDIS_SET_PACKET_STATUS(pNdisPacket, NDIS_STATUS_RESOURCES); NdisMIndicateReceivePacket(pa->MiniportHandle, &pNdisPacket, 1); NdisFreePacket(pNdisPacket); } rc = STATUS_PENDING; rc = STATUS_SUCCESS; Out: pIrp->IoStatus.Status = rc; if (rc != STATUS_PENDING) { pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } return rc; }
int divert_filter( IN PADAPT pAdapt, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize ) { #define MAC_SIZE 14 USHORT EtherType; ULONG NumberOfBytesRead; struct ether_header *pEthHdr; // See ../B2Winet/ethernet.h struct ip *pIPHeader; struct tcphdr *tcp; int rc = 0; struct divert_packet *dp, *cur; NDISPROT_ETH_HEADER UNALIGNED *pEthHeader; NdisDprAcquireSpinLock(&pAdapt->Lock); pEthHdr = (struct ether_header * )HeaderBuffer; pEthHeader = pEthHdr; if (ntohs( pEthHdr->ether_type ) != ETHERTYPE_IP) goto Out; if (get_pa(pEthHeader->SrcAddr)) goto Out; pIPHeader = (struct ip * )LookAheadBuffer; if (LookAheadBufferSize < 40) goto Out; if (pIPHeader->ip_p != IPPROTO_TCP) goto Out; tcp = (struct tcphr*) (pIPHeader + 1); #if 0 if (ntohs(tcp->th_dport) == 666) rc = 1; #endif lock(); if (!_open) goto Outl; dp = get_packet(); if (!dp) { DbgPrint("Out of queue - shit\n"); goto Outl; } if (LookAheadBufferSize != PacketSize) { NDIS_STATUS status; PNDIS_PACKET pkt; PNDIS_BUFFER buf; int len; if ((PacketSize + MAC_SIZE) > sizeof(dp->dp_packet)) { DbgPrint("cAZZOOOOOOOOOOOOOOOOOOOOOOOOOOo\n"); goto Fanculo; } NdisAllocatePacket(&status, &pkt, _packet_pool); NdisAllocateBuffer(&status, &buf, _buf_pool, dp->dp_packet + MAC_SIZE, sizeof(dp->dp_packet) - MAC_SIZE); NdisChainBufferAtFront(pkt, buf); NdisTransferData(&status, pAdapt->BindingHandle, MacReceiveContext, 0, PacketSize, pkt, &len); NdisFreeBuffer(buf); NdisFreePacket(pkt); } else { NdisCopyLookaheadData(dp->dp_packet + MAC_SIZE, LookAheadBuffer, LookAheadBufferSize, 0); } Fanculo: rc = 1; memcpy(dp->dp_packet, pEthHdr, MAC_SIZE); dp->dp_len = PacketSize + MAC_SIZE; dp->dp_flags = 1; kick_pending(); Outl: unlock(); Out: NdisDprReleaseSpinLock(&pAdapt->Lock); return rc; #undef MAC_SIZE }
NTSTATUS NdisProtWrite( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) /*++ Routine Description: Dispatch routine to handle IRP_MJ_WRITE. Arguments: pDeviceObject - pointer to our device object pIrp - Pointer to request packet Return Value: NT status code. --*/ { PIO_STACK_LOCATION pIrpSp; ULONG DataLength; NTSTATUS NtStatus; NDIS_STATUS Status; PNDISPROT_OPEN_CONTEXT pOpenContext; PNDIS_PACKET pNdisPacket; PNDIS_BUFFER pNdisBuffer; NDISPROT_ETH_HEADER UNALIGNED *pEthHeader; #ifdef NDIS51 PVOID CancelId; #endif UNREFERENCED_PARAMETER(pDeviceObject); pIrpSp = IoGetCurrentIrpStackLocation(pIrp); pOpenContext = pIrpSp->FileObject->FsContext; pNdisPacket = NULL; do { if (pOpenContext == NULL) { DEBUGP(DL_WARN, ("Write: FileObject %p not yet associated with a device\n", pIrpSp->FileObject)); NtStatus = STATUS_INVALID_HANDLE; break; } NPROT_STRUCT_ASSERT(pOpenContext, oc); if (pIrp->MdlAddress == NULL) { DEBUGP(DL_FATAL, ("Write: NULL MDL address on IRP %p\n", pIrp)); NtStatus = STATUS_INVALID_PARAMETER; break; } // // Try to get a virtual address for the MDL. // pEthHeader = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); if (pEthHeader == NULL) { DEBUGP(DL_FATAL, ("Write: MmGetSystemAddr failed for" " IRP %p, MDL %p\n", pIrp, pIrp->MdlAddress)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; } // // Sanity-check the length. // DataLength = MmGetMdlByteCount(pIrp->MdlAddress); if (DataLength < sizeof(NDISPROT_ETH_HEADER)) { DEBUGP(DL_WARN, ("Write: too small to be a valid packet (%d bytes)\n", DataLength)); NtStatus = STATUS_BUFFER_TOO_SMALL; break; } if (DataLength > (pOpenContext->MaxFrameSize + sizeof(NDISPROT_ETH_HEADER))) { DEBUGP(DL_WARN, ("Write: Open %p: data length (%d)" " larger than max frame size (%d)\n", pOpenContext, DataLength, pOpenContext->MaxFrameSize)); NtStatus = STATUS_INVALID_BUFFER_SIZE; break; } // // To prevent applications from sending packets with spoofed // mac address, we will do the following check to make sure the source // address in the packet is same as the current MAC address of the NIC. // if ((pIrp->RequestorMode == UserMode) && !NPROT_MEM_CMP(pEthHeader->SrcAddr, pOpenContext->CurrentAddress, NPROT_MAC_ADDR_LEN)) { DEBUGP(DL_WARN, ("Write: Failing with invalid Source address")); NtStatus = STATUS_INVALID_PARAMETER; break; } NPROT_ACQUIRE_LOCK(&pOpenContext->Lock); if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE)) { NPROT_RELEASE_LOCK(&pOpenContext->Lock); DEBUGP(DL_FATAL, ("Write: Open %p is not bound" " or in low power state\n", pOpenContext)); NtStatus = STATUS_INVALID_HANDLE; break; } // // Allocate a send packet. // NPROT_ASSERT(pOpenContext->SendPacketPool != NULL); NdisAllocatePacket( &Status, &pNdisPacket, pOpenContext->SendPacketPool); if (Status != NDIS_STATUS_SUCCESS) { NPROT_RELEASE_LOCK(&pOpenContext->Lock); DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send pkt\n", pOpenContext)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; } // // Allocate a send buffer if necessary. // if (pOpenContext->bRunningOnWin9x) { NdisAllocateBuffer( &Status, &pNdisBuffer, pOpenContext->SendBufferPool, pEthHeader, DataLength); if (Status != NDIS_STATUS_SUCCESS) { NPROT_RELEASE_LOCK(&pOpenContext->Lock); NdisFreePacket(pNdisPacket); DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send buf\n", pOpenContext)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; } } else { pNdisBuffer = pIrp->MdlAddress; } NdisInterlockedIncrement((PLONG)&pOpenContext->PendedSendCount); NPROT_REF_OPEN(pOpenContext); // pended send IoMarkIrpPending(pIrp); // // Initialize the packet ref count. This packet will be freed // when this count goes to zero. // NPROT_SEND_PKT_RSVD(pNdisPacket)->RefCount = 1; #ifdef NDIS51 // // NDIS 5.1 supports cancelling sends. We set up a cancel ID on // each send packet (which maps to a Write IRP), and save the // packet pointer in the IRP. If the IRP gets cancelled, we use // NdisCancelSendPackets() to cancel the packet. // CancelId = NPROT_GET_NEXT_CANCEL_ID(); NDIS_SET_PACKET_CANCEL_ID(pNdisPacket, CancelId); pIrp->Tail.Overlay.DriverContext[0] = (PVOID)pOpenContext; pIrp->Tail.Overlay.DriverContext[1] = (PVOID)pNdisPacket; NPROT_INSERT_TAIL_LIST(&pOpenContext->PendedWrites, &pIrp->Tail.Overlay.ListEntry); IoSetCancelRoutine(pIrp, NdisProtCancelWrite); #endif // NDIS51 NPROT_RELEASE_LOCK(&pOpenContext->Lock); // // Set a back pointer from the packet to the IRP. // NPROT_IRP_FROM_SEND_PKT(pNdisPacket) = pIrp; NtStatus = STATUS_PENDING; pNdisBuffer->Next = NULL; NdisChainBufferAtFront(pNdisPacket, pNdisBuffer); #if SEND_DBG { PUCHAR pData; pData = MmGetSystemAddressForMdlSafe(pNdisBuffer, NormalPagePriority); NPROT_ASSERT(pEthHeader == pData); DEBUGP(DL_VERY_LOUD, ("Write: MDL %p, MdlFlags %x, SystemAddr %p, %d bytes\n", pIrp->MdlAddress, pIrp->MdlAddress->MdlFlags, pData, DataLength)); DEBUGPDUMP(DL_VERY_LOUD, pData, MIN(DataLength, 48)); } #endif // SEND_DBG NdisSendPackets(pOpenContext->BindingHandle, &pNdisPacket, 1); } while (FALSE); if (NtStatus != STATUS_PENDING) { pIrp->IoStatus.Status = NtStatus; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } return (NtStatus); }
NTSTATUS SendPacketAlloc ( IN PDEVICE_CONTEXT DeviceContext, IN PTP_ADDRESS Address, IN UCHAR DestinationAddressNode[], IN PUCHAR UserData, IN ULONG UserDataLength, IN PIO_STACK_LOCATION IrpSp, IN UCHAR Option, OUT PNDIS_PACKET *Packet ) { NTSTATUS status; PUCHAR packetHeader = NULL; PNDIS_BUFFER packetHeaderBuffer = NULL; ULONG packetHeaderLength; PNDIS_BUFFER userDataBuffer = NULL; PUCHAR paddingData = NULL; PNDIS_BUFFER paddingDataBuffer = NULL; PNDIS_PACKET packet = NULL; USHORT etherType; packetHeaderLength = ETHERNET_HEADER_LENGTH + sizeof(LPX_HEADER); #if __LPX_OPTION_ADDRESSS__ if (FlagOn(Option, LPX_OPTION_SOURCE_ADDRESS)) { packetHeaderLength += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(Option, LPX_OPTION_DESTINATION_ADDRESS)) { packetHeaderLength += ETHERNET_ADDRESS_LENGTH; } #endif ASSERT( packetHeaderLength + UserDataLength <= ETHERNET_HEADER_LENGTH + DeviceContext->MaxUserData ); DebugPrint( 3, ("SendPacketAlloc, packetHeaderLength = %d, NumberOfAllockPackets = %d\n", packetHeaderLength, NumberOfAllockPackets) ); ASSERT( DeviceContext ); ASSERT( DeviceContext->LpxPacketPool != NULL ); do { NdisAllocatePacket( &status, &packet, DeviceContext->LpxPacketPool ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( FALSE ); LPX_ASSERT( status == NDIS_STATUS_RESOURCES ); return status; } RtlZeroMemory( RESERVED(packet), sizeof(LPX_RESERVED) ); ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); packetHeader = (PCHAR)&RESERVED(packet)->EthernetHeader; NdisAllocateBuffer( &status, &packetHeaderBuffer, DeviceContext->LpxBufferPool, packetHeader, packetHeaderLength ); if (!NT_SUCCESS(status)) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } if (UserData && UserDataLength) { NdisAllocateBuffer( &status, &userDataBuffer, DeviceContext->LpxBufferPool, UserData, UserDataLength ); if(!NT_SUCCESS(status)) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } } ////////////////////////////////////////////////////////////////////////// // // Add padding to fix Under-60byte bug of NDAS chip 2.0. // if (packetHeaderLength == ETHERNET_HEADER_LENGTH + sizeof(LPX_HEADER)) { UINT totalPacketLength; totalPacketLength = packetHeaderLength + UserDataLength; if (totalPacketLength >= ETHERNET_HEADER_LENGTH + sizeof(LPX_HEADER) + 4 && totalPacketLength <= 56) { LONG paddingLen = 60 - totalPacketLength; DebugPrint( 4, ("[LpxSmp]TransmitDataPacket: Adding padding to support NDAS chip 2.0\n") ); status = LpxAllocateMemoryWithLpxTag( &paddingData, paddingLen ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } NdisAllocateBuffer( &status, &paddingDataBuffer, DeviceContext->LpxBufferPool, paddingData, paddingLen ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } RtlZeroMemory( paddingData, paddingLen ); RtlCopyMemory( paddingData + paddingLen - 4, UserData + UserDataLength - 4, 4 ); } } // // End of padding routine. // ////////////////////////////////////////////////////////////////////////// } while(0); if (status == STATUS_SUCCESS) { RtlCopyMemory( &packetHeader[0], DestinationAddressNode, ETHERNET_ADDRESS_LENGTH ); RtlCopyMemory( &packetHeader[ETHERNET_ADDRESS_LENGTH], Address->NetworkName->Node, ETHERNET_ADDRESS_LENGTH ); etherType = HTONS( ETH_P_LPX ); RtlCopyMemory( &packetHeader[ETHERNET_ADDRESS_LENGTH*2], ðerType, 2 ); #if __LPX_OPTION_ADDRESSS__ if (FlagOn(Option, LPX_OPTION_DESTINATION_ADDRESS)) { RtlCopyMemory( RESERVED(packet)->OptionDestinationAddress, DestinationAddressNode, ETHERNET_ADDRESS_LENGTH ); } if (FlagOn(Option, LPX_OPTION_SOURCE_ADDRESS)) { if (FlagOn(Option, LPX_OPTION_DESTINATION_ADDRESS)) { RtlCopyMemory( RESERVED(packet)->OptionSourceAddress, Address->NetworkName->Node, ETHERNET_ADDRESS_LENGTH ); } else { RtlCopyMemory( RESERVED(packet)->OptionDestinationAddress, Address->NetworkName->Node, ETHERNET_ADDRESS_LENGTH ); } } #endif RESERVED(packet)->LpxHeader.PacketSize = HTONS( (USHORT)(packetHeaderLength - ETHERNET_HEADER_LENGTH + UserDataLength) ); RESERVED(packet)->LpxHeader.Option = Option; RESERVED(packet)->Cloned = 0; RESERVED(packet)->IrpSp = IrpSp; RESERVED(packet)->Type = LPX_PACKET_TYPE_SEND; RESERVED(packet)->Packet = packet; if (IrpSp == NULL) { DebugPrint( 3, ("[LPX] PacketAllocate: No IrpSp\n") ) ; } if (paddingDataBuffer) NdisChainBufferAtFront( packet, paddingDataBuffer ); if (userDataBuffer) NdisChainBufferAtFront( packet, userDataBuffer ); NdisChainBufferAtFront( packet, packetHeaderBuffer ); InterlockedIncrement( &NumberOfAllockPackets ); *Packet = packet; } else { if (paddingDataBuffer) NdisFreeBuffer( paddingDataBuffer ); if( paddingData) LpxFreeMemoryWithLpxTag( paddingData ); if (userDataBuffer) NdisFreeBuffer( userDataBuffer ); if (packetHeaderBuffer) NdisFreeBuffer( packetHeaderBuffer ); if (packet) NdisFreePacket( packet ); *Packet = NULL; DebugPrint( 1, ("[LPX]PacketAllocate: Can't Allocate Buffer For CopyData!!!\n") ); } return status; }
VOID PacketCancelRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { POPEN_INSTANCE open = DeviceObject->DeviceExtension; KIRQL oldIrql; PIRP irpToComplete = NULL; PLIST_ENTRY thisEntry, listHead; PIRP pendingIrp; PNDIS_PACKET myPacket = NULL; PPACKET_RESERVED reserved; PMDL mdl; // Don't assume that the IRP being cancelled is in the queue. // Only complete the IRP if it IS in the queue. // // Must acquire the local spinlock before releasing // the global cancel spinlock // // DebugPrint(("PacketCancelRoutine\n")); oldIrql = Irp->CancelIrql; // One should not intermix KeAcquireSpinLock(AtDpcLevel) // and ExInterlocked...List() functions on the same spinlock if the // routines that use the lock run at IRQL > DISPATCH_LEVEL. // After acquiring the lock using Ke function, if we got interrupted // and entered into an ISR and tried to manipulate the list using // ExInterlocked...List function with the same lock, we deadlock. // In this sample we can safely do that because none of our routines // will be called at IRQL > DISPATCH_LEVEL. KeAcquireSpinLockAtDpcLevel(&open->RcvQSpinLock); IoReleaseCancelSpinLock( KeGetCurrentIrql() ); listHead = &open->RcvList; for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink ) { reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement); myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); pendingIrp = RESERVED(myPacket)->Irp; if (pendingIrp == Irp) { RemoveEntryList(thisEntry); irpToComplete = pendingIrp; break; } } KeReleaseSpinLock(&open->RcvQSpinLock, oldIrql); if(irpToComplete) { // DebugPrint(("Cancelling IRP\n")); // ASSERT(myPacket); NdisFreePacket(myPacket); irpToComplete->IoStatus.Status = STATUS_CANCELLED; irpToComplete->IoStatus.Information = 0; IoCompleteRequest(irpToComplete, IO_NO_INCREMENT); IoDecrement(open); } }
/*+ * * FreeAdapterMemory * * Routine Description: * * Frees the memory previously allocated by * AllocateAdapterMemory * * Arguments: * * Adapter - The adapter to deallocate memory for. * * Return Value: * * None. * -*/ extern VOID FreeAdapterMemory( IN PDC21X4_ADAPTER Adapter ) { PDC21X4_RECEIVE_DESCRIPTOR ReceiveDescriptor; PRCV_HEADER RcvHeader; PNDIS_PACKET Packet; UINT i; if ((PVOID)Adapter->DescriptorRing.AllocVa == (PVOID)NULL) { // AllocateAdapterMemory failed on the first allocation: // no ressources were allocated return; } for (i = 0, ReceiveDescriptor = (PDC21X4_RECEIVE_DESCRIPTOR)Adapter->ReceiveDescriptorRingVa; i < Adapter->ReceiveRingSize; i++, (PCHAR)ReceiveDescriptor += Adapter->DescriptorSize ) { if (ReceiveDescriptor->RcvHeader) { RcvHeader = ReceiveDescriptor->RcvHeader; if (RcvHeader->FlushBuffer) { NdisFreeBuffer(RcvHeader->FlushBuffer); } if (RcvHeader->Packet) { NdisFreePacket(RcvHeader->Packet); } if (!Adapter->RcvBufferSpace.Va) { NdisMFreeSharedMemory( Adapter->MiniportAdapterHandle, RcvHeader->AllocSize, TRUE, (PVOID)RcvHeader->AllocVa, RcvHeader->AllocPa ); } } } while (Adapter->FreeRcvList != NULL) { RcvHeader = Adapter->FreeRcvList; Adapter->FreeRcvList = RcvHeader->Next; if (RcvHeader->FlushBuffer) { NdisFreeBuffer(RcvHeader->FlushBuffer); } if ( !Adapter->RcvBufferSpace.Va && RcvHeader->AllocVa) { NdisMFreeSharedMemory( Adapter->MiniportAdapterHandle, RcvHeader->AllocSize, TRUE, (PVOID)RcvHeader->AllocVa, RcvHeader->AllocPa ); } } while (Adapter->FreePacketList != NULL) { Packet = Adapter->FreePacketList; Adapter->FreePacketList = RCV_RESERVED(Packet)->Next; if (NULL != Packet) { NdisFreePacket(Packet); } } if (Adapter->RcvBufferSpace.Va) { NdisMFreeSharedMemory( Adapter->MiniportAdapterHandle, Adapter->RcvBufferSpace.AllocSize, TRUE, (PVOID)Adapter->RcvBufferSpace.AllocVa, Adapter->RcvBufferSpace.AllocPa ); } if (Adapter->ReceivePacketPool) { NdisFreePacketPool((PVOID)Adapter->ReceivePacketPool); } for (i = 0; i < DC21X4_NUMBER_OF_MAX_TRANSMIT_BUFFERS;i ++ ) { if (Adapter->MaxTransmitBuffer[i].AllocVa) { NdisMFreeSharedMemory( Adapter->MiniportAdapterHandle, Adapter->MaxTransmitBuffer[i].AllocSize, TRUE, (PVOID)Adapter->MaxTransmitBuffer[i].AllocVa, Adapter->MaxTransmitBuffer[i].AllocPa ); } if (Adapter->MaxTransmitBuffer[i].FlushBuffer) { NdisFreeBuffer(Adapter->MaxTransmitBuffer[i].FlushBuffer); } } if (Adapter->MinTransmitBuffer[0].AllocVa && !Adapter->DontUseMinTransmitBuffer) { NdisMFreeSharedMemory( Adapter->MiniportAdapterHandle, Adapter->MinTransmitBuffer[0].AllocSize, TRUE, (PVOID)Adapter->MinTransmitBuffer[0].AllocVa, Adapter->MinTransmitBuffer[0].AllocPa ); } for (i = 0; i < DC21X4_NUMBER_OF_MIN_TRANSMIT_BUFFERS;i ++ ) { if (Adapter->MinTransmitBuffer[i].FlushBuffer) { NdisFreeBuffer(Adapter->MinTransmitBuffer[i].FlushBuffer); } } if (Adapter->FlushBufferPoolHandle) { NdisFreeBufferPool(Adapter->FlushBufferPoolHandle); } if (Adapter->DescriptorRing.AllocVa) { NdisMFreeSharedMemory( Adapter->MiniportAdapterHandle, Adapter->DescriptorRing.AllocSize, FALSE, (PVOID)Adapter->DescriptorRing.AllocVa, Adapter->DescriptorRing.AllocPa ); } }
NTSTATUS RcvPacketAlloc ( IN PDEVICE_CONTEXT DeviceContext, IN ULONG PacketDataLength, OUT PNDIS_PACKET *Packet ) { NTSTATUS status; PUCHAR packetData = NULL; PNDIS_BUFFER packetDataBuffer = NULL; PNDIS_PACKET packet = NULL; DebugPrint( 3, ("RcvPacketAlloc, PacketLength = %d, NumberOfAllockPackets = %d\n", PacketDataLength, NumberOfAllockPackets) ); ASSERT( DeviceContext ); ASSERT( DeviceContext->LpxPacketPool != NULL ); ASSERT( PacketDataLength <= DeviceContext->MaxUserData ); do { NdisAllocatePacket( &status, &packet, DeviceContext->LpxPacketPool ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( status == NDIS_STATUS_RESOURCES ); ASSERT( FALSE ); return status; } RtlZeroMemory( RESERVED(packet), sizeof(LPX_RESERVED) ); ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); if (PacketDataLength) { status = LpxAllocateMemoryWithLpxTag( &packetData, PacketDataLength ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } NdisAllocateBuffer( &status, &packetDataBuffer, DeviceContext->LpxBufferPool, packetData, PacketDataLength ); if (!NT_SUCCESS(status)) { ASSERT( status == NDIS_STATUS_FAILURE ); ASSERT( FALSE ); break; } NdisChainBufferAtFront( packet, packetDataBuffer ); } } while(0); if (status == STATUS_SUCCESS) { RESERVED(packet)->Cloned = 0; RESERVED(packet)->Type = LPX_PACKET_TYPE_RECEIVE; RESERVED(packet)->Packet = packet; InterlockedIncrement( &NumberOfAllockPackets ); *Packet = packet; #if __LPX_STATISTICS__ KeQuerySystemTime( &RESERVED(packet)->RecvTime2 ); RESERVED(packet)->DeviceContext = DeviceContext; #endif } else { if (packetDataBuffer) NdisFreeBuffer( packetDataBuffer ); if (packetData) LpxFreeMemoryWithLpxTag( packetData ); if (packet) NdisFreePacket( packet ); *Packet = NULL; DebugPrint( 1, ("[LPX]RcvPacketAlloc: Can't Allocate Buffer For CopyData!!!\n") ); } return status; }