u8* _malloc(u32 sz) { u8 *pbuf; #ifdef PLATFORM_LINUX #ifdef RTK_DMP_PLATFORM if(sz > 0x4000) pbuf = dvr_malloc(sz); else #endif pbuf = kmalloc(sz, /*GFP_KERNEL*/GFP_ATOMIC); #endif #ifdef PLATFORM_WINDOWS NdisAllocateMemoryWithTag(&pbuf,sz, RT_TAG); #endif if ( pbuf == NULL ) printk( "[%s] allocate memory failed! sz = %d\n", __FUNCTION__, sz); return pbuf; }
BOOLEAN FilterPacket_ReceiveHandler ( PVOID pHeadBuffer, ULONG ulHeadSize, PNDIS_PACKET pPacket ) /*++ Routine Description: Filters network packets for NDISReceiveHandler. Arguments: ... Return Value: TRUE: This packet should be blocked. FALSE: This packet should pass through. Author: xiaonie 2012/07/12 --*/ { ULONG ulPacketSize; PUCHAR pBuffer = NULL; NDIS_STATUS status; PNDIS_BUFFER pFirstBuffer, pNextBuffer; BOOLEAN bRet = FALSE; NdisQueryPacket(pPacket, NULL, NULL, NULL, &ulPacketSize); if (ulPacketSize == 0) return FALSE; DbgPrint("ulHeadSize == %d, ulPacketSize == %d in FilterPacket_ReceiveHandler!\r\n", ulHeadSize, ulPacketSize); status = NdisAllocateMemoryWithTag(&pBuffer, ulPacketSize + ulHeadSize, '!nmN'); if (status != NDIS_STATUS_SUCCESS/* || pBuffer == NULL */) return FALSE; //obtain content from the packet NdisMoveMemory(pBuffer, pHeadBuffer, ulHeadSize); ReadPacket(pPacket, pBuffer + ulHeadSize, ulPacketSize); bRet = RabbitHole(pBuffer, ulPacketSize + ulHeadSize); NdisFreeMemory(pBuffer, ulPacketSize + ulHeadSize, 0); return bRet; }
u8* _rtw_malloc(u32 sz) { u8 *pbuf=NULL; #ifdef PLATFORM_LINUX #ifdef RTK_DMP_PLATFORM if(sz > 0x4000) pbuf = (u8 *)dvr_malloc(sz); else #endif pbuf = kmalloc(sz,in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); #endif #ifdef PLATFORM_FREEBSD pbuf = malloc(sz,M_DEVBUF,M_NOWAIT); #endif #ifdef PLATFORM_WINDOWS NdisAllocateMemoryWithTag(&pbuf,sz, RT_TAG); #endif #ifdef DBG_MEMORY_LEAK #ifdef PLATFORM_LINUX if ( pbuf != NULL) { atomic_inc(&_malloc_cnt); atomic_add(sz, &_malloc_size); } #endif #endif /* DBG_MEMORY_LEAK */ return pbuf; }
PVOID MemAlloc( __in ULONG p_Size, __in BOOLEAN zero ) { PVOID l_Return = NULL; if (p_Size) { __try { if (NdisAllocateMemoryWithTag (&l_Return, p_Size, 'APAT') == NDIS_STATUS_SUCCESS) { if (zero) { NdisZeroMemory (l_Return, p_Size); } } else { l_Return = NULL; } } __except (EXCEPTION_EXECUTE_HANDLER) { l_Return = NULL; } } return l_Return; }
inline u8* _rtw_vmalloc(u32 sz) { u8 *pbuf; #ifdef PLATFORM_LINUX pbuf = vmalloc(sz); #endif #ifdef PLATFORM_FREEBSD pbuf = malloc(sz,M_DEVBUF,M_NOWAIT); #endif #ifdef PLATFORM_WINDOWS NdisAllocateMemoryWithTag(&pbuf,sz, RT_TAG); #endif #ifdef DBG_MEMORY_LEAK #ifdef PLATFORM_LINUX if ( pbuf != NULL) { atomic_inc(&_malloc_cnt); atomic_add(sz, &_malloc_size); } #endif #endif /* DBG_MEMORY_LEAK */ return pbuf; }
u8* _rtw_malloc(u32 sz) { u8 *pbuf=NULL; #ifdef PLATFORM_LINUX #ifdef RTK_DMP_PLATFORM if(sz > 0x4000) pbuf = (u8 *)dvr_malloc(sz); else #endif pbuf = kmalloc(sz, /*GFP_KERNEL*/GFP_ATOMIC); #endif #ifdef PLATFORM_WINDOWS NdisAllocateMemoryWithTag(&pbuf,sz, RT_TAG); #endif #ifdef MEMORY_LEAK_DEBUG #ifdef PLATFORM_LINUX if ( pbuf != NULL) { atomic_inc(&_malloc_cnt); atomic_add(sz, &_malloc_size); } #endif #endif /* MEMORY_LEAK_DEBUG */ return pbuf; }
/*----------------------------------------------------------------------------*/ PVOID kalMemAlloc(IN UINT_32 u4Size, IN ENUM_KAL_MEM_ALLOCATION_TYPE eMemType) { PVOID pvAddr; if (NdisAllocateMemoryWithTag(&pvAddr, u4Size, NIC_MEM_TAG) == NDIS_STATUS_SUCCESS) { return pvAddr; } return NULL; } /* kalMemAlloc */
BOOLEAN FilterPacket_ProtocolReceiveHandler ( PNDIS_PACKET pPacket ) /*++ Routine Description: Filters network packets for NDISProtocolReceiveHandler. Arguments: pPacket - Pointer to the packet buffer descriptor. Return Value: TRUE: This packet should be blocked. FALSE: This packet should pass through. Author: xiaonie 2012/07/12 --*/ { ULONG ulTotalPacketLength; PUCHAR pBuffer = NULL; BOOLEAN bRet = FALSE; NDIS_STATUS status; NdisQueryPacket(pPacket, NULL, NULL, NULL, &ulTotalPacketLength); if (ulTotalPacketLength == 0) return FALSE; status = NdisAllocateMemoryWithTag(&pBuffer, ulTotalPacketLength, '!nmN'); if (status != NDIS_STATUS_SUCCESS/* || pBuffer == NULL*/) return FALSE; ReadPacket(pPacket, pBuffer, ulTotalPacketLength); // filter it! bRet = RabbitHole(pBuffer, ulTotalPacketLength); NdisFreeMemory(pBuffer, ulTotalPacketLength, 0); return bRet; }
inline u8* _rtw_vmalloc(u32 sz) { u8 *pbuf; #ifdef PLATFORM_LINUX pbuf = vmalloc(sz); #endif #ifdef PLATFORM_WINDOWS NdisAllocateMemoryWithTag(&pbuf,sz, RT_TAG); #endif return pbuf; }
u8* _rtw_malloc(u32 sz) { u8 *pbuf; #ifdef PLATFORM_LINUX pbuf = kmalloc(sz, /*GFP_KERNEL*/GFP_ATOMIC); #endif #ifdef PLATFORM_WINDOWS NdisAllocateMemoryWithTag(&pbuf,sz, RT_TAG); #endif return pbuf; }
// 向适配器过滤列表中添加一个过滤规则 NTSTATUS AddFilterToAdapter(PADAPT_FILTER_RSVD pFilterContext, PPassthruFilter pFilter) { PPassthruFilterList pNew; // 为新的过滤规则申请内存空间 if(NdisAllocateMemoryWithTag(&pNew, sizeof(PassthruFilterList), TAG) != NDIS_STATUS_SUCCESS) return STATUS_INSUFFICIENT_RESOURCES; // 填充这块内存 NdisMoveMemory(&pNew->filter, pFilter, sizeof(PassthruFilter)); // 连接到过滤列表中 pNew->pNext = pFilterContext->pFilterList; pFilterContext->pFilterList = pNew; return STATUS_SUCCESS; }
inline u8* _rtw_zvmalloc(u32 sz) { u8 *pbuf; #ifdef PLATFORM_LINUX pbuf = _rtw_vmalloc(sz); if (pbuf != NULL) memset(pbuf, 0, sz); #endif #ifdef PLATFORM_WINDOWS NdisAllocateMemoryWithTag(&pbuf,sz, RT_TAG); if (pbuf != NULL) NdisFillMemory(pbuf, sz, 0); #endif return pbuf; }
// Memory allocation void *NeoMalloc(UINT size) { NDIS_STATUS r; void *p; if (size == 0) { size = 1; } // Allocate the non-paged memory r = NdisAllocateMemoryWithTag(&p, size, 'SETH'); if (NG(r)) { return NULL; } return p; }
u8* _rtw_zmalloc(u32 sz) { u8 *pbuf; #ifdef PLATFORM_LINUX // kzalloc(sz, GFP_KERNEL); pbuf = kmalloc(sz, /*GFP_KERNEL*/GFP_ATOMIC); if (pbuf != NULL) memset(pbuf, 0, sz); #endif #ifdef PLATFORM_WINDOWS NdisAllocateMemoryWithTag(&pbuf,sz, RT_TAG); if (pbuf != NULL) NdisFillMemory(pbuf, sz, 0); #endif return pbuf; }
static __inline shared_buffer_t * get_pb_from_freelist(struct xennet_info *xi) { NDIS_STATUS status; shared_buffer_t *pb; PVOID ptr_ref; if (stack_pop(xi->rx_pb_stack, &ptr_ref)) { pb = ptr_ref; pb->ref_count = 1; InterlockedDecrement(&xi->rx_pb_free); return pb; } /* don't allocate a new one if we are shutting down */ if (xi->shutting_down) return NULL; status = NdisAllocateMemoryWithTag(&pb, sizeof(shared_buffer_t), XENNET_POOL_TAG); if (status != STATUS_SUCCESS) { return NULL; } status = NdisAllocateMemoryWithTag(&pb->virtual, PAGE_SIZE, XENNET_POOL_TAG); if (status != STATUS_SUCCESS) { NdisFreeMemory(pb, sizeof(shared_buffer_t), 0); return NULL; } pb->gref = (grant_ref_t)xi->vectors.GntTbl_GrantAccess(xi->vectors.context, (ULONG)(MmGetPhysicalAddress(pb->virtual).QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF, (ULONG)'XNRX'); if (pb->gref == INVALID_GRANT_REF) { NdisFreeMemory(pb, sizeof(shared_buffer_t), 0); NdisFreeMemory(pb->virtual, PAGE_SIZE, 0); return NULL; }
u8* _malloc(u32 sz) { u8 *pbuf; #ifdef PLATFORM_LINUX #ifdef RTK_DMP_PLATFORM if(sz > 0x4000) pbuf = dvr_malloc(sz); else #endif pbuf = kmalloc(sz, /*GFP_KERNEL*/GFP_ATOMIC); #endif #ifdef PLATFORM_WINDOWS NdisAllocateMemoryWithTag(&pbuf,sz, RT_TAG); #endif return pbuf; }
VOID PtBindAdapter( OUT PNDIS_STATUS Status, IN NDIS_HANDLE BindContext, IN PNDIS_STRING DeviceName, IN PVOID SystemSpecific1, IN PVOID SystemSpecific2 ) /*++ Routine Description: Called by NDIS to bind to a miniport below. Arguments: Status - Return status of bind here. BindContext - Can be passed to NdisCompleteBindAdapter if this call is pended. DeviceName - Device name to bind to. This is passed to NdisOpenAdapter. SystemSpecific1 - Can be passed to NdisOpenProtocolConfiguration to read per-binding information SystemSpecific2 - Unused Return Value: NDIS_STATUS_PENDING if this call is pended. In this case call NdisCompleteBindAdapter to complete. Anything else Completes this call synchronously --*/ { NDIS_HANDLE ConfigHandle = NULL; PNDIS_CONFIGURATION_PARAMETER Param; NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings"); PADAPT pAdapt = NULL; NDIS_STATUS Sts; UINT MediumIndex; ULONG TotalSize; PNDIS_CONFIGURATION_PARAMETER BundleParam; NDIS_STRING BundleStr = NDIS_STRING_CONST("BundleId"); NDIS_STATUS BundleStatus; DBGPRINT(("==> Protocol BindAdapter\n")); do { // // Access the configuration section for our binding-specific // parameters. // NdisOpenProtocolConfiguration(Status, &ConfigHandle, SystemSpecific1); if (*Status != NDIS_STATUS_SUCCESS) { break; } // // Read the "UpperBindings" reserved key that contains a list // of device names representing our miniport instances corresponding // to this lower binding. Since this is a 1:1 IM driver, this key // contains exactly one name. // // If we want to implement a N:1 mux driver (N adapter instances // over a single lower binding), then UpperBindings will be a // MULTI_SZ containing a list of device names - we would loop through // this list, calling NdisIMInitializeDeviceInstanceEx once for // each name in it. // NdisReadConfiguration(Status, &Param, ConfigHandle, &DeviceStr, NdisParameterString); if (*Status != NDIS_STATUS_SUCCESS) { break; } // // Allocate memory for the Adapter structure. This represents both the // protocol context as well as the adapter structure when the miniport // is initialized. // // In addition to the base structure, allocate space for the device // instance string. // TotalSize = sizeof(ADAPT) + Param->ParameterData.StringData.MaximumLength; NdisAllocateMemoryWithTag(&pAdapt, TotalSize, TAG); if (pAdapt == NULL) { *Status = NDIS_STATUS_RESOURCES; break; } // // Initialize the adapter structure. We copy in the IM device // name as well, because we may need to use it in a call to // NdisIMCancelInitializeDeviceInstance. The string returned // by NdisReadConfiguration is active (i.e. available) only // for the duration of this call to our BindAdapter handler. // NdisZeroMemory(pAdapt, TotalSize); pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength; pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length; pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(ADAPT)); NdisMoveMemory(pAdapt->DeviceName.Buffer, Param->ParameterData.StringData.Buffer, Param->ParameterData.StringData.MaximumLength); NdisInitializeEvent(&pAdapt->Event); // // Allocate a packet pool for sends. We need this to pass sends down. // We cannot use the same packet descriptor that came down to our send // handler (see also NDIS 5.1 packet stacking). // NdisAllocatePacketPoolEx(Status, &pAdapt->SendPacketPoolHandle, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, sizeof(SEND_RSVD)); if (*Status != NDIS_STATUS_SUCCESS) { break; } // // Allocate a packet pool for receives. We need this to indicate receives. // Same consideration as sends (see also NDIS 5.1 packet stacking). // NdisAllocatePacketPoolEx(Status, &pAdapt->RecvPacketPoolHandle, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET); if (*Status != NDIS_STATUS_SUCCESS) { break; } // // Now open the adapter below and complete the initialization // NdisOpenAdapter(Status, &Sts, &pAdapt->BindingHandle, &MediumIndex, MediumArray, sizeof(MediumArray)/sizeof(NDIS_MEDIUM), ProtHandle, pAdapt, DeviceName, 0, NULL); if (*Status == NDIS_STATUS_PENDING) { NdisWaitEvent(&pAdapt->Event, 0); *Status = pAdapt->Status; } if (*Status != NDIS_STATUS_SUCCESS) { break; } pAdapt->Medium = MediumArray[MediumIndex]; // // Now ask NDIS to initialize our miniport (upper) edge. // Set the flag below to synchronize with a possible call // to our protocol Unbind handler that may come in before // our miniport initialization happens. // pAdapt->MiniportInitPending = TRUE; NdisInitializeEvent(&pAdapt->MiniportInitEvent); *Status = NdisIMInitializeDeviceInstanceEx(DriverHandle, &pAdapt->DeviceName, pAdapt); if (*Status != NDIS_STATUS_SUCCESS) { DBGPRINT(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n", pAdapt, *Status)); break; } } while(FALSE); // // Close the configuration handle now - see comments above with // the call to NdisIMInitializeDeviceInstanceEx. // if (ConfigHandle != NULL) { NdisCloseConfiguration(ConfigHandle); } if (*Status != NDIS_STATUS_SUCCESS) { if (pAdapt != NULL) { if (pAdapt->BindingHandle != NULL) { NDIS_STATUS LocalStatus; // // Close the binding we opened above. // NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle); pAdapt->BindingHandle = NULL; if (LocalStatus == NDIS_STATUS_PENDING) { NdisWaitEvent(&pAdapt->Event, 0); LocalStatus = pAdapt->Status; } } if (pAdapt->SendPacketPoolHandle != NULL) { NdisFreePacketPool(pAdapt->SendPacketPoolHandle); } if (pAdapt->RecvPacketPoolHandle != NULL) { NdisFreePacketPool(pAdapt->RecvPacketPoolHandle); } NdisFreeMemory(pAdapt, sizeof(ADAPT), 0); pAdapt = NULL; } } DBGPRINT(("<== Protocol BindAdapter: pAdapt %p, Status %x\n", pAdapt, *Status)); }
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); }
PVOID ndisprotAuditAllocMem( PVOID pPointer, ULONG Size, ULONG FileNumber, ULONG LineNumber ) { PVOID pBuffer; PNPROTD_ALLOCATION pAllocInfo; if (!ndisprotdInitDone) { NdisAllocateSpinLock(&(ndisprotdMemoryLock)); ndisprotdInitDone = TRUE; } NdisAllocateMemoryWithTag( (PVOID *)&pAllocInfo, Size+sizeof(NPROTD_ALLOCATION), (ULONG)'oiuN' ); if (pAllocInfo == (PNPROTD_ALLOCATION)NULL) { DEBUGP(DL_VERY_LOUD+50, ("ndisprotAuditAllocMem: file %d, line %d, Size %d failed!\n", FileNumber, LineNumber, Size)); pBuffer = NULL; } else { pBuffer = (PVOID)&(pAllocInfo->UserData); NPROT_SET_MEM(pBuffer, 0xaf, Size); pAllocInfo->Signature = NPROTD_MEMORY_SIGNATURE; pAllocInfo->FileNumber = FileNumber; pAllocInfo->LineNumber = LineNumber; pAllocInfo->Size = Size; pAllocInfo->Location = (ULONG_PTR)pPointer; pAllocInfo->Next = (PNPROTD_ALLOCATION)NULL; NdisAcquireSpinLock(&(ndisprotdMemoryLock)); pAllocInfo->Prev = ndisprotdMemoryTail; if (ndisprotdMemoryTail == (PNPROTD_ALLOCATION)NULL) { // empty list ndisprotdMemoryHead = ndisprotdMemoryTail = pAllocInfo; } else { ndisprotdMemoryTail->Next = pAllocInfo; } ndisprotdMemoryTail = pAllocInfo; ndisprotdAllocCount++; NdisReleaseSpinLock(&(ndisprotdMemoryLock)); } DEBUGP(DL_VERY_LOUD+100, ("ndisprotAuditAllocMem: file %c%c%c%c, line %d, %d bytes, [0x%p] <- 0x%p\n", (CHAR)(FileNumber & 0xff), (CHAR)((FileNumber >> 8) & 0xff), (CHAR)((FileNumber >> 16) & 0xff), (CHAR)((FileNumber >> 24) & 0xff), LineNumber, Size, pPointer, pBuffer)); return (pBuffer); }
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); }
INT LpxProtocolReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ){ PDEVICE_CONTEXT deviceContext; PNDIS_BUFFER ndisFirstBuffer; PVOID firstBuffer; UINT firstBufferSize; UINT totalBufferSize; USHORT protocol; PNDIS_PACKET packet = NULL; NDIS_STATUS status; INT pktReferenceCount = 0; UINT addiLlcHeaderSize = 0; PLPX_HEADER lpxHeader; USHORT lpxHeaderSize; UINT lpxPayload; UINT rawDataOffset; DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") ); deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext; // // Check to see if the device context is initialized. // ASSERT( deviceContext->NdisBindingHandle ); if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) { DebugPrint( 4,("Device is not initialized. Drop packet\n") ); return 0; } // // validation // NdisGetFirstBufferFromPacket( Packet, &ndisFirstBuffer, &firstBuffer, &firstBufferSize, &totalBufferSize); if (firstBufferSize < ETHERNET_HEADER_LENGTH) { DebugPrint( 1, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) ); return 0; } protocol = ((PETHERNET_HEADER)firstBuffer)->Type; // // Discard 802.2 LLC SNAP field. // // if Ether Type less than 0x0600 ( 1536 ) // if (NTOHS(protocol) < 0x0600 && NTOHS(protocol) != 0x0060 && // LOOP: Ethernet Loopback NTOHS(protocol) != 0x0200 && // PUP : Xerox PUP packet NTOHS(protocol) != 0x0201) { // PUPAP: Xerox PUP address trans packet protocol = *(PUSHORT)((PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2); if(firstBufferSize >= LENGTH_8022LLCSNAP) firstBufferSize -= LENGTH_8022LLCSNAP; else { DebugPrint( 1, ("ProtocolReceivePacket: Too small first buffer\n") ); return 0; } if(totalBufferSize >= LENGTH_8022LLCSNAP) totalBufferSize -= LENGTH_8022LLCSNAP; else { DebugPrint( 1, ("ProtocolReceivePacket: Too small total buffer\n") ); return 0; } addiLlcHeaderSize = LENGTH_8022LLCSNAP; } if (protocol != HTONS(ETH_P_LPX)) { DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", protocol) ); return 0; } if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) { DebugPrint( 1, ("ProtocolReceivePacket: too small packet(1).\n")); return 0; } // // Extract LPX header information // // lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize); lpxHeaderSize = sizeof(LPX_HEADER); lpxPayload = NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize; #if __LPX_OPTION_ADDRESSS__ if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } #endif if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) { DebugPrint( 1, ("ProtocolReceivePacket: too small packet(2).\n")); return 0; } // // DROP PACKET for DEBUGGING!!!! // #if 1 //DBG // Enabled for testing if (PacketRxDropRate) { PacketRxCountForDrop++; if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) { PLPX_HEADER lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize); #if 0 if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) DebugPrint( 1, ("[Drop(%x,%x,%x))]\n", NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) ); #endif DebugPrint( 1, ("D\n") ); return 0; } } #endif ASSERT( addiLlcHeaderSize == 0 ); DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n", totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) ); // // If the miniport is out of resources, we can't queue // this packet - make a copy if this is so. // if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES) { UINT bytesCopied; DebugPrint( 1, ("ProtocolReceivePacket: Miniport reported low packet resources.\n")); status = RcvPacketAlloc( deviceContext, lpxPayload, &packet ); if (status == STATUS_SUCCESS) { ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); // // Copy lpx payload. payload contains only data. // NdisCopyFromPacketToPacket( packet, 0, lpxPayload, Packet, ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize, &bytesCopied); ASSERT(lpxPayload == bytesCopied); } rawDataOffset = 0; pktReferenceCount = 0; } else { PLPX_RESERVED externalReserved; // // No need to allocate new NDIS packet and copy data to the new NDIS packet. // But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context. // We should allocate our own. // packet = Packet; status = NdisAllocateMemoryWithTag(&externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED); if(status == NDIS_STATUS_SUCCESS) { RtlZeroMemory(externalReserved, sizeof(LPX_RESERVED)); // By setting the external reserved field, RESERVED() uses external reserved context automatically. ((PLPX_RESERVED)packet->ProtocolReserved)->ExternalReserved = externalReserved; // Initialize LPX reserved context instead of RcvPacketAlloc(). RESERVED(packet)->Cloned = 0; RESERVED(packet)->Type = LPX_PACKET_TYPE_RECEIVE; RESERVED(packet)->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT; // set data offset // Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data. rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize; lpxPayload += rawDataOffset; // return one reference count indicating LPX will call NdisReturnPackets() once. pktReferenceCount = 1; } } if (status != NDIS_STATUS_SUCCESS) { return 0; } // // Init LPX reserved context // LpxCopyEthLpxHeadersToLpxReserved(packet, firstBuffer, protocol, lpxHeader, lpxHeaderSize); RESERVED(Packet)->Packet = packet; RESERVED(Packet)->RecvTime = CurrentTime(); RESERVED(Packet)->PacketRawDataLength = lpxPayload; RESERVED(Packet)->PacketRawDataOffset = rawDataOffset; // // Queue to the device context. // ExInterlockedInsertTailList( &deviceContext->PacketInProgressList, &(RESERVED(Packet)->ListEntry), &deviceContext->PacketInProgressQSpinLock ); return pktReferenceCount; }
INT LpxProtocolReceivePacket ( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ) { PDEVICE_CONTEXT deviceContext; PLPX_RESERVED reserved = NULL; PNDIS_BUFFER ndisFirstBuffer; PVOID firstBuffer; UINT firstBufferSize; UINT totalBufferSize; PNDIS_PACKET packet = NULL; NDIS_STATUS status; INT pktReferenceCount = 0; UINT addiLlcHeaderSize = 0; PLPX_HEADER lpxHeader; USHORT lpxHeaderSize; UINT lpxPayload; UINT rawDataOffset; ETHERNET_HEADER ethernetHeader; DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") ); deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext; // Check to see if the device context is initialized. if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) { DebugPrint( 1, ("Device is not initialized. Drop packet\n") ); return NDIS_STATUS_NOT_RECOGNIZED; } NDAS_ASSERT( deviceContext->NdisBindingHandle ); // validation #ifndef NTDDI_VERSION NdisGetFirstBufferFromPacket( Packet, &ndisFirstBuffer, &firstBuffer, &firstBufferSize, &totalBufferSize ); #else firstBufferSize = 0; NdisGetFirstBufferFromPacketSafe( Packet, &ndisFirstBuffer, &firstBuffer, &firstBufferSize, &totalBufferSize, HighPagePriority ); #endif if (firstBufferSize < ETHERNET_HEADER_LENGTH) { NDAS_ASSERT(FALSE); DebugPrint( 2, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) ); return 0; } RtlCopyMemory( ðernetHeader, firstBuffer, ETHERNET_HEADER_LENGTH ); if (ethernetHeader.DestinationAddress[5] != 0xFF) { DebugPrint( 3, ("LpxProtocolReceivePacket: Type = %X\n", ethernetHeader.Type) ); } // Discard 802.2 LLC SNAP field. // // if Ether Type less than 0x0600 ( 1536 ) if (NTOHS(ethernetHeader.Type) < 0x0600 && NTOHS(ethernetHeader.Type) != 0x0060 && // LOOP: Ethernet Loopback NTOHS(ethernetHeader.Type) != 0x0200 && // PUP : Xerox PUP packet NTOHS(ethernetHeader.Type) != 0x0201) { // PUPAP: Xerox PUP address trans packet RtlCopyMemory( ðernetHeader, (PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2, ETHERNET_HEADER_LENGTH ); if (firstBufferSize >= LENGTH_8022LLCSNAP) { firstBufferSize -= LENGTH_8022LLCSNAP; } else { DebugPrint( 2, ("ProtocolReceivePacket: Too small first buffer\n") ); return 0; } if (totalBufferSize >= LENGTH_8022LLCSNAP) { totalBufferSize -= LENGTH_8022LLCSNAP; } else { DebugPrint( 2, ("ProtocolReceivePacket: Too small total buffer\n") ); return 0; } addiLlcHeaderSize = LENGTH_8022LLCSNAP; NDAS_ASSERT( ethernetHeader.Type != HTONS(ETH_P_LPX) ); } if (ethernetHeader.Type != HTONS(ETH_P_LPX)) { DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", ethernetHeader.Type) ); return 0; } if (totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) { DebugPrint( 2, ("ProtocolReceivePacket: too small packet(1).\n")); return 0; } // DROP PACKET for DEBUGGING!!!! if (PacketRxDropRate) { PacketRxCountForDrop++; if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) { PLPX_HEADER lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize); if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) { DebugPrint( 6, ("[Drop(%x,%x,%x))]\n", NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) ); } DebugPrint( 2, ("D\n") ); return 0; } } if (!(RtlEqualMemory(ethernetHeader.DestinationAddress, deviceContext->LocalAddress.Address, ETHERNET_ADDRESS_LENGTH) || RtlEqualMemory(ethernetHeader.DestinationAddress, LpxBroadcastAddress, ETHERNET_ADDRESS_LENGTH))) { DebugPrint( 4, ("LpxProtocolReceivePacket, %02x%02x%02x%02x%02x%02x\n", deviceContext->LocalAddress.Address[0], deviceContext->LocalAddress.Address[1], deviceContext->LocalAddress.Address[2], deviceContext->LocalAddress.Address[3], deviceContext->LocalAddress.Address[4], deviceContext->LocalAddress.Address[5]) ); DebugPrint( 4, ("LpxProtocolReceivePacket, %02x%02x%02x%02x%02x%02x\n", ethernetHeader.DestinationAddress[0], ethernetHeader.DestinationAddress[1], ethernetHeader.DestinationAddress[2], ethernetHeader.DestinationAddress[3], ethernetHeader.DestinationAddress[4], ethernetHeader.DestinationAddress[5]) ); return 0; } // Extract LPX header information lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize); lpxHeaderSize = sizeof(LPX_HEADER); lpxPayload = NTOHS((UINT16)(lpxHeader->PacketSize & ~LPX_TYPE_MASK)) - lpxHeaderSize; if (lpxHeader->DestinationPort == NTOHS(LPXRP_HIX_PORT)) { DebugPrint( 1, ("[LPX] LpxProtocolReceivePacket: DataGram packet arrived.\n") ); } #if __LPX_OPTION_ADDRESSS__ if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } #endif if (totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) { DebugPrint( 2, ("ProtocolReceivePacket: too small packet(2).\n") ); return 0; } NDAS_ASSERT( addiLlcHeaderSize == 0 ); DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n", totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) ); // If the miniport is out of resources, we can't queue // this packet - make a copy if this is so. NDAS_ASSERT( sizeof(ZeroProtocolReserved) == PROTOCOL_RESERVED_OFFSET ); if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES || !RtlEqualMemory(&Packet->ProtocolReserved[PROTOCOL_RESERVED_OFFSET], ZeroProtocolReserved, sizeof(ZeroProtocolReserved))) { UINT bytesCopied; INT i; for (i=0; i<16; i++) { DebugPrint( 1, ("Packet->ProtocolReserved[%d] = %d\n", i, Packet->ProtocolReserved[i]) ); } NDAS_ASSERT(FALSE); DebugPrint( 2, ("ProtocolReceivePacket: Miniport reported low packet resources.\n") ); status = RcvPacketAlloc( deviceContext, lpxPayload, &packet ); if (status == STATUS_SUCCESS) { NDAS_ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); // Copy lpx payload. payload contains only data. NdisCopyFromPacketToPacket( packet, 0, lpxPayload, Packet, ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize, &bytesCopied ); NDAS_ASSERT( lpxPayload == bytesCopied ); } rawDataOffset = 0; pktReferenceCount = 0; } else { PLPX_RESERVED externalReserved; // No need to allocate new NDIS packet and copy data to the new NDIS packet. // But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context. // We should allocate our own. packet = Packet; status = NdisAllocateMemoryWithTag( &externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED ); if (status == NDIS_STATUS_SUCCESS) { RtlZeroMemory( externalReserved, sizeof(LPX_RESERVED) ); // By setting the external reserved field, LpxGetReserved() uses external reserved context automatically. ((PLPX_RESERVED)(&packet->ProtocolReserved[PROTOCOL_RESERVED_OFFSET]))->ExternalReserved = externalReserved; reserved = LpxGetReserved(packet); // Initialize LPX reserved context instead of RcvPacketAlloc(). reserved->Cloned = 0; reserved->Type = LPX_PACKET_TYPE_RECEIVE; reserved->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT; // set data offset // Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data. rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize; lpxPayload += rawDataOffset; // return one reference count indicating LPX will call NdisReturnPackets() once. pktReferenceCount = 1; } } if (status != NDIS_STATUS_SUCCESS) { DebugPrint( 2, ("ProtocolReceivePacket: status != NDIS_STATUS_SUCCESS\n") ); return 0; } // Init LPX reserved context LpxCopyEthLpxHeadersToLpxReserved( packet, firstBuffer, ethernetHeader.Type, lpxHeader, lpxHeaderSize ); reserved = LpxGetReserved(packet); reserved->Packet = packet; reserved->RecvTime = NdasCurrentTime(); reserved->PacketRawDataLength = lpxPayload; reserved->PacketRawDataOffset = rawDataOffset; // Queue to the device context. ExInterlockedInsertTailList( &deviceContext->PacketInProgressList, &(reserved->ListEntry), &deviceContext->PacketInProgressQSpinLock ); return pktReferenceCount; }
// Called at <= DISPATCH_LEVEL static NDIS_STATUS XenNet_Init( OUT PNDIS_STATUS OpenErrorStatus, OUT PUINT SelectedMediumIndex, IN PNDIS_MEDIUM MediumArray, IN UINT MediumArraySize, IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_HANDLE WrapperConfigurationContext ) { NDIS_STATUS status; BOOLEAN medium_found = FALSE; struct xennet_info *xi = NULL; UINT nrl_length; PNDIS_RESOURCE_LIST nrl; PCM_PARTIAL_RESOURCE_DESCRIPTOR prd; KIRQL irq_level = 0; ULONG irq_vector = 0; ULONG irq_mode = 0; NDIS_HANDLE config_handle; NDIS_STRING config_param_name; PNDIS_CONFIGURATION_PARAMETER config_param; ULONG i; PUCHAR ptr; UCHAR type; PCHAR setting, value; ULONG length; //CHAR buf[128]; PVOID network_address; UINT network_address_length; BOOLEAN qemu_hide_filter = FALSE; ULONG qemu_hide_flags_value = 0; UNREFERENCED_PARAMETER(OpenErrorStatus); FUNCTION_ENTER(); KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql())); /* deal with medium stuff */ for (i = 0; i < MediumArraySize; i++) { if (MediumArray[i] == NdisMedium802_3) { medium_found = TRUE; break; } } if (!medium_found) { KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n")); return NDIS_STATUS_UNSUPPORTED_MEDIA; } *SelectedMediumIndex = i; /* Alloc memory for adapter private info */ status = NdisAllocateMemoryWithTag((PVOID)&xi, sizeof(*xi), XENNET_POOL_TAG); if (!NT_SUCCESS(status)) { KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status)); status = NDIS_STATUS_RESOURCES; goto err; } RtlZeroMemory(xi, sizeof(*xi)); xi->adapter_handle = MiniportAdapterHandle; xi->rx_target = RX_DFL_MIN_TARGET; xi->rx_min_target = RX_DFL_MIN_TARGET; xi->rx_max_target = RX_MAX_TARGET; xi->inactive = TRUE; NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi, 0, 0 /* the last zero is to give the next | something to | with */ #ifdef NDIS51_MINIPORT |NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS #endif |NDIS_ATTRIBUTE_DESERIALIZE |NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK, NdisInterfaceInternal); /* PnpBus option doesn't exist... */ xi->multicast_list_size = 0; xi->current_lookahead = MIN_LOOKAHEAD_LENGTH; nrl_length = 0; NdisMQueryAdapterResources(&status, WrapperConfigurationContext, NULL, (PUINT)&nrl_length); KdPrint((__DRIVER_NAME " nrl_length = %d\n", nrl_length)); status = NdisAllocateMemoryWithTag((PVOID)&nrl, nrl_length, XENNET_POOL_TAG); if (status != NDIS_STATUS_SUCCESS) { KdPrint((__DRIVER_NAME " Could not get allocate memory for Adapter Resources 0x%x\n", status)); return NDIS_STATUS_RESOURCES; } NdisMQueryAdapterResources(&status, WrapperConfigurationContext, nrl, (PUINT)&nrl_length); if (status != NDIS_STATUS_SUCCESS) { KdPrint((__DRIVER_NAME " Could not get Adapter Resources 0x%x\n", status)); return NDIS_STATUS_RESOURCES; } xi->event_channel = 0; xi->config_csum = 1; xi->config_csum_rx_check = 1; xi->config_sg = 1; xi->config_gso = 61440; xi->config_page = NULL; xi->config_rx_interrupt_moderation = 0; for (i = 0; i < nrl->Count; i++) { prd = &nrl->PartialDescriptors[i]; switch(prd->Type) { case CmResourceTypeInterrupt: irq_vector = prd->u.Interrupt.Vector; irq_level = (KIRQL)prd->u.Interrupt.Level; irq_mode = (prd->Flags & CM_RESOURCE_INTERRUPT_LATCHED)?NdisInterruptLatched:NdisInterruptLevelSensitive; KdPrint((__DRIVER_NAME " irq_vector = %03x, irq_level = %03x, irq_mode = %s\n", irq_vector, irq_level, (irq_mode == NdisInterruptLatched)?"NdisInterruptLatched":"NdisInterruptLevelSensitive")); break; case CmResourceTypeMemory: if (xi->config_page) { KdPrint(("More than one memory range\n")); return NDIS_STATUS_RESOURCES; } else { status = NdisMMapIoSpace(&xi->config_page, MiniportAdapterHandle, prd->u.Memory.Start, prd->u.Memory.Length); if (!NT_SUCCESS(status)) { KdPrint(("NdisMMapIoSpace failed with 0x%x\n", status)); NdisFreeMemory(nrl, nrl_length, 0); return NDIS_STATUS_RESOURCES; } } break; } } NdisFreeMemory(nrl, nrl_length, 0); if (!xi->config_page) { KdPrint(("No config page given\n")); return NDIS_STATUS_RESOURCES; } KeInitializeDpc(&xi->suspend_dpc, XenNet_SuspendResume, xi); KeInitializeSpinLock(&xi->resume_lock); KeInitializeDpc(&xi->rxtx_dpc, XenNet_RxTxDpc, xi); KeSetTargetProcessorDpc(&xi->rxtx_dpc, 0); KeSetImportanceDpc(&xi->rxtx_dpc, HighImportance); NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo, &xi->lower_do, NULL, NULL); xi->packet_filter = 0; status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription, NAME_SIZE, xi->dev_desc, &length); if (!NT_SUCCESS(status)) { KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status)); status = NDIS_STATUS_FAILURE; goto err; } ptr = xi->config_page; while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value)) != XEN_INIT_TYPE_END) { switch(type) { case XEN_INIT_TYPE_VECTORS: KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n")); if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) || ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC) { KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n", ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length)); FUNCTION_EXIT(); return NDIS_STATUS_FAILURE; } else memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS)); break; case XEN_INIT_TYPE_STATE_PTR: KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value))); xi->device_state = (PXENPCI_DEVICE_STATE)value; break; case XEN_INIT_TYPE_QEMU_HIDE_FLAGS: qemu_hide_flags_value = PtrToUlong(value); break; case XEN_INIT_TYPE_QEMU_HIDE_FILTER: qemu_hide_filter = TRUE; break; default: KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type)); break; } } if ((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) || qemu_hide_filter) xi->inactive = FALSE; xi->power_state = NdisDeviceStateD0; xi->power_workitem = IoAllocateWorkItem(xi->fdo); // now build config page NdisOpenConfiguration(&status, &config_handle, WrapperConfigurationContext); if (!NT_SUCCESS(status)) { KdPrint(("Could not open config in registry (%08x)\n", status)); status = NDIS_STATUS_RESOURCES; goto err; } NdisInitUnicodeString(&config_param_name, L"ScatterGather"); NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger); if (!NT_SUCCESS(status)) { KdPrint(("Could not read ScatterGather value (%08x)\n", status)); xi->config_sg = 1; } else { KdPrint(("ScatterGather = %d\n", config_param->ParameterData.IntegerData)); xi->config_sg = config_param->ParameterData.IntegerData; } NdisInitUnicodeString(&config_param_name, L"LargeSendOffload"); NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger); if (!NT_SUCCESS(status)) { KdPrint(("Could not read LargeSendOffload value (%08x)\n", status)); xi->config_gso = 0; } else { KdPrint(("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData)); xi->config_gso = config_param->ParameterData.IntegerData; if (xi->config_gso > 61440) { xi->config_gso = 61440; KdPrint(("(clipped to %d)\n", xi->config_gso)); } } NdisInitUnicodeString(&config_param_name, L"ChecksumOffload"); NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger); if (!NT_SUCCESS(status)) { KdPrint(("Could not read ChecksumOffload value (%08x)\n", status)); xi->config_csum = 1; } else { KdPrint(("ChecksumOffload = %d\n", config_param->ParameterData.IntegerData)); xi->config_csum = !!config_param->ParameterData.IntegerData; } NdisInitUnicodeString(&config_param_name, L"ChecksumOffloadRxCheck"); NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger); if (!NT_SUCCESS(status)) { KdPrint(("Could not read ChecksumOffloadRxCheck value (%08x)\n", status)); xi->config_csum_rx_check = 1; } else { KdPrint(("ChecksumOffloadRxCheck = %d\n", config_param->ParameterData.IntegerData)); xi->config_csum_rx_check = !!config_param->ParameterData.IntegerData; } NdisInitUnicodeString(&config_param_name, L"ChecksumOffloadDontFix"); NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger); if (!NT_SUCCESS(status)) { KdPrint(("Could not read ChecksumOffloadDontFix value (%08x)\n", status)); xi->config_csum_rx_dont_fix = 0; } else { KdPrint(("ChecksumOffloadDontFix = %d\n", config_param->ParameterData.IntegerData)); xi->config_csum_rx_dont_fix = !!config_param->ParameterData.IntegerData; } NdisInitUnicodeString(&config_param_name, L"MTU"); NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger); if (!NT_SUCCESS(status)) { KdPrint(("Could not read MTU value (%08x)\n", status)); xi->config_mtu = 1500; } else { KdPrint(("MTU = %d\n", config_param->ParameterData.IntegerData)); xi->config_mtu = config_param->ParameterData.IntegerData; } NdisInitUnicodeString(&config_param_name, L"RxInterruptModeration"); NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger); if (!NT_SUCCESS(status)) { KdPrint(("Could not read RxInterruptModeration value (%08x)\n", status)); xi->config_rx_interrupt_moderation = 1500; } else { KdPrint(("RxInterruptModeration = %d\n", config_param->ParameterData.IntegerData)); xi->config_rx_interrupt_moderation = config_param->ParameterData.IntegerData; } NdisReadNetworkAddress(&status, &network_address, &network_address_length, config_handle); if (!NT_SUCCESS(status) || network_address_length != ETH_ALEN || ((((PUCHAR)network_address)[0] & 0x03) != 0x02)) { KdPrint(("Could not read NetworkAddress value (%08x) or value is invalid\n", status)); memset(xi->curr_mac_addr, 0, ETH_ALEN); } else { memcpy(xi->curr_mac_addr, network_address, ETH_ALEN); KdPrint((" Set MAC address from registry to %02X:%02X:%02X:%02X:%02X:%02X\n", xi->curr_mac_addr[0], xi->curr_mac_addr[1], xi->curr_mac_addr[2], xi->curr_mac_addr[3], xi->curr_mac_addr[4], xi->curr_mac_addr[5])); } xi->config_max_pkt_size = max(xi->config_mtu + XN_HDR_SIZE, xi->config_gso + XN_HDR_SIZE); NdisCloseConfiguration(config_handle); status = XenNet_D0Entry(xi); if (!NT_SUCCESS(status)) { KdPrint(("Failed to go to D0 (%08x)\n", status)); goto err; } return NDIS_STATUS_SUCCESS; err: NdisFreeMemory(xi, 0, 0); *OpenErrorStatus = status; FUNCTION_EXIT_STATUS(status); return status; }
BOOLEAN GetUdpPortMapOut( IN USHORT original, IN BOOLEAN trans, OUT PUSHORT mapped ) /*++ Routine Description: Get the mapped id for the outflow UDP packet. Arguments: original - Original UDP source port in outflow packet. trans - TRUE for 4to6 mapping; FLASE for 6to6 mapping. mapped - Pointer to caller-supplied memory that holds the returned mapping port. Return Value: TRUE if find mapping is successful, mapped port is returned in 'mapped' pointer; FALSE if failed to find or create a mapping info, 'mapped' is set to 0 in this case. --*/ { USHORT ret = 0; SHORT remaining; LONG MaxPorts = 65536 / LocalPrefixInfo.Ratio; // Total port number is determined by ratio USHORT rover_j; USHORT rover_k; USHORT low; // lower bound of j USHORT high; // higher bound of j PUDP_MAP_CONTEXT Map = NULL; NDIS_STATUS Status; NdisAcquireSpinLock(&PortListLock); // Do NOT call RefreshUdpListEntrySafe() since we have already hold the spin lock. RefreshUdpListEntry(); if (UdpPortMapOutTable[original].Map != NULL) { Map = UdpPortMapOutTable[original].Map; if (Map->OriginalPort == original && Map->Translated == trans) // Found existing mapping info { ret = Map->MappedPort; NdisGetCurrentSystemTime(&(Map->MapSetTime)); // refresh timer DBGPRINT(("==> GetUdpPortMapOut: Find Map %d -> %d\n", Map->OriginalPort, Map->MappedPort)); } } if (ret == 0) // no existing map, generate new map { if (PortListLength >= MaxPorts) { NdisReleaseSpinLock(&PortListLock); DBGPRINT(("==> GetUdpPortMapOut: list full. Map id is used up.\n")); *mapped = 0; return FALSE; } if (LocalPrefixInfo.XlateMode == 1) // 1:N id mapping { low = (USHORT)(1024 / LocalPrefixInfo.Ratio / LocalPrefixInfo.Adjacent) + 1; high = (USHORT)(65536 / LocalPrefixInfo.Ratio / LocalPrefixInfo.Adjacent) - 1; remaining = (high - low) + 1; if (PortListLength != 0) { rover_j = (USHORT)(LastAllocatedUdpPort / LocalPrefixInfo.Ratio / LocalPrefixInfo.Adjacent); rover_k = (USHORT)(LastAllocatedUdpPort % LocalPrefixInfo.Adjacent) + 1; if (rover_k == LocalPrefixInfo.Adjacent) { rover_j++; rover_k = 0; } } else { // No port allocated before rover_j = low; rover_k = 0; } do { ret = (rover_j * LocalPrefixInfo.Ratio + LocalPrefixInfo.Offset) * LocalPrefixInfo.Adjacent + rover_k; if (UdpPortMapInTable[ret].Map == NULL) { // find idle ivi port break; } rover_k++; if (rover_k == LocalPrefixInfo.Adjacent) { rover_j++; remaining--; rover_k = 0; if (rover_j > high) { rover_j = low; } } } while (remaining > 0); if (remaining <= 0) { NdisReleaseSpinLock(&PortListLock); *mapped = 0; return FALSE; } } else { // 1:1 id mapping ret = original; } // Allocate map info memory Status = NdisAllocateMemoryWithTag((PVOID)&Map, sizeof(UDP_MAP_CONTEXT), TAG); if (Status != NDIS_STATUS_SUCCESS) { NdisReleaseSpinLock(&PortListLock); // No memory for map info. Fail this map. DBGPRINT(("==> GetUdpPortMapOut: NdisAllocateMemoryWithTag failed for port %d\n", original)); *mapped = 0; return FALSE; } NdisZeroMemory(Map, sizeof(UDP_MAP_CONTEXT)); // Routine to add new map-info Map->OriginalPort = original; Map->MappedPort = ret; Map->Translated = trans; NdisGetCurrentSystemTime(&(Map->MapSetTime)); // set timer for newly added mapping // Set hash table pointer UdpPortMapOutTable[Map->OriginalPort].Map = Map; UdpPortMapInTable[Map->MappedPort].Map = Map; // Linked list need not be sorted. Just insert new entry at tail. InsertTailList(&PortListHead, &(Map->ListEntry)); PortListLength++; LastAllocatedUdpPort = ret; DBGPRINT(("==> GetUdpPortMapOut: New map %d -> %d added, xlate=%d.\n", Map->OriginalPort, Map->MappedPort, Map->Translated)); } NdisReleaseSpinLock(&PortListLock); *mapped = ret; return TRUE; }
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; }
// //发送相关函数的实现、 // 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); }
VOID natpBindAdapter( OUT PNDIS_STATUS Status, IN NDIS_HANDLE BindContext, IN PNDIS_STRING DeviceName, IN PVOID SystemSpecific1, IN PVOID SystemSpecific2 ) { NDIS_HANDLE ConfigHandle = NULL; PNDIS_CONFIGURATION_PARAMETER Param; NDIS_STRING DeviceStr = UPPER_BINDINGS; PFILTER_ADAPTER pAdapt = NULL; NDIS_STATUS Sts; UINT MediumIndex, i; ULONG TotalSize; WCHAR DevicePrefix[] = L"\\Device\\"; UNREFERENCED_PARAMETER(BindContext); UNREFERENCED_PARAMETER(SystemSpecific2); __try{ NdisOpenProtocolConfiguration( Status, &ConfigHandle, SystemSpecific1 ); if (*Status != NDIS_STATUS_SUCCESS) __leave; NdisReadConfiguration( Status, &Param, ConfigHandle, &DeviceStr, NdisParameterString ); if (*Status != NDIS_STATUS_SUCCESS) __leave; TotalSize = sizeof(FILTER_ADAPTER) + Param->ParameterData.StringData.MaximumLength + DeviceName->MaximumLength; NdisAllocateMemoryWithTag(&pAdapt, TotalSize, NAT_TAG); if (NULL == pAdapt){ *Status = NDIS_STATUS_RESOURCES; __leave; } NdisZeroMemory(pAdapt, TotalSize); pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength; pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length; pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(FILTER_ADAPTER)); NdisMoveMemory( pAdapt->DeviceName.Buffer, Param->ParameterData.StringData.Buffer, Param->ParameterData.StringData.MaximumLength ); if(sizeof(DevicePrefix) >= DeviceName->Length){ }else{ pAdapt->RootDeviceName.MaximumLength = DeviceName->MaximumLength; pAdapt->RootDeviceName.Length = DeviceName->Length - sizeof(DevicePrefix) + sizeof(WCHAR); pAdapt->RootDeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(FILTER_ADAPTER) + Param->ParameterData.StringData.MaximumLength); NdisMoveMemory( pAdapt->RootDeviceName.Buffer, DeviceName->Buffer + sizeof(DevicePrefix)/sizeof(WCHAR) - 1, DeviceName->MaximumLength - sizeof(DevicePrefix)/sizeof(WCHAR) + 1 ); } NdisInitializeEvent(&pAdapt->Event); NdisAllocateSpinLock(&pAdapt->Lock); natInitControlBlock(&pAdapt->ctrl); NdisAllocatePacketPoolEx( Status, &pAdapt->SndPP1, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET ); if (*Status != NDIS_STATUS_SUCCESS) __leave; NdisAllocatePacketPoolEx( Status, &pAdapt->SndPP2, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET ); if (*Status != NDIS_STATUS_SUCCESS) __leave; NdisAllocateBufferPool( Status, &pAdapt->SndBP, MIN_PACKET_POOL_SIZE ); if ( *Status != NDIS_STATUS_SUCCESS ) __leave; NdisAllocatePacketPoolEx( Status, &pAdapt->RcvPP1, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET ); if (*Status != NDIS_STATUS_SUCCESS) __leave; NdisAllocatePacketPoolEx( Status, &pAdapt->RcvPP2, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET ); if (*Status != NDIS_STATUS_SUCCESS) __leave; NdisAllocateBufferPool( Status, &pAdapt->RcvBP, MIN_PACKET_POOL_SIZE ); if ( *Status != NDIS_STATUS_SUCCESS ) __leave; NdisOpenAdapter( Status, &Sts, &pAdapt->BindingHandle, &MediumIndex, MediumArray, sizeof(MediumArray)/sizeof(NDIS_MEDIUM), ProtHandle, pAdapt, DeviceName, 0,NULL ); if (*Status == NDIS_STATUS_PENDING){ NdisWaitEvent(&pAdapt->Event, 0); *Status = pAdapt->Status; } if (*Status != NDIS_STATUS_SUCCESS) __leave; pAdapt->Medium = MediumArray[MediumIndex]; pAdapt->MiniportInitPending = TRUE; NdisInitializeEvent(&pAdapt->MiniportInitEvent); *Status = NdisIMInitializeDeviceInstanceEx( DriverHandle, &pAdapt->DeviceName, pAdapt ); if (*Status != NDIS_STATUS_SUCCESS) __leave; StartQueryInfo( pAdapt ); } __finally{ } if (ConfigHandle != NULL) NdisCloseConfiguration(ConfigHandle); if(NDIS_STATUS_SUCCESS != *Status){ if (pAdapt != NULL){ if (pAdapt->BindingHandle != NULL){ NDIS_STATUS LocalStatus; NdisResetEvent(&pAdapt->Event); NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle); pAdapt->BindingHandle = NULL; if (LocalStatus == NDIS_STATUS_PENDING){ NdisWaitEvent(&pAdapt->Event, 0); LocalStatus = pAdapt->Status; } } natFreeAllItems(&pAdapt->ctrl); natFreeAllFwSessionsAndRules(&pAdapt->ctrl); for(i = 0;i<FLT_FW_SESSION_HASH_TBL_SZ;i++) NdisFreeSpinLock(pAdapt->ctrl.FwSessionLocks + i); NdisFreeSpinLock(&pAdapt->ctrl.IcmpRuleLock); NdisFreeSpinLock(&pAdapt->ctrl.UdpRuleLock); NdisFreeSpinLock(&pAdapt->ctrl.TcpRuleLock); natmFreeAllPacketPools(pAdapt); NdisFreeSpinLock(&pAdapt->Lock); NdisFreeMemory(pAdapt, 0, 0); pAdapt = NULL; } } }
NDIS_STATUS NTAPI MiniportInitialize ( OUT PNDIS_STATUS OpenErrorStatus, OUT PUINT SelectedMediumIndex, IN PNDIS_MEDIUM MediumArray, IN UINT MediumArraySize, IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_HANDLE WrapperConfigurationContext ) { PRTL_ADAPTER adapter; NDIS_STATUS status; UINT i; PNDIS_RESOURCE_LIST resourceList; UINT resourceListSize; // // Make sure the medium is supported // for (i = 0; i < MediumArraySize; i++) { if (MediumArray[i] == NdisMedium802_3) { *SelectedMediumIndex = i; break; } } if (i == MediumArraySize) { NDIS_DbgPrint(MIN_TRACE, ("802.3 medium was not found in the medium array\n")); return NDIS_STATUS_UNSUPPORTED_MEDIA; } // // Allocate our adapter context // status = NdisAllocateMemoryWithTag((PVOID*)&adapter, sizeof(*adapter), ADAPTER_TAG); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate adapter context\n")); return NDIS_STATUS_RESOURCES; } RtlZeroMemory(adapter, sizeof(*adapter)); adapter->MiniportAdapterHandle = MiniportAdapterHandle; NdisAllocateSpinLock(&adapter->Lock); // // Notify NDIS of some characteristics of our NIC // NdisMSetAttributesEx(MiniportAdapterHandle, adapter, 0, NDIS_ATTRIBUTE_BUS_MASTER, NdisInterfacePci); // // Get our resources for IRQ and IO base information // resourceList = NULL; resourceListSize = 0; NdisMQueryAdapterResources(&status, WrapperConfigurationContext, resourceList, &resourceListSize); if (status != NDIS_STATUS_RESOURCES) { NDIS_DbgPrint(MIN_TRACE, ("Unexpected failure of NdisMQueryAdapterResources #1\n")); status = NDIS_STATUS_FAILURE; goto Cleanup; } status = NdisAllocateMemoryWithTag((PVOID*)&resourceList, resourceListSize, RESOURCE_LIST_TAG); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate resource list\n")); goto Cleanup; } NdisMQueryAdapterResources(&status, WrapperConfigurationContext, resourceList, &resourceListSize); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Unexpected failure of NdisMQueryAdapterResources #2\n")); goto Cleanup; } ASSERT(resourceList->Version == 1); ASSERT(resourceList->Revision == 1); for (i = 0; i < resourceList->Count; i++) { switch (resourceList->PartialDescriptors[i].Type) { case CmResourceTypePort: ASSERT(adapter->IoRangeStart == 0); ASSERT(resourceList->PartialDescriptors[i].u.Port.Start.HighPart == 0); adapter->IoRangeStart = resourceList->PartialDescriptors[i].u.Port.Start.LowPart; adapter->IoRangeLength = resourceList->PartialDescriptors[i].u.Port.Length; NDIS_DbgPrint(MID_TRACE, ("I/O port range is %p to %p\n", adapter->IoRangeStart, adapter->IoRangeStart + adapter->IoRangeLength)); break; case CmResourceTypeInterrupt: ASSERT(adapter->InterruptVector == 0); ASSERT(adapter->InterruptLevel == 0); adapter->InterruptVector = resourceList->PartialDescriptors[i].u.Interrupt.Vector; adapter->InterruptLevel = resourceList->PartialDescriptors[i].u.Interrupt.Level; adapter->InterruptShared = (resourceList->PartialDescriptors[i].ShareDisposition == CmResourceShareShared); adapter->InterruptFlags = resourceList->PartialDescriptors[i].Flags; NDIS_DbgPrint(MID_TRACE, ("IRQ vector is %d\n", adapter->InterruptVector)); break; default: NDIS_DbgPrint(MIN_TRACE, ("Unrecognized resource type: 0x%x\n", resourceList->PartialDescriptors[i].Type)); break; } } NdisFreeMemory(resourceList, resourceListSize, 0); resourceList = NULL; if (adapter->IoRangeStart == 0 || adapter->InterruptVector == 0) { NDIS_DbgPrint(MIN_TRACE, ("Adapter didn't receive enough resources\n")); goto Cleanup; } // // Allocate the DMA resources // status = NdisMInitializeScatterGatherDma(MiniportAdapterHandle, FALSE, // RTL8139 only supports 32-bit addresses MAXIMUM_FRAME_SIZE); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Unable to configure DMA\n")); goto Cleanup; } adapter->ReceiveBufferLength = FULL_RECEIVE_BUFFER_SIZE; NdisMAllocateSharedMemory(MiniportAdapterHandle, adapter->ReceiveBufferLength, FALSE, (PVOID*)&adapter->ReceiveBuffer, &adapter->ReceiveBufferPa); if (adapter->ReceiveBuffer == NULL) { NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate receive buffer\n")); status = NDIS_STATUS_RESOURCES; goto Cleanup; } NdisMAllocateSharedMemory(MiniportAdapterHandle, MINIMUM_FRAME_SIZE * TX_DESC_COUNT, FALSE, (PVOID*)&adapter->RuntTxBuffers, &adapter->RuntTxBuffersPa); if (adapter->RuntTxBuffers == NULL) { NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate runt TX buffer\n")); status = NDIS_STATUS_RESOURCES; goto Cleanup; } // // Register the I/O port range and configure the NIC // status = NdisMRegisterIoPortRange((PVOID*)&adapter->IoBase, MiniportAdapterHandle, adapter->IoRangeStart, adapter->IoRangeLength); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Unable to register IO port range (0x%x)\n", status)); goto Cleanup; } // // Adapter setup // status = NICPowerOn(adapter); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Unable to power on NIC (0x%x)\n", status)); goto Cleanup; } status = NICSoftReset(adapter); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Unable to reset the NIC (0x%x)\n", status)); goto Cleanup; } status = NICGetPermanentMacAddress(adapter, adapter->PermanentMacAddress); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Unable to get the fixed MAC address (0x%x)\n", status)); goto Cleanup; } RtlCopyMemory(adapter->CurrentMacAddress, adapter->PermanentMacAddress, IEEE_802_ADDR_LENGTH); // // Update link state and speed // NICUpdateLinkStatus(adapter); status = NICRegisterReceiveBuffer(adapter); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Unable to setup receive buffer (0x%x)\n", status)); goto Cleanup; } // // We're ready to handle interrupts now // status = NdisMRegisterInterrupt(&adapter->Interrupt, MiniportAdapterHandle, adapter->InterruptVector, adapter->InterruptLevel, TRUE, // We always want ISR calls adapter->InterruptShared, (adapter->InterruptFlags & CM_RESOURCE_INTERRUPT_LATCHED) ? NdisInterruptLatched : NdisInterruptLevelSensitive); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Unable to register interrupt (0x%x)\n", status)); goto Cleanup; } adapter->InterruptRegistered = TRUE; // // Enable interrupts on the NIC // adapter->InterruptMask = DEFAULT_INTERRUPT_MASK; status = NICApplyInterruptMask(adapter); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Unable to apply interrupt mask (0x%x)\n", status)); goto Cleanup; } // // Turn on TX and RX now // status = NICEnableTxRx(adapter); if (status != NDIS_STATUS_SUCCESS) { NDIS_DbgPrint(MIN_TRACE, ("Unable to enable TX and RX (0x%x)\n", status)); goto Cleanup; } return NDIS_STATUS_SUCCESS; Cleanup: if (resourceList != NULL) { NdisFreeMemory(resourceList, resourceListSize, 0); } if (adapter != NULL) { MiniportHalt(adapter); } return status; }
/****************************************************************************** * * 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; }