static Boolean ssh_wan_alloc_buffer(SshInterceptor interceptor, SshUInt32 length, SshNetDataBuffer *buf_return, unsigned char **buf_addr_return) { SshCpuContext cpu_ctx; SshNetDataBuffer buffer; unsigned char *buf_addr; SshUInt32 buf_size; SSH_ASSERT(interceptor != NULL); SSH_ASSERT(buf_return != NULL); SSH_ASSERT(buf_addr_return != NULL); ssh_kernel_critical_section_start(&interceptor->packet_pool_cs); cpu_ctx = &interceptor->cpu_ctx[ssh_kernel_get_cpu()]; buffer = ssh_net_buffer_alloc(interceptor, &cpu_ctx->packet_pool); ssh_kernel_critical_section_end(&interceptor->packet_pool_cs); if (buffer == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Out of buffer pool!")); return FALSE; } SSH_RESET_BUFFER(buffer, 0); if (buffer->total_size < length) { ssh_wan_free_buffer(interceptor, buffer); SSH_DEBUG(SSH_D_FAIL, ("Could not allocate contiguous buffer (%u bytes " "requested)", length)); return FALSE; } NdisAdjustBufferLength(buffer->nb, length); buffer->data_len = length; if (!ssh_query_data_block(buffer->nb, &buf_addr, &buf_size)) { ssh_wan_free_buffer(interceptor, buffer); SSH_DEBUG(SSH_D_FAIL, ("Failed to query buffer address!")); return FALSE; } *buf_return = buffer; *buf_addr_return = buf_addr; return TRUE; }
// Process the received packet void NeoWrite(void *buf) { UINT num, i, size; void *packet_buf; // Validate arguments if (buf == NULL) { return; } // Number of packets num = NEO_NUM_PACKET(buf); if (num > NEO_MAX_PACKET_EXCHANGE) { // Number of packets is too many return; } if (num == 0) { // No packet return; } if (ctx->Halting != FALSE) { // Halting return; } if (ctx->Opened == FALSE) { // Not connected return; } for (i = 0;i < num;i++) { PACKET_BUFFER *p = ctx->PacketBuffer[i]; size = NEO_SIZE_OF_PACKET(buf, i); if (size > NEO_MAX_PACKET_SIZE) { size = NEO_MAX_PACKET_SIZE; } if (size < NEO_PACKET_HEADER_SIZE) { size = NEO_PACKET_HEADER_SIZE; } packet_buf = NEO_ADDR_OF_PACKET(buf, i); // Buffer copy NeoCopy(p->Buf, packet_buf, size); if (g_is_win8 == false) { // Adjust the buffer size NdisAdjustBufferLength(p->NdisBuffer, size); // Set the packet information NDIS_SET_PACKET_STATUS(p->NdisPacket, NDIS_STATUS_RESOURCES); NDIS_SET_PACKET_HEADER_SIZE(p->NdisPacket, NEO_PACKET_HEADER_SIZE); } else { NdisMEthIndicateReceive(ctx->NdisMiniport, ctx, p->Buf, NEO_PACKET_HEADER_SIZE, ((UCHAR *)p->Buf) + NEO_PACKET_HEADER_SIZE, size - NEO_PACKET_HEADER_SIZE, size - NEO_PACKET_HEADER_SIZE); NdisMEthIndicateReceiveComplete(ctx->NdisMiniport); } } // Notify that packets have received ctx->Status.NumPacketRecv += num; if (g_is_win8 == false) { NdisMIndicateReceivePacket(ctx->NdisMiniport, ctx->PacketBufferArray, num); } }
VOID NICIndicateReceivedPacket( IN PRCB pRCB, IN ULONG dataoffset, IN ULONG BytesToIndicate, IN ULONG PacketNum ) /*++ Routine Description: Initialize the packet to describe the received data and indicate to NDIS. Arguments: pRCB - pointer to the RCB block BytesToIndicate - number of bytes to indicate Return value: VOID --*/ { ULONG PacketLength; PNDIS_BUFFER CurrentBuffer = NULL; PETH_HEADER pEthHeader = NULL; PMP_ADAPTER Adapter = pRCB->Adapter; KIRQL oldIrql; PVOID VirtualAddress=NULL; ASSERT( PacketNum < RCB_BUFFERARRAY_SIZE); ASSERT((dataoffset+BytesToIndicate) < pRCB->ulBufferSize); //NdisAdjustBufferLength(pRCB->Buffer, BytesToIndicate); //MmInitializeMdl(pRCB->BufferArray[PacketNum],pRCB->pDataForNTB+dataoffset,BytesToIndicate); VirtualAddress=MmGetMdlVirtualAddress(pRCB->BufferArray[PacketNum]); ASSERT(VirtualAddress!=NULL); NdisMoveMemory(VirtualAddress,pRCB->pDataForNTB+dataoffset,BytesToIndicate); NdisAdjustBufferLength(pRCB->BufferArray[PacketNum], BytesToIndicate); //NdisMoveMemory(pRCB->pDataForNet+NIC_BUFFER_SIZE*PacketNum,pRCB->pDataForNTB+dataoffset,BytesToIndicate); // // Prepare the recv packet // NdisReinitializePacket(pRCB->PacketArray[PacketNum]); *((PRCB *)pRCB->PacketArray[PacketNum]->MiniportReserved) = pRCB; // // Chain the TCB buffers to the packet // NdisChainBufferAtBack(pRCB->PacketArray[PacketNum], pRCB->BufferArray[PacketNum]); NdisQueryPacket(pRCB->PacketArray[PacketNum], NULL, NULL, &CurrentBuffer, (PUINT) &PacketLength); ASSERT(CurrentBuffer == pRCB->BufferArray[PacketNum]); pEthHeader = (PETH_HEADER)(pRCB->pDataForNTB+dataoffset); if(PacketLength >= sizeof(ETH_HEADER) && Adapter->PacketFilter && NICIsPacketAcceptable(Adapter, pEthHeader->DstAddr)){ DEBUGP(MP_LOUD, ("Src Address = %02x-%02x-%02x-%02x-%02x-%02x", pEthHeader->SrcAddr[0], pEthHeader->SrcAddr[1], pEthHeader->SrcAddr[2], pEthHeader->SrcAddr[3], pEthHeader->SrcAddr[4], pEthHeader->SrcAddr[5])); DEBUGP(MP_LOUD, (" Dest Address = %02x-%02x-%02x-%02x-%02x-%02x\n", pEthHeader->DstAddr[0], pEthHeader->DstAddr[1], pEthHeader->DstAddr[2], pEthHeader->DstAddr[3], pEthHeader->DstAddr[4], pEthHeader->DstAddr[5])); DEBUGP(MP_LOUD, ("Indicating packet = %p, Packet Length = %d\n", pRCB->PacketArray[PacketNum], PacketLength)); NdisInterlockedIncrement(&pRCB->Ref); NDIS_SET_PACKET_STATUS(pRCB->PacketArray[PacketNum], NDIS_STATUS_SUCCESS); Adapter->nPacketsIndicated++; // // NDIS expects the indication to happen at DISPATCH_LEVEL if the // device is assinged any I/O resources in the IRP_MN_START_DEVICE_IRP. // Since this sample is flexible enough to be used as a standalone // virtual miniport talking to another device or part of a WDM stack for // devices consuming hw resources such as ISA, PCI, PCMCIA. I have to // do the following check. You should avoid raising the IRQL, if you // know for sure that your device wouldn't have any I/O resources. This // would be the case if your driver is talking to USB, 1394, etc. // if(Adapter->IsHardwareDevice){ KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); NdisMIndicateReceivePacket(Adapter->AdapterHandle, &pRCB->PacketArray[PacketNum], 1); KeLowerIrql(oldIrql); }else{ NdisMIndicateReceivePacket(Adapter->AdapterHandle, &pRCB->PacketArray[PacketNum], 1); } }else { DEBUGP(MP_VERY_LOUD, ("Invalid packet or filter is not set packet = %p,Packet Length = %d\n", pRCB->PacketArray, PacketLength)); } }
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; }