NDIS_STATUS IgmpPktInfoQuery( IN PRTMP_ADAPTER pAd, IN PUCHAR pSrcBufVA, IN PNDIS_PACKET pPacket, IN UCHAR FromWhichBSSID, OUT INT *pInIgmpGroup, OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry) { if(IS_MULTICAST_MAC_ADDR(pSrcBufVA)) { INT32 ExcludedGroupType = -1; UINT16 EtherType = ntohs(*((UINT16 *)(pSrcBufVA + 12))); if (EtherType == ETH_P_IPV6) { ExcludedGroupType = IPv6MulticastFilterExcluded(pSrcBufVA); } else if(EtherType == ETH_P_IP) { ExcludedGroupType = IPv4MulticastFilterExcluded(pSrcBufVA); } if (ExcludedGroupType) { *ppGroupEntry = NULL; if (ExcludedGroupType == 1) *pInIgmpGroup = IGMP_PKT; } else if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pSrcBufVA, get_netdev_from_bssid(pAd, FromWhichBSSID))) == NULL) { RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } else *pInIgmpGroup = IGMP_IN_GROUP; } else if (IS_BROADCAST_MAC_ADDR(pSrcBufVA)) { PUCHAR pDstIpAddr = pSrcBufVA + 30; /* point to Destination of Ip address of IP header. */ UCHAR GroupMacAddr[6]; PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr; ConvertMulticastIP2MAC(pDstIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pGroupMacAddr, get_netdev_from_bssid(pAd, FromWhichBSSID))) != NULL) { *pInIgmpGroup = IGMP_IN_GROUP; } } return NDIS_STATUS_SUCCESS; }
NDIS_STATUS IgmpPktInfoQuery( IN PRTMP_ADAPTER pAd, IN PUCHAR pSrcBufVA, IN PNDIS_PACKET pPacket, IN struct wifi_dev *wdev, OUT INT *pInIgmpGroup, OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry) { if(IS_MULTICAST_MAC_ADDR(pSrcBufVA)) { BOOLEAN IgmpMldPkt = FALSE; PUCHAR pIpHeader = pSrcBufVA + 12; if(ntohs(*((UINT16 *)(pIpHeader))) == ETH_P_IPV6) IgmpMldPkt = IPv6MulticastFilterExcluded(pSrcBufVA, pIpHeader); else IgmpMldPkt = isIgmpPkt(pSrcBufVA, pIpHeader); if (IgmpMldPkt) { *ppGroupEntry = NULL; *pInIgmpGroup = IGMP_PKT; } else if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pSrcBufVA, wdev->if_dev)) == NULL) { RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } else *pInIgmpGroup = IGMP_IN_GROUP; } else if (IS_BROADCAST_MAC_ADDR(pSrcBufVA)) { PUCHAR pDstIpAddr = pSrcBufVA + 30; /* point to Destination of Ip address of IP header. */ UCHAR GroupMacAddr[6]; PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr; ConvertMulticastIP2MAC(pDstIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pGroupMacAddr, wdev->if_dev)) != NULL) { *pInIgmpGroup = IGMP_IN_GROUP; } } return NDIS_STATUS_SUCCESS; }
/* ========================================================================== Description: Add and new entry into MAC table ========================================================================== */ BOOLEAN MulticastFilterTableInsertEntry( IN PRTMP_ADAPTER pAd, IN PUCHAR pGrpId, IN PUCHAR pMemberAddr, IN PNET_DEV dev, IN MulticastFilterEntryType type) { UCHAR HashIdx; int i; MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL, *pCurrEntry, *pPrevEntry; PMEMBER_ENTRY pMemberEntry; PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable; if (pMulticastFilterTable == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__)); return FALSE; } /* if FULL, return */ if (pMulticastFilterTable->Size >= MAX_LEN_OF_MULTICAST_FILTER_TABLE) { DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table full. max-entries = %d\n", __FUNCTION__, MAX_LEN_OF_MULTICAST_FILTER_TABLE)); return FALSE; } /* check the rule is in table already or not. */ if ((pEntry = MulticastFilterTableLookup(pMulticastFilterTable, pGrpId, dev))) { /* doesn't indicate member mac address. */ if(pMemberAddr == NULL) { return FALSE; } pMemberEntry = (PMEMBER_ENTRY)pEntry->MemberList.pHead; while (pMemberEntry) { if (MAC_ADDR_EQUAL(pMemberAddr, pMemberEntry->Addr)) { DBGPRINT(RT_DEBUG_ERROR, ("%s: already in Members list.\n", __FUNCTION__)); return FALSE; } pMemberEntry = pMemberEntry->pNext; } } RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); do { ULONG Now; /* the multicast entry already exist but doesn't include the member yet. */ if (pEntry != NULL && pMemberAddr != NULL) { InsertIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); break; } /* allocate one MAC entry */ for (i = 0; i < MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++) { /* pick up the first available vacancy */ pEntry = &pMulticastFilterTable->Content[i]; NdisGetSystemUpTime(&Now); if ((pEntry->Valid == TRUE) && (pEntry->type == MCAT_FILTER_DYNAMIC) && ((Now - pEntry->lastTime) > IGMPMAC_TB_ENTRY_AGEOUT_TIME)) { PMULTICAST_FILTER_TABLE_ENTRY pHashEntry; HashIdx = MULTICAST_ADDR_HASH_INDEX(pEntry->Addr); pHashEntry = pMulticastFilterTable->Hash[HashIdx]; if ((pEntry->net_dev == pHashEntry->net_dev) && MAC_ADDR_EQUAL(pEntry->Addr, pHashEntry->Addr)) { pMulticastFilterTable->Hash[HashIdx] = pHashEntry->pNext; pMulticastFilterTable->Size --; DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 1 - Total= %d\n", pMulticastFilterTable->Size)); } else { while (pHashEntry->pNext) { pPrevEntry = pHashEntry; pHashEntry = pHashEntry->pNext; if ((pEntry->net_dev == pHashEntry->net_dev) && MAC_ADDR_EQUAL(pEntry->Addr, pHashEntry->Addr)) { pPrevEntry->pNext = pHashEntry->pNext; pMulticastFilterTable->Size --; DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size)); break; } } } pEntry->Valid = FALSE; DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList); } if (pEntry->Valid == FALSE) { NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY)); pEntry->Valid = TRUE; COPY_MAC_ADDR(pEntry->Addr, pGrpId); pEntry->net_dev = dev; NdisGetSystemUpTime(&Now); pEntry->lastTime = Now; pEntry->type = type; initList(&pEntry->MemberList); if (pMemberAddr != NULL) InsertIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr); pMulticastFilterTable->Size ++; DBGPRINT(RT_DEBUG_TRACE, ("MulticastFilterTableInsertEntry -IF(%s) allocate entry #%d, Total= %d\n", RTMP_OS_NETDEV_GET_DEVNAME(dev), i, pMulticastFilterTable->Size)); break; } } /* add this MAC entry into HASH table */ if (pEntry) { HashIdx = MULTICAST_ADDR_HASH_INDEX(pGrpId); if (pMulticastFilterTable->Hash[HashIdx] == NULL) { pMulticastFilterTable->Hash[HashIdx] = pEntry; } else { pCurrEntry = pMulticastFilterTable->Hash[HashIdx]; while (pCurrEntry->pNext != NULL) pCurrEntry = pCurrEntry->pNext; pCurrEntry->pNext = pEntry; } } }while(FALSE); RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); return TRUE; }