NDIS_STATUS AllocatePacketWithBufferX( PNDIS_PACKET *NdisPacket, PCHAR Data, UINT Len, PCHAR File, UINT Line ) { PNDIS_PACKET Packet; PNDIS_BUFFER Buffer; NDIS_STATUS Status; PCHAR NewData; NewData = exAllocatePool( NonPagedPool, Len ); if( !NewData ) return NDIS_STATUS_NOT_ACCEPTED; // XXX if( Data ) RtlCopyMemory(NewData, Data, Len); NdisAllocatePacket( &Status, &Packet, GlobalPacketPool ); if( Status != NDIS_STATUS_SUCCESS ) { exFreePool( NewData ); return Status; } TrackWithTag(NDIS_PACKET_TAG, Packet, File, Line); NdisAllocateBuffer( &Status, &Buffer, GlobalBufferPool, NewData, Len ); if( Status != NDIS_STATUS_SUCCESS ) { exFreePool( NewData ); FreeNdisPacket( Packet ); } TrackWithTag(NDIS_BUFFER_TAG, Buffer, File, Line); NdisChainBufferAtFront( Packet, Buffer ); *NdisPacket = Packet; return NDIS_STATUS_SUCCESS; }
NDIS_STATUS AllocatePacketWithBuffer( PNDIS_PACKET *NdisPacket, PCHAR Data, UINT Len ) { PNDIS_PACKET Packet; PNDIS_BUFFER Buffer; NDIS_STATUS Status; PCHAR NewData; NewData = ExAllocatePoolWithTag( NonPagedPool, Len, PACKET_BUFFER_TAG ); if( !NewData ) return NDIS_STATUS_RESOURCES; if( Data ) RtlCopyMemory(NewData, Data, Len); NdisAllocatePacket( &Status, &Packet, GlobalPacketPool ); if( Status != NDIS_STATUS_SUCCESS ) { ExFreePoolWithTag( NewData, PACKET_BUFFER_TAG ); return Status; } NdisAllocateBuffer( &Status, &Buffer, GlobalBufferPool, NewData, Len ); if( Status != NDIS_STATUS_SUCCESS ) { ExFreePoolWithTag( NewData, PACKET_BUFFER_TAG ); FreeNdisPacket( Packet ); return Status; } NdisChainBufferAtFront( Packet, Buffer ); *NdisPacket = Packet; return NDIS_STATUS_SUCCESS; }
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; }
/*----------------------------------------------------------------------------*/ WLAN_STATUS kalProcessRxPacket(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN PUINT_8 pucPacketStart, IN UINT_32 u4PacketLen, IN BOOL fgIsRetain, IN ENUM_CSUM_RESULT_T aerCSUM[] ) { PNDIS_PACKET prNdisPacket; PNDIS_BUFFER prNdisBuf; NDIS_STATUS rStatus; ASSERT(prGlueInfo); ASSERT(pvPacket); ASSERT(pucPacketStart); prNdisPacket = (PNDIS_PACKET) pvPacket; NdisAllocateBuffer(&rStatus, &prNdisBuf, prGlueInfo->hBufPool, (PVOID) pucPacketStart, (UINT_32) u4PacketLen); if (rStatus != NDIS_STATUS_SUCCESS) { ASSERT(0); return WLAN_STATUS_FAILURE; } NdisChainBufferAtBack(prNdisPacket, prNdisBuf); if (fgIsRetain) { /* We don't have enough receive buffers, so set the status on the packet to NDIS_STATUS_RESOURCES to force the protocol driver(s) to copy this packet and return this buffer immediately after returning from the NdisMIndicateReceivePacket function. */ NDIS_SET_PACKET_STATUS(prNdisPacket, NDIS_STATUS_RESOURCES); } else { /* We have enough receive buffers, so set the status on the packet to NDIS_STATUS_SUCCESS. */ NDIS_SET_PACKET_STATUS(prNdisPacket, NDIS_STATUS_SUCCESS); } #if CFG_TCP_IP_CHKSUM_OFFLOAD kalUpdateRxCSUMOffloadParam(pvPacket, aerCSUM); #endif return WLAN_STATUS_SUCCESS; }
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; }
NDIS_STATUS PrependPacket( PNDIS_PACKET Packet, PCHAR Data, UINT Length, BOOLEAN Copy ) { PNDIS_BUFFER Buffer; NDIS_STATUS Status; PCHAR NewBuf; if( Copy ) { NewBuf = PoolAllocateBuffer( Length ); if( !NewBuf ) return STATUS_NO_MEMORY; RtlCopyMemory( NewBuf, Data, Length ); } else NewBuf = Data; NdisAllocateBuffer( &Status, &Buffer, GlobalBufferPool, Data, Length ); if( Status != NDIS_STATUS_SUCCESS ) return Status; NdisChainBufferAtFront( Packet, Buffer ); return STATUS_SUCCESS; }
NDIS_STATUS PrependPacket( PNDIS_PACKET Packet, PCHAR Data, UINT Length, BOOLEAN Copy ) { PNDIS_BUFFER Buffer; NDIS_STATUS Status; PCHAR NewBuf; if( Copy ) { NewBuf = ExAllocatePoolWithTag( NonPagedPool, Length, PACKET_BUFFER_TAG ); if( !NewBuf ) return NDIS_STATUS_RESOURCES; RtlCopyMemory( NewBuf, Data, Length ); } else NewBuf = Data; NdisAllocateBuffer( &Status, &Buffer, GlobalBufferPool, NewBuf, Length ); if( Status != NDIS_STATUS_SUCCESS ) { if (Copy) ExFreePoolWithTag(NewBuf, PACKET_BUFFER_TAG); return Status; } NdisChainBufferAtFront( Packet, Buffer ); return STATUS_SUCCESS; }
// Create a packet buffer PACKET_BUFFER *NeoNewPacketBuffer() { PACKET_BUFFER *p; NDIS_STATUS ret; // Memory allocation p = NeoZeroMalloc(sizeof(PACKET_BUFFER)); // Memory allocation for packet p->Buf = NeoMalloc(NEO_MAX_PACKET_SIZE); // Allocate the buffer pool NdisAllocateBufferPool(&ret, &p->BufferPool, 1); // Allocate the buffer NdisAllocateBuffer(&ret, &p->NdisBuffer, p->BufferPool, p->Buf, NEO_MAX_PACKET_SIZE); // Secure the packet pool NdisAllocatePacketPool(&ret, &p->PacketPool, 1, PROTOCOL_RESERVED_SIZE_IN_PACKET); // Secure the packet NdisAllocatePacket(&ret, &p->NdisPacket, p->PacketPool); NDIS_SET_PACKET_HEADER_SIZE(p->NdisPacket, NEO_PACKET_HEADER_SIZE); // Attach the buffer to the packet NdisChainBufferAtFront(p->NdisPacket, p->NdisBuffer); return p; }
NDIS_STATUS FakeNDISReceiveHandler ( NDIS_HANDLE ProtocolBindingContext, NDIS_HANDLE MacReceiveContext, PUCHAR pHeaderBuffer, UINT HeaderBufferSize, PUCHAR pLookaheadBuffer, UINT LookaheadBufferSize, UINT PacketSize ) /*++ Routine Description: Filters network packets received. Arguments: ProtocolBindingContext - ... MacReceiveContext - ... pHeaderBuffer - packet header HeaderBufferSize - packet header length pLookaheadBuffer - look ahead buffer after packet header LookaheadBufferSize - length of look ahead buffer PacketSize - length of packet, exclude packet header Return Value: ... Author: xiaonie 2012/07/12 --*/ { PLIST_ENTRY pEntry; PNDIS_HOOK_LIST_NODE pNode; KIRQL irql; ULONG ulFunAddr = 0; // PVOID MacHandle = NULL; NDIS_STATUS status = NDIS_STATUS_SUCCESS; PNDIS_PACKET pNdisPacket = NULL; PNDIS_BUFFER pNdisBuffer = NULL; PUCHAR pBuffer = NULL; ULONG ulLen; KEVENT evt; KeAcquireSpinLock(&g_lock, &irql); for (pEntry = g_linkListHead.Flink; pEntry != &g_linkListHead; pEntry = pEntry->Flink) { pNode = CONTAINING_RECORD(pEntry, NDIS_HOOK_LIST_NODE, ListEntry); if (pNode->ProtocolBindingContext == ProtocolBindingContext) { ulFunAddr = pNode->ulRealReceiveHandler; // MacHandle = pNode->MacHandle; break; } } KeReleaseSpinLock(&g_lock, irql); if (ulFunAddr == 0) { DbgPrint("\r\n Attention: FunAddr == 0(0: FakeNDISReceiveHandler)\r\n"); // return NDIS_STATUS_SUCCESS; return NDIS_STATUS_NOT_ACCEPTED; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (PacketSize + HeaderBufferSize < PacketSize || PacketSize < LookaheadBufferSize) { // PacketSize not valid DbgPrint("\r\n Attention: PacketSize not valid!(0: FakeNDISReceiveHandler)\r\n"); return NDIS_STATUS_NOT_ACCEPTED; } // allocate buffer to hold network packet status = NdisAllocateMemoryWithTag(&pBuffer, HeaderBufferSize + PacketSize, '!nmN'); if (status != NDIS_STATUS_SUCCESS/* || pBuffer == NULL*/) return NDIS_STATUS_NOT_ACCEPTED; // copy packet header to buffer NdisMoveMemory(pBuffer, pHeaderBuffer, HeaderBufferSize); if (PacketSize == LookaheadBufferSize) // Lookahead buffer contains a complete packet { // // path 1 of 3, tested ok! // NdisMoveMemory(pBuffer + HeaderBufferSize, pLookaheadBuffer, PacketSize); // do the filtering work if (TRUE == RabbitHole(pBuffer, HeaderBufferSize + PacketSize)) { NdisFreeMemory(pBuffer, 0, 0); return NDIS_STATUS_NOT_ACCEPTED; } NdisFreeMemory(pBuffer, 0, 0); } else // Lookahead buffer contains an incomplete packet { // // get the full packet // // DbgPrint("Get Full Packet!\r\n"); //if (MacHandle == NULL) { // DbgPrint("MacHandle == NULL!(0: FakeNDISReceiveHandler)\r\n"); // NdisFreeMemory(pBuffer, 0, 0); // return NDIS_STATUS_NOT_ACCEPTED; //} // make pBuffer a NDIS buffer to hold data NdisAllocateBuffer(&status, &pNdisBuffer, g_BufferPool, pBuffer + HeaderBufferSize, PacketSize); if (status != NDIS_STATUS_SUCCESS/* || pNdisBuffer == NULL*/) { DbgPrint("allocate pNdisBuffer(size = %d) failed in FakeNDISReceiveHandler!\r\n", PacketSize); NdisFreeMemory(pBuffer, 0, 0); return NDIS_STATUS_NOT_ACCEPTED; } // allocate a NIDS packet to chain buffer in. NdisAllocatePacket(&status, &pNdisPacket, g_PacketPool); if (status != NDIS_STATUS_SUCCESS/* || pNdisPacket == NULL*/) { DbgPrint("allocate pNdisPacket failed in FakeNDISReceiveHandler!\r\n"); NdisFreeBuffer(pNdisBuffer); NdisFreeMemory(pBuffer, 0, 0); return NDIS_STATUS_NOT_ACCEPTED; } NDIS_SET_PACKET_STATUS(pNdisPacket, STATUS_SUCCESS); // Bring explosives. KeInitializeEvent(&evt, NotificationEvent, FALSE); *(PKEVENT *)(pNdisPacket->ProtocolReserved) = &evt; NdisChainBufferAtFront(pNdisPacket, pNdisBuffer); // try to get complete packet NdisTransferData(&status, pNode->pOpenBlock, MacReceiveContext, 0, PacketSize, pNdisPacket, &ulLen); if (status == NDIS_STATUS_PENDING) { // wait for the right time // // Path 2 of 3, not tested yet! Warning: An Error may occur! // DbgPrint("NdisTransferData is pending in FakeNDISReceiveHandler!\r\n", status); KeWaitForSingleObject(&evt, Executive, KernelMode, FALSE, NULL); } else if (status != NDIS_STATUS_SUCCESS) { DbgPrint("NdisTransferData failed(status == 0x%08x) in FakeNDISReceiveHandler!\r\n", status); NdisFreePacket(pNdisPacket); NdisFreeBuffer(pNdisBuffer); NdisFreeMemory(pBuffer, 0, 0); return NDIS_STATUS_NOT_ACCEPTED; } // // Path 3 of 3, Filtering doesn't seem to work properly. // // do the filtering work if (TRUE == FilterPacket_ReceiveHandler(pBuffer, HeaderBufferSize, pNdisPacket)) { NdisFreePacket(pNdisPacket); NdisFreeBuffer(pNdisBuffer); NdisFreeMemory(pBuffer, 0, 0); return NDIS_STATUS_NOT_ACCEPTED; } NdisFreePacket(pNdisPacket); NdisFreeBuffer(pNdisBuffer); NdisFreeMemory(pBuffer, 0, 0); } // call the original NDIS routine. __asm { pushad; push PacketSize; push LookaheadBufferSize; push pLookaheadBuffer; push HeaderBufferSize; push pHeaderBuffer; push MacReceiveContext; push ProtocolBindingContext; mov eax, ulFunAddr; call eax; mov status, eax; popad; } return status; }
INT natpReceivePacketPassThrough( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN FLT_PKT* pFltPkt ) { PFILTER_ADAPTER pAdapt =(PFILTER_ADAPTER)ProtocolBindingContext; NDIS_STATUS Status; PNDIS_PACKET MyPacket; BOOLEAN Remaining; PNDIS_BUFFER pNewBuffer; if (NULL == pAdapt->MiniportHandle || pAdapt->natmDeviceState > NdisDeviceStateD0) return 0; NdisIMGetCurrentPacketStack(Packet, &Remaining); if (NULL == pFltPkt && Remaining){ Status = NDIS_GET_PACKET_STATUS(Packet); NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1); return Status != NDIS_STATUS_RESOURCES ? 1 : 0; } if(NULL == pFltPkt){ NdisDprAllocatePacket( &Status, &MyPacket, pAdapt->RcvPP1 ); if (Status != NDIS_STATUS_SUCCESS){ return 0; } *((PVOID*)&MyPacket->MiniportReserved) = Packet; MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; }else{ NdisDprAllocatePacket( &Status, &MyPacket, pAdapt->RcvPP2 ); if (Status != NDIS_STATUS_SUCCESS) return NDIS_STATUS_NOT_ACCEPTED; *((PVOID*)&MyPacket->MiniportReserved) = pFltPkt; NdisAllocateBuffer( &Status, &pNewBuffer, pAdapt->RcvBP, pFltPkt->pBuf, pFltPkt->uLen ); if ( Status != NDIS_STATUS_SUCCESS ){ NdisReinitializePacket (MyPacket); NdisFreePacket (MyPacket); return 0; } NdisChainBufferAtFront(MyPacket, pNewBuffer ); } NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); Status = NDIS_GET_PACKET_STATUS(Packet); NDIS_SET_PACKET_STATUS(MyPacket, Status); NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet)); if (Status == NDIS_STATUS_RESOURCES){ natpQueueReceivedPacket(pAdapt, MyPacket, TRUE); }else{ natpQueueReceivedPacket(pAdapt, MyPacket, FALSE); } if (Status == NDIS_STATUS_RESOURCES) NdisDprFreePacket(MyPacket); return Status != NDIS_STATUS_RESOURCES ? 1 : 0; }
PNDIS_PACKET SecLabAllocateReceivePacket( PADAPT pAdapt, IN UINT DataLength, OUT PUCHAR * ppDataBuffer ) /*++ Routine Description: 分配用于拷贝和排队接收包的资源. Arguments: DataLength - 封包的总长度,包括包头和数据 ppDataBuffer - 返回的缓冲区地址 Return Value: 如果成功则返回包的指针,否则为空. --*/ { PNDIS_PACKET pNdisPacket; PNDIS_BUFFER pNdisBuffer; PUCHAR pDataBuffer; NDIS_STATUS Status; pNdisPacket = NULL; pNdisBuffer = NULL; pDataBuffer = NULL; do { NdisAllocateMemoryWithTag((PVOID *)(&pDataBuffer), DataLength,'lceS'); if (pDataBuffer == NULL) { DbgPrint("Can not Allocate resoures for packet"); break; } // // 将其转化为NDIS_BUFFER. // NdisAllocateBuffer( &Status, &pNdisBuffer, RecvBufferPool, pDataBuffer, DataLength); if (Status != NDIS_STATUS_SUCCESS) { DbgPrint("failed to allocate Ndis Buffer"); break; } NdisAllocatePacket(&Status, &pNdisPacket, pAdapt->RecvPacketPoolHandle); if (Status != NDIS_STATUS_SUCCESS) { DbgPrint("failed to alloc NDIS packet"); break; } NDIS_SET_PACKET_STATUS(pNdisPacket, 0); SECLAB_RCV_PKT_TO_ORIGINAL_BUFFER(pNdisPacket) = NULL; NdisChainBufferAtFront(pNdisPacket, pNdisBuffer); *ppDataBuffer = pDataBuffer; break; } while (FALSE); if (pNdisPacket == NULL) { // // Clean up // if (pNdisBuffer != NULL) { NdisFreeBuffer(pNdisBuffer); } if (pDataBuffer != NULL) { NdisFreeMemory(pDataBuffer, 0, 0); } } return (pNdisPacket); }
BOOLEAN ArcConvertToNdisPacket( IN PARC_FILTER Filter, IN PARC_PACKET Packet, IN BOOLEAN ConvertWholePacket ) /*++ Routine description: This routine builds a corresponding NDIS_PACKET in TmpNdisPacket, that corresponds to the arcnet packet. The flag ConvertWholePacket is used to convert only part of the arcnet packet, or the whole stream. If the flag is FALSE, then only the buffers that have free space (starting with buffer LastBuffer on up) are converted. NOTE: It assumes TmpNdisPacket is an initialized ndis_packet structure. Arguments: Filter - Filter to allocate from. Packet - The packet to convert. ConvertWholePacket - Convert the whole stream, or only part? Return values: TRUE - If successful, else FALSE --*/ { PNDIS_BUFFER NdisBuffer; PARC_BUFFER_LIST Buffer; NDIS_STATUS NdisStatus; Buffer = Packet->FirstBuffer; while (Buffer != NULL) { NdisAllocateBuffer( &NdisStatus, &NdisBuffer, Filter->ReceiveBufferPool, Buffer->Buffer, Buffer->Size - Buffer->BytesLeft ); if (NdisStatus != NDIS_STATUS_SUCCESS) { return(FALSE); } NdisChainBufferAtBack( &(Packet->TmpNdisPacket), NdisBuffer ); Buffer = Buffer->Next; } return(TRUE); }
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 }
/*+ * * AllocateAdapterMemory * * Routine Description: * * This routine allocates memory for: * * - Transmit descriptor ring * - Receive descriptor ring * - Receive buffers * - Transmit buffer * - Setup buffer * * Arguments: * * Adapter - The adapter to allocate memory for. * * Functional description * * For each allocated zone, we maintain a set of pointers: * - virtual & physical addresses of the allocated block * - virtual & physical addresses of the aligned structure (descriptor ring, buffer,...) * whithin the block * * Return Value: * * Returns FALSE if an allocation fails. * -*/ extern BOOLEAN AllocateAdapterMemory( IN PDC21X4_ADAPTER Adapter ) { PDC21X4_TRANSMIT_DESCRIPTOR TransmitDescriptor; PDC21X4_RECEIVE_DESCRIPTOR ReceiveDescriptor; NDIS_STATUS Status; PRCV_HEADER RcvHeader; PNDIS_PACKET Packet; ULONG AllocSize; PULONG AllocVa; NDIS_PHYSICAL_ADDRESS AllocPa; ULONG Va; ULONG Pa; UINT i; ULONG Offset; INT TransmitDescriptorRingSize; INT ReceiveDescriptorRingSize; Adapter->RcvHeaderSize = ((RCV_HEADER_SIZE + Adapter->CacheLineSize - 1) / Adapter->CacheLineSize) * Adapter->CacheLineSize; #if _DBG DbgPrint("Alloc Rcv_ring[%d desc.], Txm_ring[%d desc.], setup_buf[%d]...\n", Adapter->ReceiveRingSize, TRANSMIT_RING_SIZE, DC21X4_SETUP_BUFFER_SIZE ); #endif // Allocate space for transmit descriptor ring, // the receive descriptor ring and the setup buffer TransmitDescriptorRingSize = Adapter->DescriptorSize * TRANSMIT_RING_SIZE; ReceiveDescriptorRingSize = Adapter->DescriptorSize * Adapter->ReceiveRingSize; Adapter->DescriptorRing.AllocSize = TransmitDescriptorRingSize + ReceiveDescriptorRingSize + DC21X4_SETUP_BUFFER_SIZE + Adapter->CacheLineSize; NdisMAllocateSharedMemory( Adapter->MiniportAdapterHandle, Adapter->DescriptorRing.AllocSize, FALSE, // NON-CACHED (PVOID *)&Adapter->DescriptorRing.AllocVa, // virtual ... &Adapter->DescriptorRing.AllocPa // and physical address of the allocation ); // Check the allocation success if ((PVOID)Adapter->DescriptorRing.AllocVa == (PVOID)NULL) { return FALSE; } if (NdisGetPhysicalAddressHigh(Adapter->DescriptorRing.AllocPa) != 0) { return FALSE; } NdisZeroMemory ( (PVOID)(Adapter->DescriptorRing.AllocVa), (ULONG)(Adapter->DescriptorRing.AllocSize) ); // Align to the next cache line boundary AlignStructure ( &Adapter->DescriptorRing, Adapter->CacheLineSize ); Adapter->TransmitDescriptorRingVa = Adapter->DescriptorRing.Va; Adapter->TransmitDescriptorRingPa = Adapter->DescriptorRing.Pa; Offset = TransmitDescriptorRingSize; Adapter->ReceiveDescriptorRingVa = Adapter->DescriptorRing.Va + Offset; Adapter->ReceiveDescriptorRingPa = Adapter->DescriptorRing.Pa + Offset; Offset += ReceiveDescriptorRingSize; Adapter->SetupBufferVa = Adapter->DescriptorRing.Va + Offset; Adapter->SetupBufferPa = Adapter->DescriptorRing.Pa + Offset; //Initialize the setup buffer NdisZeroMemory ( (PVOID)(Adapter->SetupBufferVa), DC21X4_SETUP_BUFFER_SIZE ); // Allocate a pool of NDIS buffers NdisAllocateBufferPool( &Status, &Adapter->FlushBufferPoolHandle, ( Adapter->ReceiveRingSize + Adapter->ExtraReceiveBuffers + DC21X4_NUMBER_OF_MAX_TRANSMIT_BUFFERS + DC21X4_NUMBER_OF_MIN_TRANSMIT_BUFFERS ) ); if (Status != NDIS_STATUS_SUCCESS) { return FALSE; } // Allocate a pool of packets. #if _DBG DbgPrint("Allocate PacketPool [%d packets]\n", Adapter->ExtraReceivePackets); #endif NdisAllocatePacketPool( &Status, &Adapter->ReceivePacketPool, Adapter->ExtraReceivePackets, 0 ); if (Status != NDIS_STATUS_SUCCESS) { return FALSE; } // Allocate all of the packets out of the packet pool // and place them on a queue. for (i = 0; i < Adapter->ExtraReceivePackets; i++) { // Allocate a packet from the pool. NdisAllocatePacket( &Status, &Packet, Adapter->ReceivePacketPool ); if (Status != NDIS_STATUS_SUCCESS) { return(FALSE); } // Set the header size in the packet's Out-Of-Band information. // All other fields in the Out-Of-Band information have been // initialized to 0 by NdisAllocatePacket(). NDIS_SET_PACKET_HEADER_SIZE(Packet, ETH_HEADER_SIZE); // Place it on the receive packet free list. RCV_RESERVED(Packet)->Next = Adapter->FreePacketList; Adapter->FreePacketList = Packet; } // Clear out the free receive list of buffers. Adapter->FreeRcvList = NULL; // We allocate the receive buffers. We allocate both // the buffers for the descriptor ring and the extra // buffers and place them all on the free queue. #if _DBG DbgPrint("Allocate Receive Buffers [%d]\n", Adapter->ExtraReceiveBuffers+Adapter->ReceiveRingSize); #endif // Attempt to allocate all the receive buffer space // in one block // If it fails,allocate each buffer individually // Allocation size Adapter->RcvBufferSpace.AllocSize = ((Adapter->ExtraReceiveBuffers + Adapter->ReceiveRingSize) * (DC21X4_RECEIVE_BUFFER_SIZE + Adapter->RcvHeaderSize)) + Adapter->CacheLineSize; NdisMAllocateSharedMemory( Adapter->MiniportAdapterHandle, Adapter->RcvBufferSpace.AllocSize, TRUE, (PVOID *)&Adapter->RcvBufferSpace.AllocVa, &Adapter->RcvBufferSpace.AllocPa ); // Check the allocation success if (((PVOID)Adapter->RcvBufferSpace.AllocVa != (PVOID)NULL) && (NdisGetPhysicalAddressHigh(Adapter->RcvBufferSpace.AllocPa) == 0)) { NdisZeroMemory ( (PVOID)(Adapter->RcvBufferSpace.AllocVa), (ULONG)(Adapter->RcvBufferSpace.AllocSize) ); // Align to the next cache line boundary AlignStructure ( &Adapter->RcvBufferSpace, Adapter->CacheLineSize ); // Allocation size needed for the receive buffer AllocSize = DC21X4_RECEIVE_BUFFER_SIZE + Adapter->RcvHeaderSize; Offset=0; } else { // Allocation size needed for the receive buffer AllocSize = DC21X4_RECEIVE_BUFFER_SIZE + Adapter->RcvHeaderSize + Adapter->CacheLineSize; Adapter->RcvBufferSpace.Va=0; } for (i = 0; i < (Adapter->ExtraReceiveBuffers + Adapter->ReceiveRingSize); i++ ) { if (Adapter->RcvBufferSpace.Va != 0) { Va = Adapter->RcvBufferSpace.Va + Offset; Pa = Adapter->RcvBufferSpace.Pa + Offset; Offset += AllocSize; } else { // Allocate a receive buffer. NdisMAllocateSharedMemory( Adapter->MiniportAdapterHandle, AllocSize, TRUE, (PVOID *)&AllocVa, &AllocPa ); if (((PVOID)AllocVa == (PVOID)NULL) || (NdisGetPhysicalAddressHigh(AllocPa) != 0)) { return FALSE; } NdisZeroMemory(AllocVa, AllocSize); // Align on the cache line boundary Offset = Adapter->CacheLineSize - ((ULONG)AllocVa % Adapter->CacheLineSize); Va = (ULONG)(AllocVa) + Offset; Pa = NdisGetPhysicalAddressLow(AllocPa) + Offset; } //The receive header points to the aligned va. RcvHeader = (PRCV_HEADER)Va; RcvHeader->AllocVa = (ULONG)AllocVa; RcvHeader->AllocPa = AllocPa; RcvHeader->AllocSize = (USHORT)AllocSize; // These addresses point to the data buffer RcvHeader->Va = (ULONG)(Va + Adapter->RcvHeaderSize); RcvHeader->Pa = Pa + Adapter->RcvHeaderSize; RcvHeader->Size = DC21X4_RECEIVE_BUFFER_SIZE; #if DBG RcvHeader->Signature = 'dHxR'; #if _DBG DbgPrint( "%-3d RcvHeader: %lx, RcvBuffer: %lx/%lx, HeaderSize: %lx\n", i,RcvHeader, RcvHeader->Va, RcvHeader->Pa, Adapter->RcvHeaderSize ); #endif #endif // Allocate an NDIS flush buffer for each receive buffer. NdisAllocateBuffer( &Status, &RcvHeader->FlushBuffer, Adapter->FlushBufferPoolHandle, (PVOID)RcvHeader->Va, DC21X4_RECEIVE_BUFFER_SIZE ); if (Status != NDIS_STATUS_SUCCESS) { return FALSE; } // Grab a packet off of the free packet list and // associate it with the buffer. Packet = Adapter->FreePacketList; Adapter->FreePacketList = RCV_RESERVED(Packet)->Next; // Chain the buffer on the packet. NdisChainBufferAtFront(Packet, RcvHeader->FlushBuffer); // Save a pointer to the receive header with the packet. RCV_RESERVED(Packet)->RcvHeader = RcvHeader; // Save the packet with the receive header. RcvHeader->Packet = Packet; // Place the descriptor on the free queue. RcvHeader->Next = Adapter->FreeRcvList; Adapter->FreeRcvList = RcvHeader; Adapter->CurrentReceiveBufferCount++; } #if _DBG DbgPrint("Init Rcv ring..\n"); #endif // Assign the receive buffers to the descriptors. for (i = 0, ReceiveDescriptor = (PDC21X4_RECEIVE_DESCRIPTOR)Adapter->ReceiveDescriptorRingVa, Pa = Adapter->ReceiveDescriptorRingPa; i < Adapter->ReceiveRingSize; i++, (PCHAR)ReceiveDescriptor += Adapter->DescriptorSize, Pa += Adapter->DescriptorSize ) { // Grab a receive buffer from the free list. ASSERT(Adapter->FreeRcvList != NULL); RcvHeader = Adapter->FreeRcvList; Adapter->FreeRcvList = RcvHeader->Next; Adapter->CurrentReceiveBufferCount--; // Associate the buffer with the descriptor. ReceiveDescriptor->RcvHeader = RcvHeader; ReceiveDescriptor->FirstBufferAddress = RcvHeader->Pa; ReceiveDescriptor->Status = DESC_OWNED_BY_DC21X4; ReceiveDescriptor->Control = DC21X4_RECEIVE_BUFFER_SIZE; ReceiveDescriptor->Next = (PDC21X4_RECEIVE_DESCRIPTOR)((PCHAR)ReceiveDescriptor + Adapter->DescriptorSize); } //last descriptor of the ring (PCHAR)ReceiveDescriptor -= Adapter->DescriptorSize; ReceiveDescriptor->Control |= DC21X4_RDES_SECOND_ADDR_CHAINED; ReceiveDescriptor->SecondBufferAddress = Adapter->ReceiveDescriptorRingPa; ReceiveDescriptor->Next = (PDC21X4_RECEIVE_DESCRIPTOR)Adapter->ReceiveDescriptorRingVa; #if _DBG DbgPrint("Init Txm ring..\n"); #endif // Initialize the Transmit Descriptor ring for (i=0, TransmitDescriptor = (PDC21X4_TRANSMIT_DESCRIPTOR)Adapter->TransmitDescriptorRingVa, Pa = Adapter->TransmitDescriptorRingPa; i < TRANSMIT_RING_SIZE; i++, (PCHAR)TransmitDescriptor += Adapter->DescriptorSize, Pa += Adapter->DescriptorSize ) { TransmitDescriptor->MapTableIndex = i * NUMBER_OF_SEGMENT_PER_DESC; TransmitDescriptor->DescriptorPa = Pa; TransmitDescriptor->Next = (PDC21X4_TRANSMIT_DESCRIPTOR)((PCHAR)TransmitDescriptor + Adapter->DescriptorSize); } //last descriptor of the ring (PCHAR)TransmitDescriptor -= Adapter->DescriptorSize; TransmitDescriptor->Control = DC21X4_TDES_SECOND_ADDR_CHAINED; TransmitDescriptor->SecondBufferAddress = Adapter->TransmitDescriptorRingPa; TransmitDescriptor->Next = (PDC21X4_TRANSMIT_DESCRIPTOR)Adapter->TransmitDescriptorRingVa; // Txm buffers for (i = 0;i < DC21X4_NUMBER_OF_MAX_TRANSMIT_BUFFERS;i ++) { Adapter->MaxTransmitBuffer[i].AllocSize = DC21X4_MAX_TRANSMIT_BUFFER_SIZE + Adapter->CacheLineSize; NdisMAllocateSharedMemory( Adapter->MiniportAdapterHandle, Adapter->MaxTransmitBuffer[i].AllocSize, TRUE, // CACHED (PVOID *)&Adapter->MaxTransmitBuffer[i].AllocVa, // virtual ... &Adapter->MaxTransmitBuffer[i].AllocPa // and physical address of the buffer allocation ); // Check the allocation success if (((PVOID)Adapter->MaxTransmitBuffer[i].AllocVa == (PVOID)NULL) || (NdisGetPhysicalAddressHigh(Adapter->MaxTransmitBuffer[i].AllocPa) != 0)) { return FALSE; } // Align the buffer on the cache line boundary AlignStructure ( &Adapter->MaxTransmitBuffer[i], Adapter->CacheLineSize ); // Allocate an NDIS flush buffer for each transmit buffer NdisAllocateBuffer( &Status, &Adapter->MaxTransmitBuffer[i].FlushBuffer, Adapter->FlushBufferPoolHandle, (PVOID)Adapter->MaxTransmitBuffer[i].Va, DC21X4_MAX_TRANSMIT_BUFFER_SIZE ); if (Status != NDIS_STATUS_SUCCESS) { return FALSE; } } // Allocate the minimal packet buffers Adapter->MinTransmitBuffer[0].AllocSize = (DC21X4_NUMBER_OF_MIN_TRANSMIT_BUFFERS * DC21X4_MIN_TRANSMIT_BUFFER_SIZE) + Adapter->CacheLineSize; NdisMAllocateSharedMemory( Adapter->MiniportAdapterHandle, Adapter->MinTransmitBuffer[0].AllocSize, TRUE, // CACHED (PVOID *)&Adapter->MinTransmitBuffer[0].AllocVa, // virtual ... &Adapter->MinTransmitBuffer[0].AllocPa // and physical address of the buffer allocation ); // Check the allocation success if (((PVOID)Adapter->MinTransmitBuffer[0].AllocVa == (PVOID)NULL) || (NdisGetPhysicalAddressHigh(Adapter->MinTransmitBuffer[0].AllocPa) != 0)) { Adapter->DontUseMinTransmitBuffer = TRUE; return TRUE; } // Align the buffer on the cache line boundary AlignStructure ( &Adapter->MinTransmitBuffer[0], Adapter->CacheLineSize ); for (i = 0;i < DC21X4_NUMBER_OF_MIN_TRANSMIT_BUFFERS;i ++) { Offset = i * DC21X4_MIN_TRANSMIT_BUFFER_SIZE; Adapter->MinTransmitBuffer[i].Va = Adapter->MinTransmitBuffer[0].Va + Offset; Adapter->MinTransmitBuffer[i].Pa = Adapter->MinTransmitBuffer[0].Pa + Offset; // Allocate an NDIS flush buffer for each transmit buffer NdisAllocateBuffer( &Status, &Adapter->MinTransmitBuffer[i].FlushBuffer, Adapter->FlushBufferPoolHandle, (PVOID)Adapter->MinTransmitBuffer[i].Va, DC21X4_MIN_TRANSMIT_BUFFER_SIZE ); if (Status != NDIS_STATUS_SUCCESS) { return FALSE; } } // Allocation has completed successfully return TRUE; }
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; }
NTSTATUS PacketAllocate( IN PSERVICE_POINT ServicePoint, IN ULONG PacketLength, IN PDEVICE_CONTEXT DeviceContext, IN UCHAR Type, IN PUCHAR CopyData, IN ULONG CopyDataLength, IN PIO_STACK_LOCATION IrpSp, OUT PNDIS_PACKET *Packet ) { NTSTATUS status; PUCHAR packetData; PNDIS_BUFFER pNdisBuffer; PNDIS_BUFFER pNdisBufferData; PNDIS_PACKET packet; USHORT port; DebugPrint(3, ("PacketAllocate, PacketLength = %d, Numberofpackets = %d\n", PacketLength, NumberOfPackets)); // if(ServicePoint && ServicePoint->SmpState == SMP_SYN_RECV) // return STATUS_INSUFFICIENT_RESOURCES; if(DeviceContext == NULL) { DebugPrint(1, ("[LPX]PacketAllocate: DeviceContext is NULL!!!\n")); return STATUS_INVALID_PARAMETER; } if(DeviceContext->LpxPacketPool == NULL) { DebugPrint(1, ("[LPX]PacketAllocate: DeviceContext->LpxPacketPool is NULL!!!\n")); return STATUS_INVALID_PARAMETER; } NdisAllocatePacket(&status, &packet, DeviceContext->LpxPacketPool); if(status != NDIS_STATUS_SUCCESS) { DebugPrint(1, ("[LPX]PacketAllocate: NdisAllocatePacket Failed!!!\n")); return STATUS_INSUFFICIENT_RESOURCES; } status = NdisAllocateMemory( &packetData, PacketLength ); if(status != NDIS_STATUS_SUCCESS) { DebugPrint(1, ("[LpxSmp]PacketAllocate: Can't Allocate Memory packet.\n")); NdisFreePacket(packet); *Packet = NULL; return status; } NdisAllocateBuffer( &status, &pNdisBuffer, DeviceContext->LpxBufferPool, packetData, PacketLength ); if(!NT_SUCCESS(status)) { NdisFreePacket(packet); *Packet = NULL; NdisFreeMemory(packetData); DebugPrint(1, ("[LPX]PacketAllocate: Can't Allocate Buffer!!!\n")); return status; } switch(Type) { case SEND_TYPE: if(ServicePoint && &ServicePoint->SmpContext) { RtlCopyMemory(&packetData[0], ServicePoint->DestinationAddress.Node, ETHERNET_ADDRESS_LENGTH ); RtlCopyMemory(&packetData[ETHERNET_ADDRESS_LENGTH], ServicePoint->SourceAddress.Node, ETHERNET_ADDRESS_LENGTH ); port = HTONS(ETH_P_LPX); RtlCopyMemory(&packetData[ETHERNET_ADDRESS_LENGTH*2], &port, //&ServicePoint->DestinationAddress.Port, 2 ); } if(CopyDataLength) { NdisAllocateBuffer( &status, &pNdisBufferData, DeviceContext->LpxBufferPool, CopyData, CopyDataLength ); if(!NT_SUCCESS(status)) { NdisFreePacket(packet); *Packet = NULL; NdisFreeMemory(packetData); DebugPrint(1, ("[LPX]PacketAllocate: Can't Allocate Buffer For CopyData!!!\n")); return status; } NdisChainBufferAtFront(packet, pNdisBufferData); } break; case RECEIVE_TYPE: NdisMoveMappedMemory( packetData, CopyData, CopyDataLength ); break; } // RESERVED(packet)->ServicePoint = ServicePoint; RESERVED(packet)->Cloned = 0; RESERVED(packet)->IrpSp = IrpSp; RESERVED(packet)->Type = Type; RESERVED(packet)->LpxSmpHeader = NULL; if(IrpSp == NULL) { DebugPrint(2, ("[LPX] PacketAllocate: No IrpSp\n")) ; } NdisChainBufferAtFront(packet, pNdisBuffer); InterlockedIncrement(&NumberOfPackets); *Packet = packet; return STATUS_SUCCESS; }
//*********************************************************************************** // Name: MpAllocSGList // // Description: // sends packet via DMA // // Return value: // None // // Parameters: // // NOTE: None // ********************************************************************************** NDIS_STATUS MpAllocSGList( IN PKIP_NDIS_ADAPTER pAdapter, IN PNDIS_PACKET Packet ) { NDIS_STATUS nStatus = NDIS_STATUS_FAILURE; PNDIS_BUFFER Buffer; PVOID pBufferVa; ULONG PacketLength; PDMA_ADAPTER SystemAdapterObject; PDEVICE_OBJECT DeviceObject; PNPAGED_LOOKASIDE_LIST SGListLookasideList = NULL; ULONG ScatterGatherListSize = 0; PVOID pSGList = NULL; KIRQL OldIrql; PVOID SendBuffer = NULL; PNDIS_BUFFER SendNdisBuffer; ULONG nBytesRead = 0; BOOLEAN fbResult; BOOLEAN fbDMAV2; do { SystemAdapterObject = NDIS_GetSystemAdapterObject( pAdapter->NdisMiniportHandle ); if ( SystemAdapterObject == NULL ){ DBGLOG(( LError, "SystemAdapterObject is NULL\n" )); nStatus = NDIS_STATUS_RESOURCES; break; } fbDMAV2 = (SystemAdapterObject->DmaOperations->Size >= sizeof(DMA_OPERATIONS_V2) ); DeviceObject = NDIS_GetMiniportDeviceObject( pAdapter->NdisMiniportHandle ); if ( DeviceObject == NULL ){ DBGLOG(( LError, "DeviceObject is NULL\n" )); nStatus = NDIS_STATUS_RESOURCES; break; } if ( fbDMAV2 ){ SGListLookasideList = NDIS_GetSGListLookasideList( pAdapter->NdisMiniportHandle ); if ( SGListLookasideList == NULL ){ DBGLOG(( LError, "SGListLookasideList is NULL\n" )); nStatus = NDIS_STATUS_RESOURCES; break; } ScatterGatherListSize = NDIS_GetScatterGatherListSize( pAdapter->NdisMiniportHandle ); if ( ScatterGatherListSize == 0 ){ DBGLOG(( LError, "SGListLookasideList is NULL\n" )); nStatus = NDIS_STATUS_RESOURCES; break; } } NdisQueryPacket(Packet, NULL, NULL, &Buffer, &PacketLength); if ( Buffer == NULL ){ DBGLOG(( LError, "Buffer is NULL\n" )); nStatus = NDIS_STATUS_FAILURE; break; } // try to use build sg list interface if ( fbDMAV2 ){ // allocate SG list pSGList = ExAllocateFromNPagedLookasideList( SGListLookasideList ); if ( pSGList != NULL ){ Packet->Private.Flags |= NDIS_FLAGS_USES_SG_BUFFER_LIST; // sg list NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, NdisReserved) = pSGList; // raise irql to dispatch KeRaiseIrql(DISPATCH_LEVEL,&OldIrql); nStatus = SystemAdapterObject->DmaOperations->BuildScatterGatherList( SystemAdapterObject, DeviceObject, Buffer, MmGetMdlVirtualAddress(Buffer), PacketLength, MpProcessSGList, Packet, TRUE, pSGList, ScatterGatherListSize ); KeLowerIrql( OldIrql ); if ( !NT_SUCCESS ( nStatus )){ DBGLOG(( LDebug, "%08X=BuildMdlFromScatterGatherList failed\n",nStatus )); Packet->Private.Flags &= ~NDIS_FLAGS_RESERVED2; // sg list NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) = NULL; ExFreeToNPagedLookasideList( SGListLookasideList, pSGList ); } }else{ DBGLOG(( LDebug, "ExAllocateFromNPagedLookasideList failed\n" )); nStatus = NDIS_STATUS_RESOURCES; } } // if ( !fbDMAV2 ) then nStatus = NDIS_STATUS_FAILURE; if ( !NT_SUCCESS ( nStatus )) { // raise irql to dispatch KeRaiseIrql(DISPATCH_LEVEL,&OldIrql); // call DMA nStatus = SystemAdapterObject->DmaOperations->GetScatterGatherList( SystemAdapterObject, DeviceObject, Buffer, MmGetMdlVirtualAddress(Buffer), PacketLength, MpProcessSGList, Packet, TRUE ); KeLowerIrql( OldIrql ); if ( !NT_SUCCESS ( nStatus )){ DBGLOG(( LError, "%08X=GetScatterGatherList failed\n",nStatus )); } } if ( fbDMAV2 && !NT_SUCCESS ( nStatus ) ) { SendBuffer = ExAllocatePoolWithTag( NonPagedPool, PacketLength, MODULE_TAG ); if ( SendBuffer == NULL ){ DBGLOG(( LError, "ExAllocatePoolWithTag failed\n" )); nStatus = NDIS_STATUS_RESOURCES; break; } NdisAllocateBuffer( &nStatus, &SendNdisBuffer, NULL, SendBuffer, PacketLength ); if ( nStatus != NDIS_STATUS_SUCCESS ){ DBGLOG(( LError, "%08X=NdisAllocateBuffer failed\n",nStatus )); break; } //copy data to intermediate buffer fbResult = NDIS_CopyPacketData( Packet, SendBuffer, PacketLength,0, &nBytesRead ); if ( !fbResult || nBytesRead != PacketLength ){ DBGLOG(( LError, "NDIS_CopyPacketData failed\n" )); nStatus = NDIS_STATUS_RESOURCES; break; } Packet->Private.Flags |= NDIS_FLAGS_DOUBLE_BUFFERED; // sg list NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, NdisReserved) = SendBuffer; // raise irql to dispatch KeRaiseIrql(DISPATCH_LEVEL,&OldIrql); // call DMA nStatus = SystemAdapterObject->DmaOperations->GetScatterGatherList( SystemAdapterObject, DeviceObject, SendNdisBuffer, MmGetMdlVirtualAddress(SendNdisBuffer), PacketLength, MpProcessSGList, Packet, TRUE ); KeLowerIrql( OldIrql ); } if ( !NT_SUCCESS ( nStatus ) ){ if ( SendNdisBuffer ){ NdisFreeBuffer( SendNdisBuffer ); } if ( SendBuffer ){ ExFreePoolWithTag( SendBuffer, MODULE_TAG ); } NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, NdisReserved) = NULL; if (KIP_MINIPORT_TEST_FLAG(pAdapter, fADAPTER_IS_CO)) { ASSERT(FALSE); // TODO: //NdisMCoSendComplete(NDIS_STATUS_FAILURE, GET_VCPTR_FROM_PACKET(Packet), Packet); } else { //MpSendPacketCompleteHandler( pAdapter, Packet, NDIS_STATUS_FAILURE ); // we complete it in caller } } } while ( FALSE ); return nStatus; }
NDIS_STATUS shared_flush( IN shared_info_t *shared, IN uchar *va, IN ULONG pa, IN ULONG len, IN BOOLEAN writetodevice ) { #ifndef NDIS60 PNDIS_BUFFER b; NDIS_STATUS status; NDIS_PHYSICAL_ADDRESS npa; /* if receive, buffer must begin and end on a cacheline boundary */ if (!writetodevice) { ASSERT(ISALIGNED((uintptr)va, shared->cacheline)); len = ROUNDUP(len, shared->cacheline); } /* alloc a temp buffer descriptor */ NdisAllocateBuffer(&status, &b, shared->rxbufferpool, va, len); if (status != NDIS_STATUS_SUCCESS) { ND_ERROR(("%s%d: shared_flush: NdisAllocateBuffer error 0x%x\n", shared->id, shared->unit, status)); return status; } /* flush processor cache */ NdisAdjustBufferLength(b, len); NdisFlushBuffer(b, writetodevice); npa.HighPart = 0; npa.LowPart = pa; #ifndef USEWDK if (!writetodevice) NdisMUpdateSharedMemory(shared->adapterhandle, len, va, npa); #endif /* USEWDK */ /* free the temp buffer descriptor */ NdisFreeBuffer(b); #else /* NDIS60 */ PMDL b; /* if receive, buffer must begin and end on a cacheline boundary */ if (!writetodevice) { ASSERT(ISALIGNED((uintptr)va, shared->cacheline)); len = ROUNDUP(len, shared->cacheline); } /* alloc a temp MDL */ b = NdisAllocateMdl(shared->adapterhandle, va, len); if (b == NULL) { ND_ERROR(("%s%d: shared_flush: NdisAllocateMdl error\n", shared->id, shared->unit)); return NDIS_STATUS_FAILURE; } /* flush processor cache */ NdisAdjustMdlLength(b, len); NdisFlushBuffer(b, writetodevice); /* free the temp MDL */ NdisFreeMdl(b); #endif /* NDIS60 */ return NDIS_STATUS_SUCCESS; }
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; }
VOID PacketAllocatePacketBuffer(PNDIS_STATUS pStatus, POPEN_INSTANCE pOpen, PNDIS_PACKET *ppPacket, PDIOCPARAMETERS pDiocParms, DWORD FunctionCode ) { // allocate a buffer for reading/writing PNDIS_BUFFER pNdisBuffer; PNDIS_PACKET pPacket; // Try to get a packet from our list of free ones NdisAllocatePacket(pStatus, ppPacket, pOpen->PacketPool); if (*pStatus != NDIS_STATUS_SUCCESS) { *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; return; } pPacket = *ppPacket; // Buffers used asynchronously must be page locked switch (FunctionCode) { case IOCTL_EPACKET_READ: RESERVED(pPacket)->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvOutBuffer, pDiocParms->cbOutBuffer); RESERVED(pPacket)->cbBuffer = pDiocParms->cbOutBuffer; break; case IOCTL_EPACKET_WRITE: RESERVED(pPacket)->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvInBuffer, pDiocParms->cbInBuffer); RESERVED(pPacket)->cbBuffer = pDiocParms->cbInBuffer; break; default: // recycle the packet NdisReinitializePacket(pPacket); // Put the packet on the free queue NdisFreePacket(pPacket); *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; *pStatus = NDIS_STATUS_NOT_ACCEPTED; return; } RESERVED(pPacket)->lpcbBytesReturned = (PVOID)PacketPageLock(pDiocParms->lpcbBytesReturned, sizeof(DWORD)); RESERVED(pPacket)->lpoOverlapped = (PVOID)PacketPageLock(pDiocParms->lpoOverlapped, sizeof(OVERLAPPED)); RESERVED(pPacket)->hDevice = pDiocParms->hDevice; RESERVED(pPacket)->tagProcess = pDiocParms->tagProcess; switch (FunctionCode) { case IOCTL_EPACKET_READ: NdisAllocateBuffer(pStatus, &pNdisBuffer, pOpen->BufferPool, (PVOID)(RESERVED(pPacket)->lpBuffer + ETHERNET_HEADER_LENGTH), pDiocParms->cbOutBuffer); break; case IOCTL_EPACKET_WRITE: NdisAllocateBuffer(pStatus, &pNdisBuffer, pOpen->BufferPool, (PVOID)RESERVED(pPacket)->lpBuffer, pDiocParms->cbInBuffer); break; } if (*pStatus == NDIS_STATUS_SUCCESS) NdisChainBufferAtFront(pPacket, pNdisBuffer); // Attach buffer to Packet else { NdisReinitializePacket(pPacket); // recycle the packet NdisFreePacket(pPacket); // Put the packet on the free queue *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; } }
NTSTATUS netgSendToMiniport(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { PIO_STACK_LOCATION pIrpSp; NTSTATUS NtStatus = STATUS_SUCCESS; NDIS_STATUS Status; ULONG BytesReturned = 0; PUCHAR ioBuffer = NULL; ULONG inputBufferLength; ULONG outputBufferLength, Remaining; POPEN_CONTEXT pOpenContext; PNDIS_PACKET pNdisPacket; PNDIS_BUFFER pNdisBuffer; DBGPRINT((" netgSendToMiniport Called \n")); UNREFERENCED_PARAMETER(pDeviceObject); pIrpSp = IoGetCurrentIrpStackLocation(pIrp); pOpenContext = pIrpSp->FileObject->FsContext; ioBuffer = pIrp->AssociatedIrp.SystemBuffer; inputBufferLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength; Remaining = outputBufferLength; DBGPRINT(("==> netgSendToMiniport: FileObject %p\n", pIrpSp->FileObject )); if( !pOpenContext ) { DBGPRINT(( " Invalid Handle\n" )); NtStatus = STATUS_INVALID_HANDLE; goto CompleteTheIRP; } DBGPRINT((" Len: %d Data: %x%x...\n", pIrpSp->Parameters.DeviceIoControl.InputBufferLength, ioBuffer[0], ioBuffer[1])); // Allocate a send packet. pNdisPacket = NULL; NdisAllocatePacket(&Status, &pNdisPacket, pOpenContext->SendPacketPool); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT((" netgSendToMiniport: open %p, failed to alloc send pkt\n", pOpenContext)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; goto CompleteTheIRP; } // Allocate a send buffer. NdisAllocateBuffer(&Status, &pNdisBuffer, pOpenContext->SendBufferPool, ioBuffer, inputBufferLength); if (Status != NDIS_STATUS_SUCCESS) { NdisFreePacket(pNdisPacket); DBGPRINT((" netgSendToMiniport: open %p, failed to alloc send buf\n", pOpenContext)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; goto CompleteTheIRP; } IoMarkIrpPending(pIrp); ((PNPROT_SEND_PACKET_RSVD)&((pNdisPacket)->ProtocolReserved[0]))->RefCount = 1; (((PNPROT_SEND_PACKET_RSVD)&((pNdisPacket)->ProtocolReserved[0]))->pIrp) = pIrp; NtStatus = STATUS_PENDING; pNdisBuffer->Next = NULL; NdisChainBufferAtFront(pNdisPacket, pNdisBuffer); NdisSendPackets(pOpenContext->pAdapt->BindingHandle, &pNdisPacket, 1); CompleteTheIRP: if (NtStatus != STATUS_PENDING) { pIrp->IoStatus.Information = BytesReturned; pIrp->IoStatus.Status = NtStatus; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } DBGPRINT(("<== netgSendToMiniport\n")); return NtStatus; }
NDIS_STATUS NdisuioReceive( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID pHeaderBuffer, IN UINT HeaderBufferSize, IN PVOID pLookaheadBuffer, IN UINT LookaheadBufferSize, IN UINT PacketSize ) /*++ Routine Description: Our protocol receive handler called by NDIS, typically if we have a miniport below that doesn't indicate packets. We make a local packet/buffer copy of this data, queue it up, and kick off the read service routine. Arguments: ProtocolBindingContext - pointer to open context MacReceiveContext - for use in NdisTransferData pHeaderBuffer - pointer to data header HeaderBufferSize - size of the above pLookaheadBuffer - pointer to buffer containing lookahead data LookaheadBufferSize - size of the above PacketSize - size of the entire packet, minus header size. Return Value: NDIS_STATUS_NOT_ACCEPTED - if this packet is uninteresting NDIS_STATUS_SUCCESS - if we processed this successfully --*/ { PNDISUIO_OPEN_CONTEXT pOpenContext; NDIS_STATUS Status; PNDISUIO_ETH_HEADER pEthHeader; PNDIS_PACKET pRcvPacket; PUCHAR pRcvData; UINT BytesTransferred; PNDIS_BUFFER pOriginalNdisBuffer, pPartialNdisBuffer; PIRP pIrp; PLIST_ENTRY pIrpEntry; ULONG BytesRemaining; // at pDst PPACKET_GROUP pGroup; //ULONG pDst; pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext; NUIO_STRUCT_ASSERT(pOpenContext, oc); pRcvPacket = NULL; pRcvData = NULL; Status = NDIS_STATUS_SUCCESS; DEBUGP(DL_LOUD, ("Receive: Open %p, LookaheadBufferSize %d, PacketSize %d\n", pOpenContext, LookaheadBufferSize, PacketSize)); NdisInterlockedAddLargeStatistic((PLARGE_INTEGER)&pOpenContext->ReceivedPackets, 1); do { if (HeaderBufferSize != sizeof(NDISUIO_ETH_HEADER)) { Status = NDIS_STATUS_NOT_ACCEPTED; break; } pEthHeader = (PNDISUIO_ETH_HEADER)pHeaderBuffer; NUIO_ACQUIRE_LOCK(&pOpenContext->Lock); // // Someone is reading, and this is the first packet. // if (!NUIO_IS_LIST_EMPTY(&pOpenContext->PendedReads) && NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue)) { // // Get the first pended Read IRP // pIrpEntry = pOpenContext->PendedReads.Flink; pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry); // // 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(pIrp, NULL); NUIO_REMOVE_ENTRY_LIST(pIrpEntry); pOpenContext->PendedReadCount--; NUIO_RELEASE_LOCK(&pOpenContext->Lock); NUIO_DEREF_OPEN(pOpenContext); // Service: dequeue rcv packet // // Copy as much data as possible from the receive packet to // the IRP MDL. // #ifndef WIN9X pGroup = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); //NUIO_ASSERT(pDst != NULL); // since it was already mapped #else pGroup = MmGetSystemAddressForMdl(pIrp->MdlAddress); // Win9x #endif BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress); BytesRemaining -= sizeof(PACKET_GROUP); // // copy the ethernet header into the actual readbuffer // NdisMoveMappedMemory(pGroup->Data, pHeaderBuffer, HeaderBufferSize); if (PacketSize == LookaheadBufferSize) { BytesTransferred = MIN(LookaheadBufferSize, BytesRemaining); NdisCopyLookaheadData(pGroup->Data + HeaderBufferSize, pLookaheadBuffer, BytesTransferred, pOpenContext->MacOptions); pGroup->Length = BytesTransferred + HeaderBufferSize; pIrp->IoStatus.Information = pGroup->Length + sizeof(PACKET_GROUP); pIrp->IoStatus.Status = STATUS_SUCCESS; DEBUGP(DL_LOUD, ("Receive: %d bytes\n", pIrp->IoStatus.Information)); IoCompleteRequest(pIrp, IO_NO_INCREMENT); } else { BytesTransferred = 0; NdisAllocatePacket( &Status, &pRcvPacket, pOpenContext->RecvBufferPool ); if (Status != NDIS_STATUS_SUCCESS) goto ERROR; // // Allocate an MDL to map the portion of the buffer following the // header // pPartialNdisBuffer = IoAllocateMdl(pGroup->Data, BytesRemaining, FALSE, FALSE, NULL); if (pPartialNdisBuffer == NULL) { NdisFreePacket(pRcvPacket); Status = NDIS_STATUS_RESOURCES; goto ERROR; } // // Build the mdl to point to the the portion of the buffer following // the header // IoBuildPartialMdl( pIrp->MdlAddress, pPartialNdisBuffer, pGroup->Data + HeaderBufferSize, 0); // // Clear the next link in the new MDL // pPartialNdisBuffer->Next = NULL; // // Get a pointer to the packet itself. // NUIO_IRP_FROM_RCV_PKT(pRcvPacket) = pIrp; NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pRcvPacket) = pPartialNdisBuffer; // // Attach our partial MDL to the packet // NdisChainBufferAtFront(pRcvPacket, pPartialNdisBuffer); // // Call the Mac to transfer the packet // NdisTransferData( &Status, pOpenContext->BindingHandle, MacReceiveContext, 0, // ByteOffset PacketSize, pRcvPacket, &BytesTransferred); ERROR: // // If it didn't pend, call the completeion routine now // if (Status != NDIS_STATUS_PENDING) { NdisuioTransferDataComplete( (NDIS_HANDLE)pOpenContext, pRcvPacket, Status, BytesTransferred); } } break; } NUIO_RELEASE_LOCK(&pOpenContext->Lock); // // Allocate resources for queueing this up. // pRcvPacket = ndisuioAllocateReceivePacket( pOpenContext, PacketSize + HeaderBufferSize, &pRcvData ); if (pRcvPacket == NULL) { Status = NDIS_STATUS_NOT_ACCEPTED; break; } NdisMoveMappedMemory(pRcvData, pHeaderBuffer, HeaderBufferSize); // // Check if the entire packet is within the lookahead. // if (PacketSize == LookaheadBufferSize) { NdisCopyLookaheadData(pRcvData + HeaderBufferSize, pLookaheadBuffer, LookaheadBufferSize, pOpenContext->MacOptions); // // Queue this up for receive processing, and // try to complete some read IRPs. // ndisuioQueueReceivePacket(pOpenContext, pRcvPacket); } else { // // Allocate an NDIS buffer to map the receive area // at an offset "HeaderBufferSize" from the current // start. This is so that NdisTransferData can copy // in at the right point in the destination buffer. // NdisAllocateBuffer( &Status, &pPartialNdisBuffer, pOpenContext->RecvBufferPool, pRcvData + HeaderBufferSize, PacketSize); if (Status == NDIS_STATUS_SUCCESS) { // // Unlink and save away the original NDIS Buffer // that maps the full receive buffer. // NdisUnchainBufferAtFront(pRcvPacket, &pOriginalNdisBuffer); NUIO_RCV_PKT_TO_ORIGINAL_BUFFER(pRcvPacket) = pOriginalNdisBuffer; NUIO_IRP_FROM_RCV_PKT(pRcvPacket) = NULL; // // Link in the partial buffer for NdisTransferData to // operate on. // NdisChainBufferAtBack(pRcvPacket, pPartialNdisBuffer); DEBUGP(DL_LOUD, ("Receive: setting up for TransferData:" " Pkt %p, OriginalBuf %p, PartialBuf %p\n", pRcvPacket, pOriginalNdisBuffer, pPartialNdisBuffer)); NdisTransferData( &Status, pOpenContext->BindingHandle, MacReceiveContext, 0, // ByteOffset PacketSize, pRcvPacket, &BytesTransferred); } else { // // Failure handled below in TransferDataComplete. // BytesTransferred = 0; } if (Status != NDIS_STATUS_PENDING) { NdisuioTransferDataComplete( (NDIS_HANDLE)pOpenContext, pRcvPacket, Status, BytesTransferred); } } } while (FALSE); if (Status != NDIS_STATUS_SUCCESS && Status != NDIS_STATUS_PENDING) NdisInterlockedAddLargeStatistic((PLARGE_INTEGER)&pOpenContext->DroppedPackets, 1); return Status; }
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); }
/****************************************************************************** * * Name: AllocateRxQ() * * Description: Allocate Rx Buffer * * Arguments: PMRVDRV_ADAPTER Adapter * * Return Value: NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE * * Notes: * *****************************************************************************/ NDIS_STATUS AllocateRxQ( IN PMRVDRV_ADAPTER Adapter ) { ULONG i; NDIS_STATUS tStatus; BOOLEAN bSuccess = TRUE; PACKET_QUEUE_NODE **pNode; PNDIS_PACKET_OOB_DATA pOOB; /// Initialize rx-related variables Adapter->RxBufferPoolHandle = Adapter->RxPacketPoolHandle = NULL; // InitializeQKeeper(&Adapter->RxPacketFreeQueue); // for ( i=0; i < MRVDRV_NUM_RX_PKT_IN_QUEUE; i++ ) { Adapter->pRxBufVM[i] = NULL; Adapter->pRxBuffer[i] = NULL; Adapter->pRxPacket[i] = NULL; } /// Allocate all needed memory space do { // packet pool NdisAllocatePacketPoolEx( &tStatus, &Adapter->RxPacketPoolHandle, MRVDRV_NUM_RX_PKT_IN_QUEUE, MRVDRV_NUM_RX_PKT_IN_QUEUE, PROTOCOL_RESERVED_SIZE_IN_PACKET); if ( tStatus != NDIS_STATUS_SUCCESS ) { DBGPRINT(DBG_LOAD | DBG_ERROR, (L"Unable to allocate packet pool!\n")); return tStatus; } // buffer pool NdisAllocateBufferPool( &tStatus, &Adapter->RxBufferPoolHandle, MRVDRV_NUM_RX_PKT_IN_QUEUE); if ( tStatus != NDIS_STATUS_SUCCESS ) { DBGPRINT(DBG_LOAD | DBG_ERROR, (L"Unable to allocate buffer pool!\n")); bSuccess = FALSE; break; } // assign space to used three array for ( i=0; i < MRVDRV_NUM_RX_PKT_IN_QUEUE; i++ ) { // data payload space array tStatus = NdisAllocateMemoryWithTag( &Adapter->pRxBufVM[i], MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, MRVDRV_MEMORY_TAG); //to hide unused packet header ahead of pointer. //(ULONG)Adapter->pRxBufVM[i] += (sizeof(RxPD)+sizeof(pkt.Len)+sizeof(pkt.Type)); (ULONG)Adapter->pRxBufVM[i] += MRVDRV_ETH_RX_HIDDEN_HEADER_SIZE; if ( tStatus != NDIS_STATUS_SUCCESS ) { bSuccess = FALSE; break; } // buffer array NdisAllocateBuffer( &tStatus, &Adapter->pRxBuffer[i], Adapter->RxBufferPoolHandle, Adapter->pRxBufVM[i], (MRVDRV_ETH_RX_PACKET_BUFFER_SIZE-MRVDRV_ETH_RX_HIDDEN_HEADER_SIZE)); if ( tStatus != NDIS_STATUS_SUCCESS ) { bSuccess = FALSE; break; } // packet array NdisAllocatePacket( &tStatus, &Adapter->pRxPacket[i], Adapter->RxPacketPoolHandle); if ( tStatus != NDIS_STATUS_SUCCESS ) { bSuccess = FALSE; break; } // init OBB space pOOB = NDIS_OOB_DATA_FROM_PACKET(Adapter->pRxPacket[i]); NdisZeroMemory(pOOB, sizeof(NDIS_PACKET_OOB_DATA)); NDIS_SET_PACKET_HEADER_SIZE(Adapter->pRxPacket[i], MRVDRV_ETH_HEADER_SIZE); // chain the packet and buffer NdisChainBufferAtFront(Adapter->pRxPacket[i], Adapter->pRxBuffer[i]); // fill packet node Adapter->RxPacketQueueNode[i].pPacket = Adapter->pRxPacket[i]; pNode = (PACKET_QUEUE_NODE **)Adapter->pRxPacket[i]->MiniportReserved; *pNode = &Adapter->RxPacketQueueNode[i]; // insert to free queue InsertQNodeAtTail(&Adapter->RxPacketFreeQueue, &Adapter->RxPacketQueueNode[i]); } // end of for(;;) } while (0); if ( ! bSuccess ) { // clean up all FreeRxQ(Adapter); return NDIS_STATUS_FAILURE; } Adapter->sNumOutstandingRxPacket = 0; return NDIS_STATUS_SUCCESS; }
NDIS_STATUS NICAllocAdapter( PMP_ADAPTER *pAdapter) { PMP_ADAPTER Adapter = NULL; PNDIS_PACKET Packet; PNDIS_BUFFER Buffer; PUCHAR pTCBMem; PTCB pTCB; NDIS_STATUS Status; LONG index; DEBUGP(MP_TRACE, ("--> NICAllocAdapter\n")); PAGED_CODE(); *pAdapter = NULL; do { // // Allocate memory for adapter context // Status = NdisAllocateMemoryWithTag( &Adapter, sizeof(MP_ADAPTER), NIC_TAG); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("Failed to allocate memory for adapter context\n")); break; } // // Zero the memory block // NdisZeroMemory(Adapter, sizeof(MP_ADAPTER)); NdisInitializeListHead(&Adapter->List); // // Initialize Send & Recv listheads and corresponding // spinlocks. // //NdisInitializeListHead(&Adapter->RecvWaitList); //NdisInitializeListHead(&Adapter->SendWaitList); //NdisInitializeListHead(&Adapter->SendFreeList); NdisAllocateSpinLock(&Adapter->SendLock); //NdisInitializeListHead(&Adapter->RecvFreeList); NdisAllocateSpinLock(&Adapter->RecvLock); //allocate a packet pool NdisAllocatePacketPool( &Status, &Adapter->LdnRecvPacketPoolHandle, 1, PROTOCOL_RESERVED_SIZE_IN_PACKET); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocatePacketPool failed\n")); break; } //allocate a single packet in the pool NdisAllocatePacket( &Status, &Adapter->LdnRecvPacket, Adapter->LdnRecvPacketPoolHandle); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocatePacket failed\n")); break; } //allocate a buffer pool NdisAllocateBufferPool( &Status, &Adapter->LdnRecvBufferPoolHandle, 1); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocateBufferPool for recv buffer failed\n")); break; } //allocate a single buffer in the buffer pool NdisAllocateBuffer( &Status, &Adapter->LdnRecvPacketBuffer, Adapter->LdnRecvBufferPoolHandle, (PVOID)&Adapter->LdnRecvPacketBufferData[0], NIC_BUFFER_SIZE); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocateBuffer failed\n")); break; } //chain the buffer to the packet NdisChainBufferAtBack(Adapter->LdnRecvPacket, Adapter->LdnRecvPacketBuffer); NDIS_SET_PACKET_STATUS(Adapter->LdnRecvPacket, NDIS_STATUS_RESOURCES); NDIS_SET_PACKET_HEADER_SIZE(Adapter->LdnRecvPacket, ETH_HEADER_SIZE); /*// // Allocate lookside list for Receive Control blocks. // NdisInitializeNPagedLookasideList( &Adapter->RecvLookaside, NULL, // No Allocate function NULL, // No Free function 0, // Reserved for system use sizeof(RCB), NIC_TAG, 0); // Reserved for system use MP_SET_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE); // // Allocate packet pool for receive indications // NdisAllocatePacketPool( &Status, &Adapter->RecvPacketPoolHandle, NIC_MAX_BUSY_RECVS, PROTOCOL_RESERVED_SIZE_IN_PACKET); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocatePacketPool failed\n")); break; } // // Initialize receive packets // for(index=0; index < NIC_MAX_BUSY_RECVS; index++) { // // Allocate a packet descriptor for receive packets // from a preallocated pool. // NdisAllocatePacket( &Status, &Packet, Adapter->RecvPacketPoolHandle); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocatePacket failed\n")); break; } NDIS_SET_PACKET_HEADER_SIZE(Packet, ETH_HEADER_SIZE); // // Insert it into the list of free receive packets. // NdisInterlockedInsertTailList( &Adapter->RecvFreeList, (PLIST_ENTRY)&Packet->MiniportReserved[0], &Adapter->RecvLock); } // // Allocate a huge block of memory for all TCB's // Status = NdisAllocateMemoryWithTag( &pTCBMem, sizeof(TCB) * NIC_MAX_BUSY_SENDS, NIC_TAG); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("Failed to allocate memory for TCB's\n")); break; } NdisZeroMemory(pTCBMem, sizeof(TCB) * NIC_MAX_BUSY_SENDS); Adapter->TCBMem = pTCBMem; // // Allocate a buffer pool for send buffers. // NdisAllocateBufferPool( &Status, &Adapter->SendBufferPoolHandle, NIC_MAX_BUSY_SENDS); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocateBufferPool for send buffer failed\n")); break; } // // Divide the TCBMem blob into TCBs and create a buffer // descriptor for the Data portion of the TCBs. // for(index=0; index < NIC_MAX_BUSY_SENDS; index++) { pTCB = (PTCB) pTCBMem; // // Create a buffer descriptor for the Data portion of the TCBs. // Buffer descriptors are nothing but MDLs on NT systems. // NdisAllocateBuffer( &Status, &Buffer, Adapter->SendBufferPoolHandle, (PVOID)&pTCB->Data[0], NIC_BUFFER_SIZE); if(Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, ("NdisAllocateBuffer failed\n")); break; } // // Initialize the TCB structure. // pTCB->Buffer = Buffer; pTCB->pData = (PUCHAR) &pTCB->Data[0]; pTCB->Adapter = Adapter; NdisInterlockedInsertTailList( &Adapter->SendFreeList, &pTCB->List, &Adapter->SendLock); pTCBMem = pTCBMem + sizeof(TCB); }*/ } while(FALSE); *pAdapter = Adapter; // // In the failure case, the caller of this routine will end up // calling NICFreeAdapter to free all the successfully allocated // resources. // DEBUGP(MP_TRACE, ("<-- NICAllocAdapter\n")); return(Status); }
NDIS_STATUS natpReceive( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize ) { PFILTER_ADAPTER pAdapt; PNDIS_PACKET Packet; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; NDIS_STATUS PacketStatus; PNDIS_PACKET pNewPacket; ULONG nDataSize; FLT_PKT *pFltPkt; PNDIS_BUFFER pNewBuffer; pAdapt = (PFILTER_ADAPTER)ProtocolBindingContext; if ((!pAdapt->MiniportHandle) || (pAdapt->natmDeviceState > NdisDeviceStateD0)){ return NDIS_STATUS_FAILURE; } nDataSize = HeaderBufferSize + PacketSize; if ( nDataSize > MAX_ETHER_SIZE ){ return NDIS_STATUS_FAILURE; } Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext); if (NULL == Packet) return NDIS_STATUS_NOT_ACCEPTED; pFltPkt = AllocateFltPacket(); if(NULL == pFltPkt) return NDIS_STATUS_NOT_ACCEPTED; if(!natbParsePacket(Packet, pFltPkt)){ if(g_LogPktDrop) PrintFtlPkt("DROP ", pFltPkt, 0, FALSE); FreeFltPkt(pFltPkt); return NDIS_STATUS_NOT_ACCEPTED; } // // Translate // TranslatePktIncoming(&pAdapt->ctrl, pFltPkt); // // Filter // if(!FilterPkt(&pAdapt->ctrl, pFltPkt, FALSE)){ if(g_LogPktDrop) PrintFtlPkt("DROP ", pFltPkt, 0, FALSE); FreeFltPkt(pFltPkt); return NDIS_STATUS_NOT_ACCEPTED; } if(g_LogPktPass) PrintFtlPkt("PASS ", pFltPkt, 0, FALSE); if(NULL == pFltPkt->pBuf){ FreeFltPkt(pFltPkt); pFltPkt = NULL; NdisDprAllocatePacket( &Status, &pNewPacket, pAdapt->RcvPP1 ); if (Status != NDIS_STATUS_SUCCESS) { return NDIS_STATUS_NOT_ACCEPTED; } *((PVOID*)&pNewPacket->MiniportReserved) = NULL; pNewPacket->Private.Head = Packet->Private.Head; pNewPacket->Private.Tail = Packet->Private.Tail; }else{ NdisDprAllocatePacket( &Status, &pNewPacket, pAdapt->RcvPP2 ); if (Status != NDIS_STATUS_SUCCESS) return NDIS_STATUS_NOT_ACCEPTED; *((PVOID*)&pNewPacket->MiniportReserved) = pFltPkt; NdisAllocateBuffer( &Status, &pNewBuffer, pAdapt->RcvBP, pFltPkt->pBuf, pFltPkt->uLen ); if ( Status != NDIS_STATUS_SUCCESS ){ NdisReinitializePacket (pNewPacket); NdisFreePacket (pNewPacket); return NDIS_STATUS_NOT_ACCEPTED; } NdisChainBufferAtFront(pNewPacket, pNewBuffer ); } NdisGetPacketFlags(pNewPacket) = NdisGetPacketFlags(Packet); NDIS_SET_PACKET_STATUS(pNewPacket, NDIS_STATUS_RESOURCES); NDIS_SET_ORIGINAL_PACKET(pNewPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); NDIS_SET_PACKET_HEADER_SIZE(pNewPacket, HeaderBufferSize); natpQueueReceivedPacket(pAdapt, pNewPacket, TRUE); natmReturnPacket( ProtocolBindingContext, pNewPacket ); return Status; }
/* ************************************************************************* * DeliverFullBuffers ************************************************************************* * * Deliver received packets to the protocol. * */ VOID DeliverFullBuffers(IrDevice *thisDev) { int rcvBufIndex = thisDev->firstRcvBufIndex; DBGOUT(("==> DeliverFullBuffers")); /* * Deliver all full rcv buffers */ while (rcvBufIndex != NO_BUF_INDEX){ rcvBuffer *rcvBuf = &thisDev->rcvBufs[rcvBufIndex]; NDIS_STATUS stat; PNDIS_BUFFER packetBuf; SLOW_IR_FCS_TYPE fcs; switch (rcvBuf->state){ case STATE_FREE: case STATE_PENDING: /* * This frame was already delivered. Just go to the next one. */ break; case STATE_FULL: /* * The packet we have already has had BOFs, EOF, and * escape-sequences removed. * It contains an FCS code at the end, * which we need to verify and then remove before * delivering the frame. * We compute the FCS on the packet with the packet FCS * attached; this should produce the constant value GOOD_FCS. */ fcs = ComputeFCS(rcvBuf->dataBuf, rcvBuf->dataLen); if (fcs != GOOD_FCS){ /* * FCS Error. Drop this frame. */ DBGERR(("Bad FCS in DeliverFullBuffers 0x%x!=0x%x.", (UINT)fcs, (UINT)GOOD_FCS)); rcvBuf->state = STATE_FREE; DBGSTAT(("Dropped %d/%d packets; packet with BAD FCS (%xh!=%xh):", ++thisDev->packetsDropped, thisDev->packetsDropped + thisDev->packetsRcvd, fcs, GOOD_FCS)); DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen); break; } /* * Remove the FCS from the end of the packet. */ rcvBuf->dataLen -= SLOW_IR_FCS_SIZE; #ifdef DBG_ADD_PKT_ID if (addPktIdOn){ /* * Remove dbg packet id. */ rcvBuf->dataLen -= sizeof(USHORT); DBGOUT((" RCVing packet %xh **", (UINT)*(USHORT *)(rcvBuf->dataBuf+rcvBuf->dataLen))); } #endif /* * The packet array is set up with its NDIS_PACKET. * Now we need to allocate a single NDIS_BUFFER for the * NDIS_PACKET and set the NDIS_BUFFER to the part of dataBuf * that we want to deliver. */ NdisAllocateBuffer( &stat, &packetBuf, thisDev->bufferPoolHandle, (PVOID)rcvBuf->dataBuf, rcvBuf->dataLen); if (stat != NDIS_STATUS_SUCCESS){ DBGERR(("NdisAllocateBuffer failed")); break; } NdisChainBufferAtFront(rcvBuf->packet, packetBuf); /* * Fix up some other packet fields. */ NDIS_SET_PACKET_HEADER_SIZE(rcvBuf->packet, SLOW_IR_ADDR_SIZE + SLOW_IR_CONTROL_SIZE); DBGPKT(("Indicating rcv packet 0x%x.", (UINT)rcvBuf->packet)); DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen); /* * Indicate to the protocol that another packet is ready. * Set the rcv buffer's state to PENDING first to avoid * a race condition with NDIS's call to the return packet * handler. */ rcvBuf->state = STATE_PENDING; NdisMIndicateReceivePacket(thisDev->ndisAdapterHandle, &rcvBuf->packet, 1); stat = NDIS_GET_PACKET_STATUS(rcvBuf->packet); if (stat == NDIS_STATUS_PENDING){ /* * The packet is being delivered asynchronously. * Leave the rcv buffer's state as PENDING; we'll * get a callback when the transfer is complete. * * Do NOT step firstRcvBufIndex. * We don't really need to break out here, * but we will anyways just to make things simple. * This is ok since we get this deferred interrupt callback * for each packet anyway. It'll give the protocol a chance * to catch up. */ DBGSTAT(("Rcv Pending. Rcvd %d packets", ++thisDev->packetsRcvd)); } else { /* * If there was an error, we are dropping this packet; * otherwise, this packet was delivered synchronously. * We can free the packet buffer and make this rcv frame * available. */ NdisUnchainBufferAtFront(rcvBuf->packet, &packetBuf); if (packetBuf){ NdisFreeBuffer(packetBuf); } rcvBuf->state = STATE_FREE; if (stat == NDIS_STATUS_SUCCESS){ DBGSTAT(("Rcvd %d packets", ++thisDev->packetsRcvd)); } else { DBGSTAT(("Dropped %d/%d rcv packets. ", thisDev->packetsDropped++, thisDev->packetsDropped+thisDev->packetsRcvd)); } } break; default: /* * This should never happen. */ DBGERR(("Bad rcv buffer state in DPC")); break; } /* * Step the buffer index */ if (rcvBufIndex == thisDev->lastRcvBufIndex){ rcvBufIndex = NO_BUF_INDEX; } else { rcvBufIndex = NEXT_RCV_BUF_INDEX(rcvBufIndex); } } DBGOUT(("<== DeliverFullBuffers")); }
// //发送相关函数的实现、 // NTSTATUS SecLabSendPacket( PADAPT pAdapt, IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp ) { PIO_STACK_LOCATION pIrpSp; ULONG FunctionCode; ULONG DataLength; NTSTATUS NtStatus=STATUS_INVALID_HANDLE; NDIS_STATUS Status; PNDIS_PACKET pNdisPacket; PNDIS_BUFFER pNdisBuffer; // SECLAB_ETH_HEADER UNALIGNED *pEthHeader; PUCHAR pData; ULONG i; #ifdef NDIS51 PVOID CancelId; #endif pIrpSp = IoGetCurrentIrpStackLocation(pIrp); pNdisPacket = NULL; pNdisBuffer = NULL; do { if (pAdapt == NULL) { DbgPrint("Write: FileObject not yet associated with a device\n"); NtStatus = STATUS_INVALID_HANDLE; break; } // // 检查发送数据包的长度 // DataLength=pIrpSp->Parameters.DeviceIoControl.InputBufferLength; if (DataLength > MAX_SEND_PACKETLEN ) { DbgPrint("Write: Open data length larger than max frame size\n"); NtStatus = STATUS_UNSUCCESSFUL; break; } // // 构造一个发送封包 // if(pAdapt->SendPacketPoolHandle==NULL) { DbgPrint("The Packet Pool should not be NULL"); DbgBreakPoint(); break; } do { //其实怎么样分配内存是无关紧要的,忘记资源的释放也不是很严重的 //最多导致内存支出过多。关键是不能让程序引用不存在的内存,这样会 //造成崩溃,比如重复释放内存。崩溃的另一大可能是在Dispatch>=passive //级别上调用非分页内存。 //pData=(PUCHAR)ExAllocatePool(NonPagedPool,DataLength); NdisAllocateMemoryWithTag((PVOID *)(&pData), DataLength,'lceS'); if(pData==NULL) { DbgPrint("Can not allocate pool for send"); break; } //RtlCopyMemory(pData,pIrp->AssociatedIrp.SystemBuffer,DataLength); NdisMoveMemory(pData,pIrp->AssociatedIrp.SystemBuffer,DataLength); // // 将其转化为NDIS_BUFFER. // NdisAllocateBuffer( &Status, &pNdisBuffer, SendBufferPool, pData, DataLength); if (Status != NDIS_STATUS_SUCCESS) { DbgPrint("failed to allocate Ndis Buffer"); break; } NdisAllocatePacket(&Status, &pNdisPacket, pAdapt->SendPacketPoolHandle); if (Status != NDIS_STATUS_SUCCESS) { DbgPrint("failed to alloc NDIS packet"); break; } NDIS_SET_PACKET_STATUS(pNdisPacket, 0); pNdisBuffer->Next = NULL; NdisChainBufferAtFront(pNdisPacket, pNdisBuffer); pNdisPacket->Private.Head->Next=NULL; pNdisPacket->Private.Tail=NULL; break; } while (FALSE); if (pNdisPacket == NULL || pNdisBuffer==NULL) { // // Clean up // if (pNdisBuffer != NULL) { NdisFreeBuffer(pNdisBuffer); } if (pData != NULL) { NdisFreeMemory(pData, 0, 0); } } IoMarkIrpPending(pIrp); NtStatus = STATUS_PENDING; pIrp->IoStatus.Status = STATUS_PENDING; // // 初始化封包中的标志符。当标志符值为0时此包被释放 // SECLAB_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 = SECLAB_GET_NEXT_CANCEL_ID(); NDIS_SET_PACKET_CANCEL_ID(pNdisPacket, CancelId); pIrp->Tail.Overlay.DriverContext[0] = (PVOID)pAdapt; pIrp->Tail.Overlay.DriverContext[1] = (PVOID)pNdisPacket; NdisInterlockedIncrement(&PendedSendCount); NdisAcquireSpinLock(&WriteIrpLock); InsertTailList(&PendedWritesList, &pIrp->Tail.Overlay.ListEntry); IoSetCancelRoutine(pIrp, SecLabCancelWrite); NdisReleaseSpinLock(&WriteIrpLock); #endif // NDIS51 // // 创建一个指针从packet回指向IRP // SECLAB_IRP_FROM_SEND_PKT(pNdisPacket) = pIrp; // //创建三个信号,以便在发送完成例程中指示此包 // SECLAB_SIGNAL1_FROM_SEND_PKT(pNdisPacket)=SIGNAL1; SECLAB_SIGNAL2_FROM_SEND_PKT(pNdisPacket)=SIGNAL2; SECLAB_SIGNAL3_FROM_SEND_PKT(pNdisPacket)=SIGNAL3; // //发包 // NdisSendPackets(pAdapt->BindingHandle, &pNdisPacket, 1); } while (FALSE); if (NtStatus != STATUS_PENDING) { pIrp->IoStatus.Status = NtStatus; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } return (NtStatus); }