VOID FilterReceiveNetBufferLists( IN NDIS_HANDLE FilterModuleContext, IN PNET_BUFFER_LIST NetBufferLists, IN NDIS_PORT_NUMBER PortNumber, IN ULONG NumberOfNetBufferLists, IN ULONG ReceiveFlags ) /*++ Routine Description: FilerReceiveNetBufferLists is an optional function for filter drivers. If provided, this function process receive indications made by underlying NIC or lower level filter drivers. This function can also be called as a result of loopback. If this handler is NULL, NDIS will skip calling this filter when processing a receive indication and will call the next upper filter in the stack with a non-NULL FitlerReceiveNetBufferLists handler or the procotol driver. A filter that doesn't provide a FilterReceiveNetBufferLists handler can not provided a FilterReturnNetBufferLists handler or a initiate a receive indication on its own. Arguments: FilterModuleContext: Pointer to our filter context area. NetBufferLists: A linked list of NetBufferLists allocated by underlying driver each containing one NetBuffer. PortNumber: Port on which the Receive is indicated ReceiveFlags: Flags associated with the Receive such as whether the filter can pend the receive Return Value: None --*/ { PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; NDIS_STATUS ReturnStatus = NDIS_STATUS_SUCCESS; PNET_BUFFER_LIST NextNetBufferList; BOOLEAN DispatchLevel; ULONG ReturnFlags; ULONG Ref; // ++ PNET_BUFFER_LIST CurrentBufferList = NULL; PNET_BUFFER CurrentBuffer = NULL; PNET_BUFFER_DATA CurrentBufferData = NULL; BOOLEAN HaveARPPacket = FALSE; PMDL PacketMdl = NULL; ULONG DataOffset = 0; ULONG PacketSize = 0; PUCHAR PacketData = NULL; ARP_PACKET* ArpPacket = NULL; GATEWAY_ITEM* Gateway = NULL; LAN_ITEM* LanItem = NULL; WAN_ITEM* WanItem = NULL; ULONG i = 0; BOOLEAN bSameRecord = FALSE; enum ATTACH_TYPE AttachType = ATTACH_NONE; enum RAS_OPT RetOpt = OPT_PASS; BOOLEAN bWanAdapter = FALSE; // -- DEBUGP(DL_TRACE, ("===>ReceiveNetBufferList: NetBufferLists = %p.\n", NetBufferLists)); do { DispatchLevel = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags); #if DBG FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel); if (pFilter->State != FilterRunning) { FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags)) { ReturnFlags = 0; if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags)) { NDIS_SET_RETURN_FLAG(ReturnFlags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL); } NdisFReturnNetBufferLists(pFilter->FilterHandle, NetBufferLists, ReturnFlags); } break; } FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); #endif ASSERT(NumberOfNetBufferLists >= 1); // ++ CurrentBufferList = NetBufferLists; while(CurrentBufferList) { // Each NET_BUFFER structure packages a packet of network data CurrentBuffer = NET_BUFFER_LIST_FIRST_NB(CurrentBufferList); while(CurrentBuffer) { // 检测其中是否有ARP协议包 PacketMdl = NET_BUFFER_FIRST_MDL(CurrentBuffer); DataOffset = NET_BUFFER_DATA_OFFSET(CurrentBuffer); PacketSize = NET_BUFFER_DATA_LENGTH(CurrentBuffer); if(PacketMdl && PacketSize) { PacketData = (UCHAR*)MmGetSystemAddressForMdlSafe(PacketMdl,NormalPagePriority); if(PacketData) { if(DataOffset) { PacketData = PacketData + DataOffset; } // PacketData 是网络包数据,PacketSize 是网络包数据长度 do { ArpPacket = (ARP_PACKET*)PacketData; if( ArpPacket->EthType != ETHERNET_ARP || PacketSize < sizeof(ARP_PACKET) ) { break; } else { KdPrint((" 收到ARP数据包")); } if( ArpPacket->OperateCode != 0x100 && ArpPacket->OperateCode != 0x200 && ArpPacket->OperateCode != 0x300 && ArpPacket->OperateCode != 0x400 ) { KdPrint((" 错误ARP/RARP协议攻击")); AttachType = WRONG_PROTOCOL_ATTACH; RetOpt = OPT_DROP; goto Exit; } //进行 IP - Mac 对应查询表的建立 NdisAcquireSpinLock(&GlobalLock); if(g_ArpFw_ShareMem) { // 查询广播包 if( ArpPacket->OperateCode == ARP_QUERY && NdisEqualMemory(ArpPacket->DestMacAddress,Empty_MacAddress,6) && !NdisEqualMemory(ArpPacket->SourceMacAddress,Empty_MacAddress,6) && g_ArpFw_ShareMem->ulItemCount < MAX_IP_MAC_ITEM_COUNT ) { bSameRecord = FALSE; for( i = 0 ; i< g_ArpFw_ShareMem->ulItemCount; i++) { if(NdisEqualMemory( g_ArpFw_ShareMem->Items[i].IPAddress,ArpPacket->SourceIPAddress,4)) { bSameRecord = TRUE; break; } } //当前没有该IP地址的记录 if(!bSameRecord) { memcpy(g_ArpFw_ShareMem->Items[g_ArpFw_ShareMem->ulItemCount].IPAddress, ArpPacket->SourceIPAddress,4); memcpy(g_ArpFw_ShareMem->Items[g_ArpFw_ShareMem->ulItemCount].MacAddress, ArpPacket->SourceMacAddress,6); g_ArpFw_ShareMem->ulItemCount ++; } } } NdisReleaseSpinLock(&GlobalLock); // ARP Reply 报文记录 if( ArpPacket->OperateCode == ARP_REPLY && g_bRecord_ARP_Reply && NdisEqualMemory(ArpPacket->SourceIPAddress,g_Want_ARP_Reply_IP,4) ) { bSameRecord = FALSE; NdisAcquireSpinLock(&GlobalLock); if(g_Reply_Record->ulItemCount < MAX_REPLY_RECORD) { do { if(g_Reply_Record->ulItemCount > 0) { for(i = 0 ; i < g_Reply_Record->ulItemCount; i ++) { if(NdisEqualMemory(ArpPacket->SourceMacAddress, g_Reply_Record->Items[i].MacAddress,6)) { g_Reply_Record->Items[i].RecordCount ++; bSameRecord = TRUE; break; } } } if(!bSameRecord) { NdisMoveMemory(g_Reply_Record->Items[g_Reply_Record->ulItemCount].IPAddress, ArpPacket->SourceIPAddress,4); NdisMoveMemory(g_Reply_Record->Items[g_Reply_Record->ulItemCount].MacAddress, ArpPacket->SourceMacAddress,6); g_Reply_Record->Items[g_Reply_Record->ulItemCount].WanAddress = bWanAdapter; g_Reply_Record->Items[g_Reply_Record->ulItemCount].Gateway = TRUE; g_Reply_Record->Items[g_Reply_Record->ulItemCount].Next = NULL; g_Reply_Record->Items[g_Reply_Record->ulItemCount].RecordCount = 1; g_Reply_Record->ulItemCount ++; } } while(FALSE); } NdisReleaseSpinLock(&GlobalLock); } //检测伪造ARP/RARP Query攻击中的源Mac地址是否为正确的网关地址 if( g_EnableGatewayCheck && (ArpPacket->OperateCode == ARP_QUERY || ArpPacket->OperateCode == RARP_QUERY ) ) { // 网关地址检测,Query操作中的源地址和源MAC地址必须是正确的 if(!bWanAdapter) // 局域网网关检测 { NdisAcquireSpinLock(&GlobalLock); Gateway = g_Gateway_List; while(Gateway) { if( NdisEqualMemory(ArpPacket->SourceIPAddress,Gateway->IPAddress,4) && !NdisEqualMemory(ArpPacket->SourceMacAddress,Gateway->MacAddress,6) ) { // IP地址相同,Mac地址不同 (禁止该包往上通行) KdPrint(("伪造网关Query攻击报文")); AttachType = GATEWAY_ARP_QUERY_ATTACH; RetOpt = OPT_DROP; NdisReleaseSpinLock(&GlobalLock); goto Exit; } Gateway = Gateway->Next; } NdisReleaseSpinLock(&GlobalLock); } } //伪造的ARP/RARP Reply报文检测 if( g_EnableGatewayCheck && (ArpPacket->OperateCode == ARP_REPLY || ArpPacket->OperateCode == RARP_REPLY) ) { if(!bWanAdapter) // 局域网网关检测 { NdisAcquireSpinLock(&GlobalLock); Gateway = g_Gateway_List; while(Gateway) { if( NdisEqualMemory(Gateway->IPAddress,ArpPacket->SourceIPAddress,4) && // 是网关IP !NdisEqualMemory(Gateway->MacAddress,ArpPacket->SourceMacAddress,6) ) // Mac 地址不相同,网关攻击 { KdPrint(("伪造网关Reply攻击报文")); //禁止该包往上通行 AttachType = GATEWAY_ARP_REPLY_ATTACH; RetOpt = OPT_DROP; NdisReleaseSpinLock(&GlobalLock); goto Exit; } else if(NdisEqualMemory(Gateway->IPAddress,ArpPacket->DestIPAddress,4) && !NdisEqualMemory(Gateway->MacAddress,ArpPacket->DestMacAddress,6) ) { KdPrint(("伪造网关Reply攻击报文")); //禁止该包往上通行 RetOpt = OPT_DROP; AttachType = GATEWAY_ARP_REPLY_ATTACH; NdisReleaseSpinLock(&GlobalLock); goto Exit; } Gateway = Gateway->Next; } NdisReleaseSpinLock(&GlobalLock); } } //进行 IP 冲突攻击检测 if( g_EnableSameIPCheck && NdisEqualMemory(ArpPacket->SourceIPAddress,ArpPacket->DestIPAddress,4) ) { NdisAcquireSpinLock(&GlobalLock); if(!bWanAdapter) // 局域网检测 { LanItem = g_Lan_List; while(LanItem) { // IP 地址相同 而 源Mac 地址不同 if( NdisEqualMemory(ArpPacket->SourceIPAddress,LanItem->IPAddress,4) && !NdisEqualMemory(ArpPacket->SourceMacAddress,LanItem->MacAddress,6) ) { KdPrint(("伪造内网间IP冲突攻击报文")); RetOpt = OPT_DROP; AttachType = LAN_SAMEIP_ATTACH; NdisReleaseSpinLock(&GlobalLock); goto Exit; } LanItem = LanItem->Next; } // 局域网对外网的相同IP攻击 WanItem = g_Wan_List; while(WanItem) { if(NdisEqualMemory(ArpPacket->SourceIPAddress,WanItem->IPAddress,4)) { KdPrint(("伪造内外网间IP冲突攻击报文")); RetOpt = OPT_DROP; AttachType = WAN_SAMEIP_ATTACH; NdisReleaseSpinLock(&GlobalLock); goto Exit; } WanItem = WanItem->Next; } } NdisReleaseSpinLock(&GlobalLock); } } while(FALSE); } } CurrentBuffer = NET_BUFFER_NEXT_NB(CurrentBuffer); } CurrentBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrentBufferList); } // -- // // If necessary, queue the NetBufferList in a local structure for later processing. // We may need to travel the list, some of them may not need post processing // if (pFilter->TrackReceives) { FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel); pFilter->OutstandingRcvs += NumberOfNetBufferLists; Ref = pFilter->OutstandingRcvs; FILTER_LOG_RCV_REF(1, pFilter, NetBufferLists, Ref); FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); } KdPrint((" NdisFIndicateReceiveNetBufferLists Run ")); NdisFIndicateReceiveNetBufferLists( pFilter->FilterHandle, NetBufferLists, PortNumber, NumberOfNetBufferLists, ReceiveFlags); if (NDIS_TEST_RECEIVE_CANNOT_PEND(ReceiveFlags) && pFilter->TrackReceives) { FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel); pFilter->OutstandingRcvs -= NumberOfNetBufferLists; Ref = pFilter->OutstandingRcvs; FILTER_LOG_RCV_REF(2, pFilter, NetBufferLists, Ref); FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); } // ++ break; Exit: KdPrint((" Drop Received Packet ")); if(ArpPacket) { NdisAcquireSpinLock(&GlobalLock); if(g_ArpFw_ShareMem && AttachType != ATTACH_NONE) { g_ArpFw_ShareMem->NotifyPacket.AttachCount = 1; g_ArpFw_ShareMem->NotifyPacket.AttachType = AttachType; g_ArpFw_ShareMem->NotifyPacket.SendPacket = FALSE; g_ArpFw_ShareMem->NotifyPacket.WanPacket = FALSE; RtlCopyMemory((PVOID)&g_ArpFw_ShareMem->NotifyPacket.ArpPacket, ArpPacket,sizeof(ARP_PACKET)); SetUserShareEvent(&g_NotifyEvent); } NdisReleaseSpinLock(&GlobalLock); } // return this packet if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags)) { ReturnFlags = 0; if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags)) { NDIS_SET_RETURN_FLAG(ReturnFlags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL); } NdisFReturnNetBufferLists(pFilter->FilterHandle, NetBufferLists, ReturnFlags); } // -- } while (FALSE); DEBUGP(DL_TRACE, ("<===ReceiveNetBufferList: Flags = %8x.\n", ReceiveFlags)); }
VOID NdisprotReceiveNetBufferLists( IN NDIS_HANDLE ProtocolBindingContext, IN PNET_BUFFER_LIST pNetBufferLists, IN NDIS_PORT_NUMBER PortNumber, IN ULONG NumberOfNetBufferLists, IN ULONG ReceiveFlags ) /*++ Routine Description: Protocol entry point called by NDIS if the driver below uses NDIS 6 net buffer list indications. If the miniport allows us to hold on to this net buffer list, we use it as is, otherwise we make a copy. Arguments: ProtocolBindingContext - pointer to open context pNetBufferLists - a list of the Net Buffer lists being indicated up. PortNumber - Port on which the Net Bufer list was received NumberOfNetBufferLists - the number of NetBufferLists in this indication ReceiveFlags - indicates whether the NetBufferLists can be pended in the protocol driver. Return Value: --*/ { PNDISPROT_OPEN_CONTEXT pOpenContext; PMDL pMdl = NULL; UINT BufferLength; PNDISPROT_ETH_HEADER pEthHeader = NULL; PNET_BUFFER_LIST pCopyNetBufList; PUCHAR pCopyBuf; ULONG TotalLength; ULONG BytesCopied; PNET_BUFFER_LIST pNetBufList; PNET_BUFFER_LIST pNetBufListOrig = NULL; PNET_BUFFER_LIST pNextNetBufList; PNET_BUFFER_LIST pReturnNetBufList = NULL; PNET_BUFFER_LIST pLastReturnNetBufList = NULL; NTSTATUS NtStatus; BOOLEAN bAcceptedReceive; ULONG Offset; ULONG ReturnFlags = 0; BOOLEAN DispatchLevel; BOOLEAN NoReadIRP = FALSE; UNREFERENCED_PARAMETER(PortNumber); UNREFERENCED_PARAMETER(NumberOfNetBufferLists); pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext; if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags)) { NDIS_SET_RETURN_FLAG(ReturnFlags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL); } NPROT_STRUCT_ASSERT(pOpenContext, oc); if ((pOpenContext->State == NdisprotPausing) || (pOpenContext->State == NdisprotPaused)) { if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags) == TRUE) { NdisReturnNetBufferLists(pOpenContext->BindingHandle, pNetBufferLists, ReturnFlags); } return; } pNetBufList = pNetBufferLists; while (pNetBufList != NULL) { pNextNetBufList = NET_BUFFER_LIST_NEXT_NBL (pNetBufList); NBL_CLEAR_PROT_RSVD_FLAG(pNetBufList, NBL_PROT_RSVD_FLAGS); bAcceptedReceive = FALSE; // // Get first MDL and data length in the list // pMdl = NET_BUFFER_CURRENT_MDL(NET_BUFFER_LIST_FIRST_NB(pNetBufList)); TotalLength = NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(pNetBufList)); Offset = NET_BUFFER_CURRENT_MDL_OFFSET(NET_BUFFER_LIST_FIRST_NB(pNetBufList)); BufferLength = 0; do { ASSERT(pMdl != NULL); if (pMdl) { NdisQueryMdl( pMdl, &pEthHeader, &BufferLength, NormalPagePriority); } if (pEthHeader == NULL) { // // The system is low on resources. Set up to handle failure // below. // BufferLength = 0; break; } if (BufferLength == 0) { break; } ASSERT(BufferLength > Offset); BufferLength -= Offset; pEthHeader = (PNDISPROT_ETH_HEADER)((PUCHAR)pEthHeader + Offset); if (BufferLength < sizeof(NDISPROT_ETH_HEADER)) { DEBUGP(DL_WARN, ("ReceiveNetBufferList: Open %p, runt nbl %p, first buffer length %d\n", pOpenContext, pNetBufList, BufferLength)); break; } // // Check the EtherType. If the Ether type indicates presence of // a tag, then the "real" Ether type is 4 bytes further down. // if (pEthHeader->EthType == NPROT_8021P_TAG_TYPE) { USHORT UNALIGNED *pEthType; if (BufferLength < (sizeof(NDISPROT_ETH_HEADER) + 4)) { break; } pEthType = (USHORT UNALIGNED *)((PUCHAR)&pEthHeader->EthType + 4); if (*pEthType != Globals.EthType) { break; } } else if (pEthHeader->EthType != Globals.EthType) { break; } bAcceptedReceive = TRUE; DEBUGP(DL_LOUD, ("ReceiveNetBufferList: Open %p, interesting nbl %p\n", pOpenContext, pNetBufList)); // // If the miniport is out of resources, we can't queue // this list of net buffer list - make a copy if this is so. // DispatchLevel = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags); NoReadIRP = NPROT_IS_LIST_EMPTY(&pOpenContext->PendedReads); if (NoReadIRP || NDIS_TEST_RECEIVE_CANNOT_PEND(ReceiveFlags)) { bAcceptedReceive = FALSE; pCopyNetBufList = ndisprotAllocateReceiveNetBufferList( pOpenContext, TotalLength, &pCopyBuf); if (pCopyNetBufList == NULL) { DEBUGP(DL_FATAL, ("ReceiveNetBufferList: Open %p, failed to" " alloc copy, %d bytes\n", pOpenContext, TotalLength)); break; } NBL_SET_PROT_RSVD_FLAG(pCopyNetBufList, NPROT_ALLOCATED_NBL); // // Copy the data to the new allocated NetBufferList // NtStatus = NdisCopyFromNetBufferToNetBuffer(NET_BUFFER_LIST_FIRST_NB(pCopyNetBufList), 0, TotalLength, NET_BUFFER_LIST_FIRST_NB(pNetBufList), 0, &BytesCopied); if (NtStatus != STATUS_SUCCESS) { DEBUGP(DL_FATAL, ("ReceiveNetBufferList: Open %p, failed to" " copy the data, %d bytes\n", pOpenContext, TotalLength)); // // Free the NetBufferList and memory allocate before // ndisprotFreeReceiveNetBufferList(pOpenContext, pCopyNetBufList, DispatchLevel); break; } NPROT_ASSERT(BytesCopied == TotalLength); // // The other members of NET_BUFFER_DATA structure are already initialized properly during allocation. // NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(pCopyNetBufList)) = BytesCopied; // //save a copy for no Read IRP case // if(NoReadIRP) { pNetBufListOrig = pNetBufList; } pNetBufList = pCopyNetBufList; } // // Queue this up and service any pending Read IRPs. // ndisprotQueueReceiveNetBufferList(pOpenContext, pNetBufList, DispatchLevel); } while (FALSE); // // Ndisprot is not interested this NetBufferList, return the // NetBufferList back to the miniport if the miniport gave us // ownership of it // if ((bAcceptedReceive == FALSE) && (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags) == TRUE)) { // Restore pNetBufList if it was overwritten earlier if (pNetBufListOrig != NULL) { pNetBufList = pNetBufListOrig; pNetBufListOrig = NULL; } if (pReturnNetBufList == NULL) { pReturnNetBufList = pNetBufList; } else { NET_BUFFER_LIST_NEXT_NBL(pLastReturnNetBufList) = pNetBufList; } pLastReturnNetBufList = pNetBufList; NET_BUFFER_LIST_NEXT_NBL(pNetBufList) = NULL; } pNetBufList = pNextNetBufList; } // end of the for loop if (pReturnNetBufList != NULL) { NdisReturnNetBufferLists(pOpenContext->BindingHandle, pReturnNetBufList, ReturnFlags); } }
// NDIS packet reception notification procedure void SlNdisReceiveNetBufferListsProc(NDIS_HANDLE protocol_binding_context, NET_BUFFER_LIST *net_buffer_lists, NDIS_PORT_NUMBER port_number, ULONG NumberOfNetBufferLists, ULONG receive_flags) { SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context; UINT i; UINT return_flags = 0; NET_BUFFER_LIST *nbl; UCHAR *tmp_buffer; UINT tmp_size; if (net_buffer_lists == NULL || NumberOfNetBufferLists == 0) { return; } if (a->AdapterHandle2 == NULL) { a->AdapterHandle2 = a->AdapterHandle; } if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(receive_flags)) { NDIS_SET_RETURN_FLAG(return_flags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL); } if (a->Halt || a->Device == NULL || a->Device->Halting || a->Ready == false || a->AdapterHandle == NULL) { goto LABEL_CLEANUP; } tmp_buffer = a->TmpBuffer; tmp_size = sizeof(a->TmpBuffer); nbl = net_buffer_lists; SlLockList(a->Device->FileList); { if (a->Halt == false) { for (i = 0;i < SL_LIST_NUM(a->Device->FileList);i++) { // Lock the receive queue SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i); SlLock(f->RecvLock); } while (nbl != NULL) { NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl); bool is_vlan = false; UCHAR vlan_tag[2]; if (NET_BUFFER_LIST_INFO(nbl, Ieee8021QNetBufferListInfo) != 0) { NDIS_NET_BUFFER_LIST_8021Q_INFO qinfo; qinfo.Value = NET_BUFFER_LIST_INFO(nbl, Ieee8021QNetBufferListInfo); if (qinfo.TagHeader.VlanId != 0) { USHORT tag_us; is_vlan = true; tag_us = (qinfo.TagHeader.UserPriority & 0x07 << 13) | (qinfo.TagHeader.CanonicalFormatId & 0x01 << 12) | (qinfo.TagHeader.VlanId & 0x0FFF); vlan_tag[0] = ((UCHAR *)(&tag_us))[1]; vlan_tag[1] = ((UCHAR *)(&tag_us))[0]; } } while (nb != NULL) { UINT size = NET_BUFFER_DATA_LENGTH(nb); if (size >= 14 && size <= tmp_size && size <= (UINT)((is_vlan == false) ? SL_MAX_PACKET_SIZE : (SL_MAX_PACKET_SIZE - 4))) { UCHAR *ptr = NdisGetDataBuffer(nb, size, tmp_buffer, 1, 0); if (ptr != NULL) { // Insert the queue to all waiting files for (i = 0;i < SL_LIST_NUM(a->Device->FileList);i++) { SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i); if (f->NumRecvPackets < SL_MAX_PACKET_QUEUED) { SL_PACKET *q = SlMalloc(sizeof(SL_PACKET)); if (is_vlan == false) { // Normal packet SlCopy(q->Data, ptr, size); q->Size = size; } else { // Insert a tag in the case of IEEE802.1Q packet SlCopy(q->Data, ptr, 12); q->Data[12] = 0x81; q->Data[13] = 0x00; SlCopy(&q->Data[14], vlan_tag, 2); SlCopy(&q->Data[16], &ptr[12], size - 12); q->Size = size + 4; } q->Next = NULL; if (f->RecvPacketHead == NULL) { f->RecvPacketHead = q; } else { f->RecvPacketTail->Next = q; } f->RecvPacketTail = q; f->NumRecvPackets++; } } } } nb = NET_BUFFER_NEXT_NB(nb); } nbl = NET_BUFFER_LIST_NEXT_NBL(nbl); } // Hit the event for (i = 0;i < SL_LIST_NUM(a->Device->FileList);i++) { SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i); // Unlock the receive queue SlUnlock(f->RecvLock); SlSet(f->Event); } } } SlUnlockList(a->Device->FileList); LABEL_CLEANUP: if (NDIS_TEST_RECEIVE_CAN_PEND(receive_flags)) { NdisReturnNetBufferLists(a->AdapterHandle2, net_buffer_lists, return_flags); } }