/*----------------------------------------------------------------------------*/ 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; }
/*------------------------------------------------------------------------- ssh_driver_transfer_data() Copies received network data to a given upper layer supplied NDIS packet. Arguments: pkt - NDIS packet for data bytes_transferred - how many bytes has been written into the packet miniport_context - virtual NIC object receive_context - ??? byte_offset - where to start copy operation bytes_to_transfer - how may bytes to copy Returns: NDIS_STATUS_FAILURE - always Notes: This function is not supported because we always indicate complete NDIS packets to the upper layer. So upper layer should never call this function but we anyway return the FAILURE status code to upper layer. Default IRQL: DISPATCH_LEVEL -------------------------------------------------------------------------*/ static NDIS_STATUS ssh_driver_transfer_data(PNDIS_PACKET pkt, PUINT bytes_transferred, NDIS_HANDLE miniport_context, NDIS_HANDLE receive_context, UINT byte_offset, UINT bytes_to_transfer) { SshNdisIMAdapter adapter = (SshNdisIMAdapter)miniport_context; SSH_ASSERT(SSH_GET_IRQL() <= SSH_DISPATCH_LEVEL); SSH_ASSERT(miniport_context != NULL); SSH_ASSERT(receive_context != NULL); SSH_ASSERT(pkt != NULL); SSH_ASSERT(bytes_transferred != NULL); *bytes_transferred = 0; SSH_DEBUG(SSH_D_ERROR, ("Adapter %@: Unexpected MiniportTransferData() call.", ssh_adapter_id_st_render, adapter)); NDIS_SET_PACKET_STATUS(pkt, NDIS_STATUS_FAILURE); return (NDIS_STATUS_FAILURE); }
/* NicIndicateRecvPackets indicate received packet (MAC frame) to NDIS (then protocol stack) Parameters: pAdapter : pointer to adapter object created by miniport driver. ppNBSPackets : pointer to an NDIS packet to be indicated up. Return: Note: History: Created by yichen, 1/Apr/2009 IRQL: PASSIVE_LEVEL */ VOID NicIndicateRecvPackets(IN PMP_ADAPTER pAdapter,IN PPNDIS_PACKETS_OR_NBL ppNBSPackets) { NDIS_SET_PACKET_HEADER_SIZE(*ppNBSPackets, ETH_HEADER_SIZE); NDIS_SET_PACKET_STATUS(*ppNBSPackets, NDIS_STATUS_SUCCESS); NdisMIndicateReceivePacket(pAdapter->AdapterHandle, ppNBSPackets, 1); //only 1 packet indicated InterlockedIncrement64(&pAdapter->ullGoodReceives); }
void CleanQueuedSendPacket(PHWT_ADAPTER Adapter) { KIRQL irql; KeAcquireSpinLock(&Adapter->UExtKeObj.SendPacketLock, &irql); if (Adapter->UExtKeObj.SendPacketControl) { ObDereferenceObject(Adapter->UExtKeObj.SendPacketControl); Adapter->UExtKeObj.SendPacketControl = NULL; } while(1) { PNDIS_PACKET Packet; if (remove_thread_safe_enlist_head(Adapter->UExtKeObj.SendPacketList, &Packet, 1)) { NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_FAILURE); NdisMSendComplete(Adapter->AdapterHandle, Packet, NDIS_STATUS_FAILURE); continue; } break; } KeReleaseSpinLock(&Adapter->UExtKeObj.SendPacketLock, irql); }
// Stop check of packet transmission BOOL NeoNdisSendPacketsHaltCheck(NDIS_PACKET **PacketArray, UINT NumberOfPackets) { UINT i; if (ctx == NULL) { return FALSE; } if (ctx->Halting != FALSE || ctx->Opened == FALSE) { // Finishing for (i = 0;i < NumberOfPackets;i++) { NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_FAILURE); if (g_is_win8) { NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_SUCCESS); } ctx->Status.NumPacketSendError++; } return FALSE; } return TRUE; }
NTSTATUS MPGetSendPacket(PHWT_ADAPTER Adapter, PVOID Input, ULONG InputSize, PVOID Output, ULONG OutputSize, PIRP Irp) { PGET_SEND_PACKET_OUT get_send_packet_out; PNDIS_PACKET Packet; get_send_packet_out = (PGET_SEND_PACKET_OUT)Output; if (remove_thread_safe_enlist_head(Adapter->UExtKeObj.SendPacketList, &Packet, 1)) { struct Send_Packet_Data* packet_data; packet_data = Packet2PacketData(Packet); if (packet_data) { get_send_packet_out->hResult = ERROR_SUCCESS; get_send_packet_out->Packet = (PACKET_HANDLE)packet_data; get_send_packet_out->Addr= packet_data->m_addr; get_send_packet_out->Size = packet_data->m_len; return STATUS_SUCCESS; } else { NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_FAILURE); NdisMSendComplete(Adapter->AdapterHandle, Packet, NDIS_STATUS_FAILURE); } } get_send_packet_out->hResult = ERROR_RESOURCE_FAILED; get_send_packet_out->Packet = 0; get_send_packet_out->Addr= NULL; get_send_packet_out->Size = 0; return STATUS_SUCCESS; }
VOID NicCompletePacket(IN PMP_ADAPTER Adapter, IN PNDIS_PACKET_OR_NBL pNBSPacket) { NDIS_SET_PACKET_STATUS(pNBSPacket,NDIS_STATUS_SUCCESS); NdisMSendComplete(Adapter->AdapterHandle, pNBSPacket, NDIS_STATUS_SUCCESS); InterlockedIncrement64(&Adapter->ullGoodTransmits); }
VOID NicDropPacket(IN PMP_ADAPTER Adapter, IN PNDIS_PACKET_OR_NBL pNBSPacket) { NDIS_SET_PACKET_STATUS(pNBSPacket,NDIS_STATUS_FAILURE); NdisMSendComplete(Adapter->AdapterHandle, pNBSPacket, NDIS_STATUS_FAILURE); InterlockedIncrement64(&Adapter->ullTransmitFail); }
VOID MPSendPackets( IN NDIS_HANDLE MiniportAdapterContext, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets) { PHWT_ADAPTER Adapter; KIRQL irql; UINT Index; Adapter = (PHWT_ADAPTER)MiniportAdapterContext; KeAcquireSpinLock(&Adapter->UExtKeObj.SendPacketLock, &irql); if (Adapter->UExtKeObj.SendPacketControl) { for(Index=0; Index < NumberOfPackets; Index++) { if (get_thread_safe_enlist_count(Adapter->UExtKeObj.SendPacketList) >= MAX_QUEUED_SEND_PACKET) { NDIS_SET_PACKET_STATUS(PacketArray[Index], NDIS_STATUS_FAILURE); NdisMSendComplete(Adapter->AdapterHandle, PacketArray[Index], NDIS_STATUS_FAILURE); continue; } insert_thread_safe_enlist_tail(Adapter->UExtKeObj.SendPacketList, PacketArray[Index], 1); KeReleaseSemaphore(Adapter->UExtKeObj.SendPacketControl, IO_NO_INCREMENT, 1, FALSE); } } else { for(Index=0; Index < NumberOfPackets; Index++) { NDIS_SET_PACKET_STATUS(PacketArray[Index], NDIS_STATUS_FAILURE); NdisMSendComplete(Adapter->AdapterHandle, PacketArray[Index], NDIS_STATUS_FAILURE); } } KeReleaseSpinLock(&Adapter->UExtKeObj.SendPacketLock, irql); return; }
NTSTATUS MPIndicatePacket(PHWT_ADAPTER Adapter, PVOID Input, ULONG InputSize, PDEV_RET Output, ULONG OutputSize, PIRP Irp) { PVOID data = NULL; NDIS_STATUS ndis_status = NDIS_STATUS_FAILURE; PNDIS_BUFFER ndis_buffer = NULL; PNDIS_PACKET ndis_packet = NULL; do { data = ExAllocatePoolWithTag(NonPagedPool, InputSize, 'tkpi'); RtlCopyMemory(data, Input, InputSize); NdisAllocateBuffer(&ndis_status, &ndis_buffer, Adapter->AllocateBufferPool, data, InputSize); if (ndis_status != NDIS_STATUS_SUCCESS) break; NdisAllocatePacket(&ndis_status, &ndis_packet, Adapter->AllocatePacketPool); if (ndis_status != NDIS_STATUS_SUCCESS) break; NdisReinitializePacket(ndis_packet); *(PVOID*)ndis_packet->MiniportReserved = data; NdisChainBufferAtBack(ndis_packet, ndis_buffer); NDIS_SET_PACKET_HEADER_SIZE(ndis_packet, sizeof(ETHERNET_HEADER)); NDIS_SET_PACKET_STATUS(ndis_packet, NDIS_STATUS_SUCCESS); NdisMIndicateReceivePacket(Adapter->AdapterHandle, &ndis_packet, 1); Output->hResult = S_OK; ndis_status = NDIS_STATUS_SUCCESS; } while(FALSE); if (ndis_status != NDIS_STATUS_SUCCESS && ndis_status != STATUS_PENDING) { if (ndis_packet) NdisFreePacket(ndis_packet); if (ndis_buffer) NdisFreeBuffer(ndis_buffer); if (data) ExFreePoolWithTag(data, 'tkpi'); } return ndis_status; }
NTSTATUS MPCompleteSendPacket(PHWT_ADAPTER Adapter, PVOID Input, ULONG InputSize, PDEV_RET Output, ULONG OutputSize, PIRP Irp) { PCOMPLETE_SEND_PACKET_IN complete_send_packet_in; struct Send_Packet_Data* packet_data; complete_send_packet_in = (PCOMPLETE_SEND_PACKET_IN)Input; packet_data = (struct Send_Packet_Data*)complete_send_packet_in->Packet; NDIS_SET_PACKET_STATUS(packet_data->m_ndis_packet, complete_send_packet_in->hResult); NdisMSendComplete(Adapter->AdapterHandle, packet_data->m_ndis_packet, complete_send_packet_in->hResult); free_send_packet_data(packet_data); Output->hResult = ERROR_SUCCESS; return STATUS_SUCCESS; }
/* ======================================================================== Routine Description: Early checking and OS-depened parsing for Tx packet to AP device. Arguments: NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd. PPNDIS_PACKET ppPacketArray The packet array need to do transmission. UINT NumberOfPackets Number of packet in packet array. Return Value: NONE Note: This function do early checking and classification for send-out packet. You only can put OS-depened & AP related code in here. ======================================================================== */ VOID wdev_tx_pkts(NDIS_HANDLE dev_hnd, PPNDIS_PACKET pkt_list, UINT pkt_cnt, struct wifi_dev *wdev) { RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)dev_hnd; PNDIS_PACKET pPacket; BOOLEAN allowToSend; UCHAR wcid = MCAST_WCID; UINT Index; for (Index = 0; Index < pkt_cnt; Index++) { pPacket = pkt_list[Index]; if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))) { /* Drop send request since hardware is in reset state */ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); continue; } if ((wdev->allow_data_tx == TRUE) && (wdev->tx_pkt_allowed)) allowToSend = wdev->tx_pkt_allowed(pAd, wdev, pPacket, &wcid); else allowToSend = FALSE; if (allowToSend == TRUE) { RTMP_SET_PACKET_WCID(pPacket, wcid); RTMP_SET_PACKET_WDEV(pPacket, wdev->wdev_idx); NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING); pAd->RalinkCounters.PendingNdisPacketCount++; #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { #ifdef DELAYED_TCP_ACK if(!delay_tcp_ack(pAd, wcid, pPacket)) #endif /* DELAYED_TCP_ACK */ APSendPacket(pAd, pPacket); } #endif /* CONFIG_AP_SUPPORT */ } else {
/* ************************************************************************* * SendPacketsHandler ************************************************************************* * * Send an array of packets simultaneously. * */ VOID SendPacketsHandler(NDIS_HANDLE MiniportAdapterContext, PPNDIS_PACKET PacketArray, UINT NumberofPackets) { NDIS_STATUS stat; UINT i; DBGOUT(("==> SendPacketsHandler(0x%x)", (UINT)MiniportAdapterContext)); /* * This is a great opportunity to be lazy. * Just call MiniportSend with each packet in sequence and * set the result in the packet array object. */ for (i = 0; i < NumberofPackets; i++){ stat = MiniportSend(MiniportAdapterContext, PacketArray[i], 0); NDIS_SET_PACKET_STATUS(PacketArray[i], stat); } DBGOUT(("<== SendPacketsHandler")); }
//wireshark这个模块就不自己建线程了,就直接用系统的workitem就好了 VOID WSWorkThread(PDEVICE_OBJECT DeviceObject, PVOID pContext) { NTSTATUS status=STATUS_SUCCESS; ULONG pHeaderBuffer, HeaderBufferSize, pLookaheadBuffer,LookaheadBufferSize,PacketSize; PWorkItemContext pWIC =NULL; PNDIS_PACKET pPacket =NULL; ULONG ProtocolBindingContext=0; PNDIS_COMMON_OPEN_BLOCK_2k3_early OpenQueue=NULL; KIRQL CIrql,CIrql2; CIrql=CIrql2=0; CIrql = KeGetCurrentIrql(); pWIC =(PWorkItemContext)pContext; do { if (pWIC==NULL) { break; } if (OpenQueue = g_pNpfProtocolBlock->OpenQueue) { ProtocolBindingContext = (ULONG)OpenQueue->ProtocolBindingContext; } else { break; } //Receive Packet Handler Available if (g_NPFReceivePacketHandler) { pPacket = MakePacketByMem(pWIC->pBuffer, pWIC->uBufferLen); if (pPacket==NULL) { break; } NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_RESOURCES); __asm { //提上去给wireshark push pPacket push ProtocolBindingContext call NewNPFReceivePacketHandler } } else//f**k { pHeaderBuffer = (ULONG)pWIC->pBuffer; HeaderBufferSize = sizeof(Dlc_Header); pLookaheadBuffer = pHeaderBuffer+HeaderBufferSize; LookaheadBufferSize = PacketSize = pWIC->uBufferLen-HeaderBufferSize; _asm { push PacketSize push LookaheadBufferSize push pLookaheadBuffer push HeaderBufferSize push pHeaderBuffer push 0 //mac context,用不上 push ProtocolBindingContext mov eax, NewNPFReceiveHandler call eax } } } while (0);
INT PtReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ) /*++ Routine Description: ReceivePacket handler. Called by NDIS if the miniport below supports NDIS 4.0 style receives. Re-package the buffer chain in a new packet and indicate the new packet to protocols above us. Any context for packets indicated up must be kept in the MiniportReserved field. NDIS 5.1 - packet stacking - if there is sufficient "stack space" in the packet passed to us, we can use the same packet in a receive indication. Arguments: ProtocolBindingContext - Pointer to our adapter structure. Packet - Pointer to the packet Return Value: == 0 -> We are done with the packet != 0 -> We will keep the packet and call NdisReturnPackets() this many times when done. --*/ { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; NDIS_STATUS Status; PNDIS_PACKET MyPacket; BOOLEAN Remaining; //------------------------------WestChamber--------------------------------- BOOLEAN result=WestChamberReceiverMain(Packet,pAdapt); if(result==FALSE) { //Simply drop the packet. //return NDIS_STATUS_NOT_ACCEPTED; return 0; //Thanks to Albert Jin. } //------------------------------WestChamber--------------------------------- // // Drop the packet silently if the upper miniport edge isn't initialized // if (!pAdapt->MiniportHandle) { return 0; } #ifdef NDIS51 // // Check if we can reuse the same packet for indicating up. // See also: PtReceive(). // (VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining); if (Remaining) { // // We can reuse "Packet". Indicate it up and be done with it. // Status = NDIS_GET_PACKET_STATUS(Packet); NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1); return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0); } #endif // NDIS51 // // Get a packet off the pool and indicate that up // NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { PRECV_RSVD RecvRsvd; RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved); RecvRsvd->OriginalPkt = Packet; MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; // // Get the original packet (it could be the same packet as the one // received or a different one based on the number of layered miniports // below) and set it on the indicated packet so the OOB data is visible // correctly to protocols above us. // NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); // // Set Packet Flags // 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)); NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1); // // Check if we had indicated up the packet with NDIS_STATUS_RESOURCES // NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since // it might have changed! Use the value saved in the local variable. // if (Status == NDIS_STATUS_RESOURCES) { // // Our ReturnPackets handler will not be called for this packet. // We should reclaim it right here. // NdisDprFreePacket(MyPacket); } return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0); } else { // // We are out of packets. Silently drop it. // return(0); } }
static VOID ssh_driver_send_packets(NDIS_HANDLE miniport_context, PPNDIS_PACKET packet_array, UINT packet_cnt) { UINT i; SshNdisIMAdapter adapter = (SshNdisIMAdapter)miniport_context; PNDIS_PACKET pkt; SSH_ASSERT(SSH_GET_IRQL() <= SSH_DISPATCH_LEVEL); SSH_ASSERT(adapter != NULL); SSH_ASSERT(packet_cnt > 0); SSH_ASSERT(packet_array != NULL); SSH_DEBUG(SSH_D_LOWSTART, ("Adapter %@ MiniportSendPackets: packet count = %u", ssh_adapter_id_st_render, adapter, packet_cnt)); if (!IsListEmpty(&adapter->send_wait_queue)) { SshNdisIMInterceptor interceptor; buffer_packets: interceptor = (SshNdisIMInterceptor)adapter->interceptor; NdisAcquireSpinLock(&adapter->send_wait_queue_lock); for (i = 0; i < packet_cnt; i++) { pkt = packet_array[i]; SSH_DEBUG(SSH_D_LOWSTART, ("Adapter %@ MiniportSendPackets: " "queuing NDIS packet 0x%p", ssh_adapter_id_st_render, adapter, pkt)); /* Mark packet pending */ NDIS_SET_PACKET_STATUS(pkt, NDIS_STATUS_PENDING); /* Queue this packet. */ InsertTailList(&adapter->send_wait_queue, (PLIST_ENTRY)&(pkt->MiniportReserved[0])); } NdisReleaseSpinLock(&adapter->send_wait_queue_lock); InterlockedExchangeAdd(&interceptor->delayed_sends, packet_cnt); return; } /* Loop through the packet array */ for (i = 0; i < packet_cnt; i++) { pkt = packet_array[i]; /* Check if we are ready to process the packet */ if (ssh_adapter_is_enabled(adapter) == FALSE) { NDIS_STATUS status; SSH_DEBUG(SSH_D_LOWSTART, ("Adapter %@ MiniportSendPackets: adapter not enabled", ssh_adapter_id_st_render, adapter)); /* Complete the send operation immediately with error code */ status = NDIS_STATUS_FAILURE; NDIS_SET_PACKET_STATUS(pkt, status); NdisMSendComplete(adapter->handle, pkt, status); continue; } /* Handling of previous packet was successful so continue */ if (!ssh_driver_copy_and_send(adapter, pkt)) { SSH_DEBUG(SSH_D_LOWSTART, ("Adapter %@ MiniportSendPackets: " "can't send packet to engine", ssh_adapter_id_st_render, adapter)); /* We have run out of packet descriptors of buffers; let's queue rest of the packets */ packet_array = &packet_array[i]; packet_cnt -= i; goto buffer_packets; } SSH_DEBUG(SSH_D_LOWSTART, ("Adapter %@ MiniportSendPackets: " "sent packet to engine", ssh_adapter_id_st_render, adapter)); } }
/*-------------------------------------------------------------------------- ssh_interceptor_send() Sends packet either down to the network or up to the protocol. --------------------------------------------------------------------------*/ void ssh_interceptor_send(SshInterceptor interceptor, SshInterceptorPacket ip, size_t media_header_len) { SshNdisPacket packet; ULONG first_buf_len = SSH_ETHERH_HDRLEN; SshNdisIMAdapter adapter; SshCpuContext cpu_ctx; Boolean use_one_buffer = FALSE; ULONG new_value; /* Sanity checks for arguments */ SSH_ASSERT(interceptor != NULL); SSH_ASSERT(ip != NULL); SSH_ASSERT((ip->flags & SSH_PACKET_FROMADAPTER) != (ip->flags & SSH_PACKET_FROMPROTOCOL)); #ifndef _WIN32_WCE SSH_ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); #endif /* _WIN32_WCE */ cpu_ctx = &interceptor->cpu_ctx[ssh_kernel_get_cpu()]; packet = CONTAINING_RECORD(ip, SshNdisPacketStruct, ip); #ifdef DEBUG_LIGHT packet->f.flags.in_engine = 0; #endif /* DEBUG_LIGHT */ adapter = (SshNdisIMAdapter)packet->adapter_in; /* Check if adapter where the packet should be sent is different where the packet originated from */ if (adapter && (adapter->ifnum == ip->ifnum_out)) { new_value = InterlockedIncrement(&adapter->ref_count); packet->adapter_out = (SshAdapter)adapter; } else { SshAdapter gen_adapter = NULL; if (ip->ifnum_out < SSH_INTERCEPTOR_MAX_ADAPTERS) { ssh_kernel_rw_mutex_lock_read(&interceptor->adapter_lock); gen_adapter = interceptor->adapter_table[ip->ifnum_out]; if (gen_adapter) { new_value = InterlockedIncrement(&gen_adapter->ref_count); packet->adapter_out = gen_adapter; } ssh_kernel_rw_mutex_unlock_read(&interceptor->adapter_lock); } if (gen_adapter == NULL) goto free_packet; adapter = (SshNdisIMAdapter)gen_adapter; } SSH_ASSERT(new_value > 0); /* Check that active adapter found and it supports the protocol */ if (!ssh_adapter_is_enabled((SshNdisIMAdapter)adapter)) { SSH_DEBUG(SSH_D_FAIL, ("active network connection not found")); goto free_packet; } #ifndef _WIN32_WCE /* Check if packet is plain IPv4 (IPv6) and then add ethernet framing */ if (ip->protocol == SSH_PROTOCOL_IP4 || ip->protocol == SSH_PROTOCOL_IP6) { if (!ssh_wan_packet_encapsulate((SshAdapter)adapter, ip)) { SSH_DEBUG(SSH_D_FAIL, ("packet framing failed")); goto free_packet; } /* Some dial-up drivers seem to expect to receive whole packet in one NDIS buffer. */ if (ip->flags & SSH_PACKET_FROMADAPTER) use_one_buffer = TRUE; } #endif /* _WIN32_WCE */ /* Add the VLAN tagging, if any */ if (packet->vlan_tag_count > 0) { if (adapter != (SshNdisIMAdapter)packet->adapter_in) { /* Engine forwards this packet to different interface. Check whether this is VLAN/QoS enabled interface and reconstruct tagging accordingly. */ switch (adapter->options & (NDIS_MAC_OPTION_8021Q_VLAN | NDIS_MAC_OPTION_8021P_PRIORITY)) { case 0: /* Adapter doesn't support IEEE 802.1q/p; drop VLAN tag(s). */ packet->vlan_tag_count = 0; break; case NDIS_MAC_OPTION_8021P_PRIORITY: /* Adapter supports only priority (QoS) tagging. */ packet->vlan_tags[0].vlan_id = 0; packet->vlan_tag_count = 1; break; default: /* Adapter supports also VLAN. Change the VLAN ID of the first tag to the one configued to this NIC driver. */ packet->vlan_tags[0].vlan_id = adapter->vlan_id; break; } } if (packet->vlan_tag_count) { unsigned char *vlan_tags; SshUInt16 i; vlan_tags = ssh_interceptor_packet_insert(ip, SSH_ETHERH_OFS_TYPE, packet->vlan_tag_count * 4); if (vlan_tags == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Failed to add VLAN tags")); return; } for (i = 0; i < packet->vlan_tag_count; i++) { unsigned char *tag = vlan_tags + (i * 4); SSH_PUT_16BIT(tag, SSH_ETHERTYPE_VLAN); SSH_PUT_16BIT((tag + 2), (packet->vlan_tags[i].vlan_id << 4 | packet->vlan_tags[i].qos)); } } } NDIS_SET_PACKET_HEADER_SIZE(packet->np, SSH_ETHERH_HDRLEN); NDIS_SET_PACKET_STATUS(packet->np, NDIS_STATUS_SUCCESS); #ifdef _WIN32_WCE if (adapter->media == NdisMediumWan) { if (ip->flags & SSH_PACKET_FROMPROTOCOL) { if (!ssh_wan_send_to_adapter(adapter, packet, ip->protocol)) SSH_DEBUG(SSH_D_FAIL, ("Cannot send packet to WAN adapter")); } else if (ip->flags & SSH_PACKET_FROMADAPTER) { if (!ssh_wan_send_to_protocol(adapter, packet, ip->protocol)) SSH_DEBUG(SSH_D_FAIL, ("Cannot send packet to WAN protocol")); } else { SSH_DEBUG(SSH_D_ERROR, ("Dropping WAN packet without direction")); } ssh_interceptor_packet_free(&packet->ip); return; } #endif /* _WIN32_WCE */ if (ip->flags & SSH_PACKET_FROMPROTOCOL) { NDIS_STATUS status; /* Send packet to network */ NdisSetPacketFlags(packet->np, NDIS_FLAGS_DONT_LOOPBACK); if (cpu_ctx->in_packet_cb || cpu_ctx->in_route_cb || cpu_ctx->in_timeout_cb) { SSH_DEBUG(SSH_D_NICETOKNOW, ("Risk for recursive call; enqueueing packet 0x%p", packet)); #ifdef DEBUG_LIGHT packet->f.flags.in_send_queue = 1; #endif /* DEBUG_LIGHT */ if (cpu_ctx->in_packet_cb) { ssh_net_packet_enqueue(&cpu_ctx->send_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_send_queue = 1; } else if (cpu_ctx->in_route_cb) { ssh_net_packet_enqueue(&cpu_ctx->route_send_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_route_send_queue = 1; } else if (cpu_ctx->in_timeout_cb) { ssh_net_packet_enqueue( &cpu_ctx->timeout_send_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_timeout_send_queue = 1; } } else { #ifdef DEBUG_LIGHT SSH_DEBUG(SSH_D_NICETOKNOW, ("Sending packet 0x%p to underlying driver", packet)); packet->f.flags.in_miniport = 1; #endif /* DEBUG_LIGHT */ NdisSend(&status, adapter->binding_handle, packet->np); if (status != NDIS_STATUS_PENDING) { SSH_DEBUG(SSH_D_NICETOKNOW, ("Send operation completed synchronously; " "packet=0x%p, status=%@", ssh_ndis_status_render, status)); ssh_interceptor_packet_free(&packet->ip); } } } else if (ip->flags & SSH_PACKET_FROMADAPTER) { /* Packet is ready now so check packet consistency */ if (use_one_buffer) first_buf_len = packet->packet_len; else first_buf_len += adapter->lookahead_size; first_buf_len = MIN(first_buf_len, packet->packet_len); if (!ssh_packet_get_contiguous_data((SshNetDataPacket)packet, 0, first_buf_len, FALSE)) { SSH_DEBUG(SSH_D_FAIL, ("Invalid packet")); goto free_packet; } if (cpu_ctx->in_packet_cb || cpu_ctx->in_route_cb || cpu_ctx->in_timeout_cb) { SSH_DEBUG(SSH_D_NICETOKNOW, ("Risk for recursive call; enqueueing packet 0x%p", packet)); #ifdef DEBUG_LIGHT packet->f.flags.in_recv_queue = 1; #endif /* DEBUG_LIGHT */ if (cpu_ctx->in_packet_cb) { ssh_net_packet_enqueue(&cpu_ctx->recv_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_recv_queue = 1; } else if (cpu_ctx->in_route_cb) { ssh_net_packet_enqueue(&cpu_ctx->route_recv_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_route_recv_queue = 1; } else if (cpu_ctx->in_timeout_cb) { ssh_net_packet_enqueue( &cpu_ctx->timeout_recv_queue[adapter->ifnum], (SshNetDataPacket)packet); cpu_ctx->packets_in_timeout_recv_queue = 1; } } else { SSH_DEBUG(SSH_D_NICETOKNOW, ("Indicating packet 0x%p to upper layers", packet)); #ifdef DEBUG_LIGHT packet->f.flags.in_protocol = 1; #endif /* DEBUG_LIGHT */ NdisMIndicateReceivePacket(adapter->handle, &packet->np, 1); } } else { SSH_NOTREACHED; } return; free_packet: /* Otherwise just drop the packet */ SSH_DEBUG(SSH_D_FAIL, ("ssh_interceptor_send(): dropping packet")); ssh_interceptor_packet_free(&packet->ip); }
// 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); } }
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); }
void CAR6KMini::ReceiveWMIDataPacket( HTC_EVENT_INFO *evInfo) // // This function processes data from an HTC_BUFFER_RECEIVED indication // not on the WMI_CONTROL_MBOX endpoint. // { ndis_mini_buf_t *pb = (ndis_mini_buf_t *)evInfo->cookie; NDIS_STATUS Status; NDIS_PACKET *pPacket; NDIS_BUFFER *pBuffer; PBYTE pData; ULONG cbData; BOOL doDix = FALSE; USHORT etherType; SNAP_HEADER *pSnapHdr; MAC_ADDRESS *pDestAddr,*tempAddr; BOOL mcForUs = FALSE; NDIS_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV, "AR6K: +ReceiveWMIDataPacket"); if (evInfo->status != A_OK) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket Error in receiving : status = %x\n", evInfo->status); if (A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } // evInfo->actualLength is the length of the pb->data including // 2 bytes: WMI_DATA_HEADER [optional - only if HTC header is 46 00] // 14 bytes: 802.3 MAC header // 8 bytes: SNAP header (with EthType as last 2 bytes) // N bytes: payload (e.g. IP packet) pData = evInfo->buffer; cbData = evInfo->actualLength; // Remove the WMI_DATA_HDR. if (cbData < sizeof(WMI_DATA_HDR)) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket missing WMI header (%u bytes)\n", evInfo->actualLength); if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } pData += sizeof(WMI_DATA_HDR); cbData -= sizeof(WMI_DATA_HDR); if (cbData < sizeof(ETHERNET_MAC_HEADER) + sizeof(SNAP_HEADER)) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - ReceiveWMIPacket missing MAC + SNAP (%u bytes)\n", cbData); if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } #ifdef WMM Lock(); wmi_implicit_create_pstream((wmi_t *)m_pWMI, pb, DNLINK_TRAFFIC,1); Unlock(); #endif //WMM pDestAddr=(MAC_ADDRESS *)pData; /* Apply NDIS receive filter */ if (isGrp(pDestAddr)) { if (isBcast(pDestAddr)) { if (!(m_CurrentPacketFilter & NDIS_PACKET_TYPE_BROADCAST)) { if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } } else { isMcForUs(pDestAddr,&mcForUs); if (!(m_CurrentPacketFilter & (NDIS_PACKET_TYPE_MULTICAST | NDIS_PACKET_TYPE_ALL_MULTICAST)) || !(mcForUs)) { if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } } } else { tempAddr=(MAC_ADDRESS *) m_PermanentAddress; if ((A_MACADDR_COMP(pDestAddr,tempAddr) != 0) && !(m_CurrentPacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)) { if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } } // Allocate an NDIS_PACKET from our packet pool. NdisAllocatePacket(&Status, &pPacket, m_RxPacketPool); if (NDIS_STATUS_SUCCESS != Status) { NDIS_DEBUG_PRINTF(ATH_LOG_ERR, "AR6K: ERROR - NdisAllocatePacket failed\n"); if ( A_OK != HTCBufferReceive(m_pHTCTarget, ENDPOINT2, a_netbuf_to_data(pb), AR6000_BUFFER_SIZE, pb)) { a_netbuf_free(pb); } goto done; } // Check for ethernetType in SNAP header for NOVELL_IPX, APPLE_TALK_ARP etc // remove 802.3 length and SNAP header if it is not of these types pSnapHdr=(SNAP_HEADER *)(pData+sizeof(ETHERNET_MAC_HEADER)); etherType=A_BE2CPU16(pSnapHdr->Type); doDix=((A_MEMCMP(pSnapHdr,&bridgeTunnel, sizeof(CAP_CONST))) == 0); if((!doDix) && ((A_MEMCMP(pSnapHdr,&vrfc1042, sizeof(CAP_CONST))) == 0)) { doDix = ((etherType != APPLE_TALK_ARP) && (etherType != NOVELL_IPX)); } // Get rid of the 802.3 length and SNAP header by copying // the 802.3 DestMACAddr and SrcMACAddr forward so they // immediately precede the EthType at the end of the SNAP header. // That gives us a DIX packet. if (doDix) { memmove(pData + sizeof(SNAP_HEADER), pData, ETHERNET_MAC_ADDRESS_LENGTH * 2); pData += sizeof(SNAP_HEADER); cbData -= sizeof(SNAP_HEADER); } // Setup the fields of NDIS_BUFFER to point to our data. pBuffer = &pb->NdisBuffer; NdisInitializeBuffer(pBuffer, pData, cbData); // Chain the NDIS_BUFFER to the start of the NDIS_PACKET NdisChainBufferAtBack(pPacket, pBuffer); NDIS_SET_PACKET_HEADER_SIZE(pPacket, sizeof(ETHERNET_MAC_HEADER)); NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_SUCCESS); #ifdef NDIS_BUS_DRIVER NDIS_PACKET *PacketArray[1]; PacketArray[0]=pPacket; NdisMIndicateReceivePacket(m_MiniportAdapterHandle, PacketArray, 1); #else // Perform the indicate on the timer thread because tying up the // SDIO receive indication thread can result in a deadlock. PLIST_ENTRY pEntry = (PLIST_ENTRY)(pPacket->MiniportReserved); Lock(); InsertTailList(&m_RxPendingPacketList, pEntry); NdisSetEvent(&m_RxPendingEvent); Unlock(); #endif done: NDIS_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV, "AR6K: -ReceiveWMIDataPacket"); }
NTSTATUS divert_write( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { int rc = STATUS_SUCCESS; PNDIS_PACKET pNdisPacket; PADAPT pa = _pa, pa2; // XXX NDIS_STATUS status; PIO_STACK_LOCATION pIrpSp; NDISPROT_ETH_HEADER UNALIGNED *pEthHeader; pIrpSp = IoGetCurrentIrpStackLocation(pIrp); if (pIrp->MdlAddress == NULL) { rc = STATUS_INSUFFICIENT_RESOURCES; goto Out; } if (!(pEthHeader = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority))) { rc = STATUS_INSUFFICIENT_RESOURCES; goto Out; } lock(); NdisAllocatePacket(&status, &pNdisPacket, _packet_pool); unlock(); if (status != STATUS_SUCCESS) { rc = STATUS_INSUFFICIENT_RESOURCES; goto Out; } NdisChainBufferAtFront(pNdisPacket, pIrp->MdlAddress); if ((pa2 = get_pa(pEthHeader->SrcAddr))) { NdisSendPackets(pa2->BindingHandle, &pNdisPacket, 1); } else { pa2 = get_pa(pEthHeader->DstAddr); if (pa2) pa = pa2; NDIS_SET_PACKET_STATUS(pNdisPacket, NDIS_STATUS_RESOURCES); NdisMIndicateReceivePacket(pa->MiniportHandle, &pNdisPacket, 1); NdisFreePacket(pNdisPacket); } rc = STATUS_PENDING; rc = STATUS_SUCCESS; Out: pIrp->IoStatus.Status = rc; if (rc != STATUS_PENDING) { pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } return rc; }
INT 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; }
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; }
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; }
/****************************************************************************** * * Name: HandleRxReadyEvent() * * Description: Rx ready event handler * * Arguments: PMRVDRV_ADAPTER Adapter * * Return Value: * * Notes: * *****************************************************************************/ VOID HandleRxReadyEvent( IN PMRVDRV_ADAPTER Adapter ) { int IsRxOK = 0; PRxPD pRxPDCurrent; PNDIS_PACKET pPacket; NDIS_STATUS pStatus; DBGPRINT(DBG_RX | DBG_HELP,(L"+HandleRxReadyEvent()\n")); pRxPDCurrent = (PRxPD)(Adapter->pRxPD1); //lykao, 060905, begin if (pRxPDCurrent->Status & MRVDRV_RXPD_STATUS_OK) { Adapter->RcvOK++; Adapter->DirectedFramesRcvOK++; wlan_compute_rssi(Adapter,pRxPDCurrent); } else { DBGPRINT(DBG_RX | DBG_WARNING,(L"WARNING: frame received with bad status\n")); //dralee++ 09212005 for error handling pPacket = Adapter->pRxCurPkt; Adapter->pRxCurPkt = NULL; if ( pPacket ) ReturnRxPacketDesc(Adapter,pPacket); return; } pPacket = Adapter->pRxCurPkt; Adapter->pRxCurPkt = NULL; if (Adapter->MediaConnectStatus == NdisMediaStateConnected) { Adapter->ulRxByteInLastPeriod += Adapter->ulRxSize; NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_SUCCESS); NdisMIndicateReceivePacket(Adapter->MrvDrvAdapterHdl, &pPacket, 1); pStatus = NDIS_GET_PACKET_STATUS(pPacket); if ((pStatus == NDIS_STATUS_RESOURCES) || (pStatus == NDIS_STATUS_SUCCESS)) { // return packet DBGPRINT(DBG_RX|DBG_HELP, (L"Packet returned success or resources...\n")); ReturnRxPacketDesc(Adapter,pPacket); } else { DBGPRINT(DBG_RX|DBG_ERROR, (L"Packet returned pending...\n")); } } else { ///pmkcache: bug#16956 ++ if (Adapter->bIsReconnectAssociation == TRUE) { Adapter->isPktPending = TRUE; if ( Adapter->pPendedRxPkt ) { NKDbgPrintfW( L"ERROR, a pended RX packet has not been process!!\r\n" ); } Adapter->pPendedRxPkt = pPacket; return; } ///pmkcache: bug#16956 -- DBGPRINT(DBG_RX|DBG_ERROR, (L"Not connected, packet was dropped...\n")); ReturnRxPacketDesc(Adapter,pPacket); } return; }
/*------------------------------------------------------------------------- ssh_driver_send_packets() Sends multiple NDIS packet into the network via virtual NIC. The packets are copied and then saved into a queue. The interceptor thread then processes the packets later. Arguments: miniport_context - virtual NIC object packet_array - array of NDIS packets packet_cnt - number of packets in the array Returns: Notes: To ensure that the sequential ordering of packets is not changed in error conditions we interrupt processing packets in the array whenever we notice that we cannot handle the packet. All the remaining packets in the array are then completed with FAILURE status. If we are running low of NDIS_PACKET resources then return with failure so that upper layer notices our lack of resources and the traffic then decreases. Default IRQL: <= DISPATCH_LEVEL -------------------------------------------------------------------------*/ static Boolean ssh_driver_copy_and_send(SshNdisIMAdapter adapter, PNDIS_PACKET src) { SshNdisIMInterceptor interceptor; SshCpuContext cpu_ctx; SshNdisPacket packet; ULONG new_value; UINT flags; SSH_IRQL old_irql; Boolean status = FALSE; SSH_ASSERT(adapter != NULL); SSH_ASSERT(src != NULL); SSH_RAISE_IRQL(DISPATCH_LEVEL, &old_irql); new_value = InterlockedIncrement(&adapter->ref_count); SSH_ASSERT(new_value > 0); if (!ssh_adapter_can_accept_send(adapter)) { SSH_DEBUG(SSH_D_FAIL, ("Adapter %@: not in running state!", ssh_adapter_id_st_render, adapter)); InterlockedDecrement(&adapter->ref_count); goto end; } interceptor = (SshNdisIMInterceptor)adapter->interceptor; #ifdef _WIN32_WCE ssh_kernel_critical_section_start(&interceptor->packet_pool_cs); #endif /* _WIN32_WCE */ cpu_ctx = &interceptor->cpu_ctx[ssh_kernel_get_cpu()]; /* Try to clone the original packet's descriptors */ packet = ssh_packet_clone((SshInterceptor)interceptor, &cpu_ctx->packet_pool, SSH_PROTOCOL_ETHERNET, src, FALSE); #ifdef _WIN32_WCE ssh_kernel_critical_section_end(&interceptor->packet_pool_cs); #endif /* _WIN32_WCE */ if (packet == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Adapter %@: Failed to clone packet", ssh_adapter_id_st_render, adapter)); InterlockedDecrement(&adapter->ref_count); goto end; } NDIS_SET_PACKET_STATUS(src, NDIS_STATUS_PENDING); packet->complete_cb = ssh_driver_send_complete_cb; packet->complete_cb_handle = adapter; packet->complete_cb_param = NULL; packet->parent_complete_cb = ssh_driver_parent_send_complete_cb; packet->parent_complete_handle = adapter; packet->parent_complete_np = src; packet->parent_complete_param = (void *)NDIS_STATUS_SUCCESS; /* Set don't loopback flag and per packet info */ flags = NdisGetPacketFlags(packet->np); flags |= NDIS_FLAGS_DONT_LOOPBACK; NdisSetPacketFlags(packet->np, flags); NdisIMCopySendPerPacketInfo(packet->np, src); /* Set the information that engine uses */ SSH_DUMP_PACKET(SSH_D_MY5, "Cloned packet:", packet); packet->f.flags.from_local_stack = 1; packet->ip.ifnum_in = adapter->ifnum; packet->ip.flags |= SSH_PACKET_FROMPROTOCOL; packet->adapter_in = (SshAdapter)adapter; SSH_DEBUG(SSH_D_NICETOKNOW, ("Adapter %@: %u operations pending", ssh_adapter_id_st_render, adapter, new_value)); ssh_interceptor_send_to_engine(interceptor, adapter, packet); ssh_interceptor_process_enqueued_packets(interceptor, cpu_ctx); status = TRUE; end: if (old_irql < SSH_DISPATCH_LEVEL) SSH_LOWER_IRQL(old_irql); return status; }
/* Maps to ReceiverReceiveNetBufferList() in xennet6 */ static NTSTATUS ReceiverReceivePacket( IN PRECEIVER Receiver, OUT PNDIS_PACKET *pPacket, OUT ULONG *pTotFrags ) { struct ethhdr *eh; PNDIS_PACKET work; NDIS_STATUS stat; PNDIS_BUFFER buffer; uint16_t head_flags; UINT buffer_length; ULONG totOctets; ULONG totFrags; PMP_RFD prefixRfd; PMP_RFD headRfd; stat = ReceiverCommonReceiveRfdChain(Receiver, &head_flags, &prefixRfd, &headRfd, &totOctets, &totFrags); if (stat != NDIS_STATUS_SUCCESS) { Receiver->Common.Adapter->RxError++; goto discard; } XM_ASSERT(totFrags > 0); /* There should never be a prefix as we do not enable GSO on the receive path. */ XM_ASSERT(prefixRfd == NULL); NdisDprAllocatePacketNonInterlocked(&stat, &work, Receiver->RecvPacketPool); if (stat != NDIS_STATUS_SUCCESS) { Receiver->nRxDiscards++; goto discard; } NDIS_SET_PACKET_HEADER_SIZE(work, XENNET_PACKET_HDR_SIZE); NdisChainBufferAtFront(work, &headRfd->Mdl); /* Ick: find the ethernet and IP headers so that we can check (a) the MAC address is for us, and (b) whether to indicate RX csum offload. We rely on the fact that netback always puts the ethernet and IP headers in the same fragment. */ buffer = &headRfd->Mdl; buffer_length = buffer->ByteCount; stat = STATUS_UNSUCCESSFUL; if (buffer_length < sizeof(struct ethhdr)) { NdisDprFreePacketNonInterlocked(work); Receiver->nRxDiscards++; goto discard; } Receiver->Common.Adapter->RxGood++; eh = (struct ethhdr *)buffer->MappedSystemVa; stat = NDIS_STATUS_INVALID_PACKET; if (!MacAddressInteresting(eh->dest, Receiver->Common.Adapter)) { Receiver->Common.Adapter->MacMisdirect++; NdisDprFreePacketNonInterlocked(work); goto discard; } if (eh->proto == TPID_IPV4) { BOOLEAN needCsumFixup; NDIS_TCP_IP_CHECKSUM_PACKET_INFO CsumInfo; CsumInfo.Value = 0; needCsumFixup = (head_flags & NETRXF_csum_blank) ? TRUE : FALSE; if (head_flags & NETRXF_data_validated) { struct iphdr *ih = (struct iphdr *)(eh + 1); if (ih->proto == IPPROTO_TCP && Receiver->rx_csum_tcp_offload) { CsumInfo.Receive.NdisPacketTcpChecksumSucceeded = 1; Receiver->nRxCsumOffload++; } else if (ih->proto == IPPROTO_UDP && Receiver->rx_csum_udp_offload) { CsumInfo.Receive.NdisPacketUdpChecksumSucceeded = 1; Receiver->nRxCsumOffload++; } } if (needCsumFixup) { FixupChecksum(work); Receiver->nRxCsumFixup++; } NDIS_PER_PACKET_INFO_FROM_PACKET(work, TcpIpChecksumPacketInfo) = (PVOID)(ULONG_PTR)CsumInfo.Value; } NDIS_SET_PACKET_STATUS(work, NDIS_STATUS_SUCCESS); *pPacket = work; *pTotFrags = totFrags; return NDIS_STATUS_SUCCESS; discard: ReceiverCommonReleaseRfdChain(&Receiver->Common, prefixRfd); ReceiverCommonReleaseRfdChain(&Receiver->Common, headRfd); return stat; }
static Boolean ssh_driver_copy_and_send_wan(SshNdisIMAdapter adapter, PNDIS_WAN_PACKET pkt, SshInterceptorProtocol protocol) { SshNdisIMInterceptor interceptor; SshCpuContext cpu_ctx; SshInterceptorPacket ip; SshNdisPacket packet; LONG new_value; SSH_ASSERT(adapter != NULL); SSH_ASSERT(adapter->interceptor != NULL); SSH_ASSERT(pkt != NULL); interceptor = (SshNdisIMInterceptor)adapter->interceptor; SSH_ASSERT(MAXIMUM_PROCESSORS == 1); cpu_ctx = &interceptor->cpu_ctx[0]; /* Allocate a new packet. */ ip = ssh_interceptor_packet_alloc((SshInterceptor)interceptor, SSH_PACKET_FROMADAPTER, protocol, adapter->ifnum, SSH_INTERCEPTOR_INVALID_IFNUM, pkt->CurrentLength); if (ip == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Adapter %@: Failed to allocate packet", ssh_adapter_id_st_render, adapter)); return FALSE; } /* Copy the data into the packet. */ if (!ssh_interceptor_packet_copyin(ip, 0, pkt->CurrentBuffer, pkt->CurrentLength)) { SSH_DEBUG(SSH_D_FAIL, ("Adapter %@: Failed to copy WAN packet", ssh_adapter_id_st_render, adapter)); return FALSE; } packet = CONTAINING_RECORD(ip, SshNdisPacketStruct, ip); /* Set don't loopback flag. */ NdisSetPacketFlags(packet->np, NDIS_FLAGS_DONT_LOOPBACK); NDIS_SET_PACKET_STATUS(packet->np, NDIS_STATUS_SUCCESS); SSH_ASSERT(packet->parent_complete_cb == NULL_FNPTR); packet->complete_cb = ssh_driver_send_complete_cb; packet->complete_cb_handle = adapter; packet->complete_cb_param = NULL; packet->f.flags.from_local_stack = 1; packet->ip.ifnum_in = adapter->ifnum; packet->ip.flags |= SSH_PACKET_FROMPROTOCOL; packet->adapter_in = (SshAdapter)adapter; new_value = InterlockedIncrement(&adapter->ref_count); SSH_ASSERT(new_value > 0); SSH_DUMP_PACKET(SSH_D_MY5, ("Cloned packet:"), packet); ssh_interceptor_send_to_engine(interceptor, adapter, packet); ssh_interceptor_process_enqueued_packets(interceptor, cpu_ctx); return TRUE; }
VOID ReceiverHandleNotification( IN PRECEIVER Receiver ) /*++ Routine Description: Interrupt handler for receive processing Put the received packets into an array and call NdisMIndicateReceivePacket If we run low on RFDs, allocate another one Arguments: Adapter Pointer to our adapter Return Value: None --*/ { PADAPTER Adapter = Receiver->Common.Adapter; RING_IDX prod; int more_work; PNDIS_PACKET PacketArray[XENNET_DEF_RFDS]; NDIS_STATUS PacketStatus[XENNET_DEF_RFDS]; UINT PacketCount; if (!RING_HAS_UNCONSUMED_RESPONSES(&Receiver->Common.Ring)) return; NdisDprAcquireSpinLock(&Receiver->Common.Lock); if (Receiver->Common.Adapter->media_disconnect) { NdisDprReleaseSpinLock(&Receiver->Common.Lock); return; } if (__RING_IDX_DIFFERENCE(Receiver->Common.Ring.req_prod_pvt, Receiver->Common.Ring.sring->rsp_prod) > NET_RX_RING_SIZE) TraceWarning(("Strange: rsp_prod ahead of req_prod (%d vs %d (s %d))\n", Receiver->Common.Ring.sring->rsp_prod, Receiver->Common.Ring.req_prod_pvt, Receiver->Common.Ring.sring->req_prod)); PacketCount = 0; top: prod = Receiver->Common.Ring.sring->rsp_prod; XsMemoryBarrier(); while (!RING_IDXS_EQ(Receiver->Common.Ring.rsp_cons, prod)) { PNDIS_PACKET packet; ULONG totFrags; NDIS_STATUS status; status = ReceiverReceivePacket(Receiver, &packet, &totFrags); if (status != NDIS_STATUS_SUCCESS) continue; TraceProfile(("%s(%s, %p)\n", __FUNCTION__, Adapter->XenbusPrefix, packet)); // See http://msdn.microsoft.com/en-us/library/ms797610.aspx if (Receiver->LowResources == 2 || (Receiver->LowResources == 1 && totFrags > 1)) { status = NDIS_STATUS_RESOURCES; NDIS_SET_PACKET_STATUS(packet, status); } PacketArray[PacketCount] = packet; PacketStatus[PacketCount] = status; PacketCount++; if (PacketCount == XENNET_DEF_RFDS) { ULONG Index; Receiver->Common.Frames += PacketCount; Receiver->nRxInNdis += PacketCount; if (Receiver->nRxInNdis >= Receiver->nRxInNdisMax) Receiver->nRxInNdisMax = Receiver->nRxInNdis; NdisDprReleaseSpinLock(&Receiver->Common.Lock); NdisMIndicateReceivePacket( Receiver->Common.Adapter->AdapterHandle, PacketArray, PacketCount); NdisDprAcquireSpinLock(&Receiver->Common.Lock); for (Index = 0; Index < PacketCount; Index++) { if (PacketStatus[Index] == NDIS_STATUS_RESOURCES) { ReceiverReleasePacket(Receiver, PacketArray[Index]); Receiver->nRxInNdis--; } else { XM_ASSERT(PacketStatus[Index] == NDIS_STATUS_SUCCESS); } } PacketCount = 0; ReceiverSwizzle(Receiver); } } RING_FINAL_CHECK_FOR_RESPONSES(&Receiver->Common.Ring, more_work); if (more_work) goto top; if (PacketCount != 0) { ULONG Index; Receiver->Common.Frames += PacketCount; Receiver->nRxInNdis += PacketCount; if (Receiver->nRxInNdis >= Receiver->nRxInNdisMax) Receiver->nRxInNdisMax = Receiver->nRxInNdis; NdisDprReleaseSpinLock(&Receiver->Common.Lock); NdisMIndicateReceivePacket( Receiver->Common.Adapter->AdapterHandle, PacketArray, PacketCount); NdisDprAcquireSpinLock(&Receiver->Common.Lock); for (Index = 0; Index < PacketCount; Index++) { if (PacketStatus[Index] == NDIS_STATUS_RESOURCES) { ReceiverReleasePacket(Receiver, PacketArray[Index]); Receiver->nRxInNdis--; } else { XM_ASSERT(PacketStatus[Index] == NDIS_STATUS_SUCCESS); } } PacketCount = 0; } // Swizzle unconditionally to make sure we replenish the ring even if // nothing was passed to NDIS. ReceiverSwizzle(Receiver); NdisDprReleaseSpinLock(&Receiver->Common.Lock); /* XXX Should maybe adjust size of packet pool from here. */ }
NDIS_STATUS PtReceive( IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookAheadBufferSize, IN UINT PacketSize ) /*++ Routine Description: Handle receive data indicated up by the miniport below. We pass it along to the protocol above us. If the miniport below indicates packets, NDIS would more likely call us at our ReceivePacket handler. However we might be called here in certain situations even though the miniport below has indicated a receive packet, e.g. if the miniport had set packet status to NDIS_STATUS_RESOURCES. Arguments: <see DDK ref page for ProtocolReceive> Return Value: NDIS_STATUS_SUCCESS if we processed the receive successfully, NDIS_STATUS_XXX error code if we discarded it. --*/ { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; PNDIS_PACKET MyPacket, Packet; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; if (!pAdapt->MiniportHandle) { Status = NDIS_STATUS_FAILURE; } else do { // // Get at the packet, if any, indicated up by the miniport below. // Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext); if (Packet != NULL) { //------------------------------WestChamber--------------------------------- BOOLEAN result=WestChamberReceiverMain(Packet,pAdapt); if(result==FALSE) { //Simply drop the packet. return NDIS_STATUS_NOT_ACCEPTED; } //------------------------------WestChamber--------------------------------- // // The miniport below did indicate up a packet. Use information // from that packet to construct a new packet to indicate up. // #ifdef NDIS51 // // NDIS 5.1 NOTE: Do not reuse the original packet in indicating // up a receive, even if there is sufficient packet stack space. // If we had to do so, we would have had to overwrite the // status field in the original packet to NDIS_STATUS_RESOURCES, // and it is not allowed for protocols to overwrite this field // in received packets. // #endif // NDIS51 // // Get a packet off the pool and indicate that up // NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { // // Make our packet point to data from the original // packet. NOTE: this works only because we are // indicating a receive directly from the context of // our receive indication. If we need to queue this // packet and indicate it from another thread context, // we will also have to allocate a new buffer and copy // over the packet contents, OOB data and per-packet // information. This is because the packet data // is available only for the duration of this // receive indication call. // MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; // // Get the original packet (it could be the same packet as the // one received or a different one based on the number of layered // miniports below) and set it on the indicated packet so the OOB // data is visible correctly at protocols above. // NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize); // // Copy packet flags. // NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); // // Force protocols above to make a copy if they want to hang // on to data in this packet. This is because we are in our // Receive handler (not ReceivePacket) and we can't return a // ref count from here. // NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES); // // By setting NDIS_STATUS_RESOURCES, we also know that we can reclaim // this packet as soon as the call to NdisMIndicateReceivePacket // returns. // NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1); // // Reclaim the indicated packet. Since we had set its status // to NDIS_STATUS_RESOURCES, we are guaranteed that protocols // above are done with it. // NdisDprFreePacket(MyPacket); break; } } else { // // The miniport below us uses the old-style (not packet) // receive indication. Fall through. // } // // Fall through if the miniport below us has either not // indicated a packet or we could not allocate one // pAdapt->IndicateRcvComplete = TRUE; switch (pAdapt->Medium) { case NdisMedium802_3: case NdisMediumWan: NdisMEthIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break; case NdisMedium802_5: NdisMTrIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); break; case NdisMediumFddi: /* NdisMFddiIndicateReceive(pAdapt->MiniportHandle, MacReceiveContext, HeaderBuffer, HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize, PacketSize); */ break; default: ASSERT(FALSE); break; } } while(FALSE); return Status; }