/* dwRetval = MgmAddGroupMembershipEntry(g_MgmIgmprtrHandle, 0, 0, pge->Group, 0, IfIndex, NHAddr); dwRetval = MgmDeleteGroupMembershipEntry(g_MgmIgmprtrHandle, 0, 0, pge->Group, 0, pite->IfIndex, NHAddr); */ //============================================================================= // Copyright (c) 1997 Microsoft Corporation // File: table2.c // // Abstract: // This module implements some of the routines associated with getting // entries. and some debug routines // // GetRasClientByAddr, GetIfByIndex, InsertIfByAddr, MatchIpAddrBinding, // GetGroupFromGroupTable, GetGIFromGIList, GetGIFromGIList. // // DebugPrintGIList, DebugPrintGroups, DebugPrintLocks // // Author: K.S.Lokesh (lokeshs@) 11-1-97 // // Revision History: //============================================================================= #include "pchigmp.h" #pragma hdrstop //------------------------------------------------------------------------------ // _GetRasClientByAddr // Returns pointer to Ras clients RasTableEntry //------------------------------------------------------------------------------ PRAS_TABLE_ENTRY GetRasClientByAddr ( DWORD NHAddr, PRAS_TABLE prt ) { PRAS_TABLE_ENTRY pite = NULL; PLIST_ENTRY phead, ple; PRAS_TABLE_ENTRY prte=NULL; phead = &prt->HashTableByAddr[RAS_HASH_VALUE(NHAddr)]; for (ple=phead->Flink; ple!=phead; ple=ple->Flink) { prte = CONTAINING_RECORD(ple, RAS_TABLE_ENTRY, HTLinkByAddr); if (prte->NHAddr == NHAddr) { break; } } return (ple == phead) ? NULL: prte; } //------------------------------------------------------------------------------ // _GetIfByIndex // // returns the interface with the given index. // assumes the interface bucket is either read or write locked //------------------------------------------------------------------------------ PIF_TABLE_ENTRY GetIfByIndex( DWORD IfIndex ) { PIF_TABLE_ENTRY pite = NULL; PLIST_ENTRY phead, ple; phead = &g_pIfTable->HashTableByIndex[IF_HASH_VALUE(IfIndex)]; for (ple=phead->Flink; ple!=phead; ple=ple->Flink) { pite = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, HTLinkByIndex); if (pite->IfIndex == IfIndex) { break; } } return (ple == phead) ? NULL: pite; } //------------------------------------------------------------------------------ // _InsertIfByAddr // // inserts the activated interface into the list of interfaces sorted by address. // assumes the table is locked for writing //------------------------------------------------------------------------------ DWORD InsertIfByAddr( PIF_TABLE_ENTRY piteInsert ) { PIF_TABLE_ENTRY pite; INT cmp, cmp1; DWORD InsertAddr; PLIST_ENTRY phead, ple; phead = &g_pIfTable->ListByAddr; InsertAddr = piteInsert->IpAddr; // // search for the insertion point // for (ple=phead->Flink; ple!=phead; ple=ple->Flink) { pite = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, LinkByAddr); if ( (cmp1 = INET_CMP(InsertAddr, pite->IpAddr, cmp)) < 0) break; // // return error if there are duplicate addresses. // no error for unnumbered interfaces, ie for addr==0 // else if ( (cmp1==0) && (InsertAddr!=0) ) return ERROR_ALREADY_EXISTS; } InsertTailList(ple, &piteInsert->LinkByAddr); return NO_ERROR; } //------------------------------------------------------------------------------ // MatchIpAddrBinding // // finds if the interface is bound to any address equal to IpAddr // //------------------------------------------------------------------------------ BOOL MatchIpAddrBinding( PIF_TABLE_ENTRY pite, DWORD IpAddr ) { PIGMP_IP_ADDRESS paddr; DWORD i; PIGMP_IF_BINDING pib; pib = pite->pBinding; paddr = IGMP_BINDING_FIRST_ADDR(pib); for (i=0; iAddrCount; i++,paddr++) { if (IpAddr==paddr->IpAddr) break; } return (iAddrCount)? TRUE: FALSE; } //------------------------------------------------------------------------------ // _InsertInGroupsList // // Inserts a newly created group in the New or Main group list. // Calls: May call _MergeGroupLists() to merge the New and Main lists //------------------------------------------------------------------------------ VOID InsertInGroupsList ( PGROUP_TABLE_ENTRY pgeNew ) { PGROUP_TABLE_ENTRY pgeTmp; PLIST_ENTRY pHead, ple; DWORD GroupLittleEndian = pgeNew->GroupLittleEndian; BOOL bInsertInNew; // // insert the group in main list if less than 20 entries, else insert in // the New list // bInsertInNew = (g_Info.CurrentGroupMemberships > 20); pHead = bInsertInNew ? &g_pGroupTable->ListByGroupNew : &g_pGroupTable->ListByGroup.Link; for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) { pgeTmp = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, LinkByGroup); if (GroupLittleEndianGroupLittleEndian) break; } InsertTailList(ple, &pgeNew->LinkByGroup); if (bInsertInNew) { // increment count of g_pGroupTable->NumGroupsInNewList++; // // merge lists if required // if (MERGE_GROUP_LISTS_REQUIRED()) { MergeGroupLists(); } } return; } //------------------------------------------------------------------------------ // _InsertInIfGroupsList // Inserts a newly created group in the New or Main group list. // Calls: May call MergeIfGroupLists() to merge the New and Main lists //------------------------------------------------------------------------------ VOID InsertInIfGroupsList ( PIF_TABLE_ENTRY pite, PGI_ENTRY pgiNew ) { PGI_ENTRY pgiTmp; PLIST_ENTRY pHead, ple; DWORD GroupLittleEndian = pgiNew->pGroupTableEntry->GroupLittleEndian; BOOL bInsertInNew; // // insert the group in main list if less than 20 entries, else insert in // the New list // bInsertInNew = (pite->Info.CurrentGroupMemberships > 20); pHead = bInsertInNew ? &pite->ListOfSameIfGroupsNew : &pite->ListOfSameIfGroups; for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) { pgiTmp = CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameIfGroups); if (GroupLittleEndianpGroupTableEntry->GroupLittleEndian) break; } InsertTailList(ple, &pgiNew->LinkBySameIfGroups); if (bInsertInNew) { // increment count of pite->NumGIEntriesInNewList++; // // merge lists if required // if (MERGE_IF_GROUPS_LISTS_REQUIRED(pite)) { MergeIfGroupsLists(pite); } } return; }//end _InsertInIfGroupsList //------------------------------------------------------------------------------ // InsertInProxyList //------------------------------------------------------------------------------ VOID InsertInProxyList ( PIF_TABLE_ENTRY pite, PPROXY_GROUP_ENTRY pNewProxyEntry ) { PPROXY_GROUP_ENTRY pTmpProxyEntry; PLIST_ENTRY pHead, ple; DWORD GroupLittleEndian = pNewProxyEntry->GroupLittleEndian; BOOL bInsertInNew; // // dont insert in new list if less than 20 entries, else insert in // the New list // bInsertInNew = (pite->NumGIEntriesInNewList > 20); pHead = bInsertInNew ? &pite->ListOfSameIfGroupsNew : &pite->ListOfSameIfGroups; for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) { pTmpProxyEntry = CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY, LinkBySameIfGroups); if (GroupLittleEndianGroupLittleEndian) break; } InsertTailList(ple, &pNewProxyEntry->LinkBySameIfGroups); if (bInsertInNew) { // increment count of pite->NumGIEntriesInNewList++; // // merge lists if required // if (MERGE_PROXY_LISTS_REQUIRED(pite)) { MergeProxyLists(pite); } } return; }//end _InsertInProxyList //------------------------------------------------------------------------------ // _GetGroupFromGroupTable // Returns the group entry. If group entry does not exist and bCreateFlag is // set, then it will take a group-list lock and create a new entry. // Locks: // Assumes lock on group bucket. // takes group-list lock if new group is being created. // If read only, assumes lock on group list //------------------------------------------------------------------------------ PGROUP_TABLE_ENTRY GetGroupFromGroupTable ( DWORD Group, BOOL *bCreate, //set to true if new one created LONGLONG llCurrentTime ) { PGROUP_TABLE_ENTRY pge; //group table entry PLIST_ENTRY pHead, ple; DWORD Error = NO_ERROR; DWORD bCreateLocal; DWORD GroupLittleEndian = NETWORK_TO_LITTLE_ENDIAN(Group); bCreateLocal = (bCreate==NULL) ? FALSE : *bCreate; if (llCurrentTime==0) llCurrentTime = GetCurrentIgmpTime(); BEGIN_BREAKOUT_BLOCK1 { // get pointer to the head of the group bucket pHead = &g_pGroupTable->HashTableByGroup[GROUP_HASH_VALUE(Group)].Link; // search for the group for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) { pge = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, HTLinkByGroup); if (GroupLittleEndian>=pge->GroupLittleEndian) { break; } } // // group entry not found // if ( (ple==pHead) || (pge->GroupLittleEndian!=GroupLittleEndian) ) { // // create and initialize new entry // if (bCreateLocal) { bCreateLocal = TRUE; pge = IGMP_ALLOC(sizeof(GROUP_TABLE_ENTRY), 0x800010,0xaaaa); PROCESS_ALLOC_FAILURE2(pge, "Error %d allocation %d bytes for Group table entry", Error, sizeof(GROUP_TABLE_ENTRY), GOTO_END_BLOCK1); InsertTailList(ple, &pge->HTLinkByGroup); InitializeListHead(&pge->LinkByGroup); pge->Group = Group; pge->GroupLittleEndian = GroupLittleEndian; pge->NumVifs = 0; pge->Status = CREATED_FLAG; pge->GroupUpTime = llCurrentTime; // // insert it into the list of all groups after taking the group // list lock // { PGROUP_TABLE_ENTRY pgeTmp; PLIST_ENTRY pHeadTmp, pleTmp; // take group list lock ACQUIRE_GROUP_LIST_LOCK("_GetGroupFromGroupTable"); // initialize GI list head InitializeListHead(&pge->ListOfGIs); // insert in group list InsertInGroupsList(pge); // release group lock RELEASE_GROUP_LIST_LOCK("_GetGroupFromGroupTable"); } // update statistics InterlockedIncrement(&g_Info.CurrentGroupMemberships); InterlockedIncrement(&g_Info.GroupMembershipsAdded); } // not found group, and do not create new group. So return NULL. else { pge = NULL; GOTO_END_BLOCK1; } } // // group entry found // else { bCreateLocal = FALSE; } } END_BREAKOUT_BLOCK1; if (bCreate!=NULL) *bCreate = bCreateLocal; #if DBG DebugPrintGroupsList(1); #endif return pge; } //end _GetGroupFromGroupTable //------------------------------------------------------------------------------ // _GetGIFromGIList // // returns the GI entry if it exists. If the bCreate flag is set, then it creates // a new GI entry if it does not exist. // // Locks: Assumes shared interface lock. If ras interface, also assumes shared // Ras interface lock. // Assumes lock on group bucket. // Takes IF_GROUP_LIST_LOCK if new entry is to be created. // On return: bCreate is set to TRUE if a new entry was created //------------------------------------------------------------------------------ PGI_ENTRY GetGIFromGIList ( PGROUP_TABLE_ENTRY pge, PIF_TABLE_ENTRY pite, DWORD dwInputSrcAddr, //used for NHAddr BOOL bStaticGroup, BOOL *bCreate, LONGLONG llCurrentTime ) { DWORD IfIndex = pite->IfIndex; BOOL bRasClient; PLIST_ENTRY pHead, ple; PGI_ENTRY pgie; PRAS_TABLE_ENTRY prte; PRAS_TABLE prt; BOOL bRasNewGroup = TRUE; //true if 1st ras group DWORD NHAddr; DWORD Error = NO_ERROR, dwRetval, i; BOOL bFound = FALSE, bCreateLocal; Trace2(ENTER1, "Entering _GetGIFromGIList() IfIndex(%0x) Group(%d.%d.%d.%d)", IfIndex, PRINT_IPADDR(pge->Group)); //DebugPrintIfGroups(pite,0);//deldel bCreateLocal = (bCreate==NULL) ? FALSE : *bCreate; if (llCurrentTime==0) llCurrentTime = GetCurrentIgmpTime(); BEGIN_BREAKOUT_BLOCK1 { // // find out if ras-server. // bRasClient = IS_RAS_SERVER_IF(pite->IfType); if (bRasClient) { prt = pite->pRasTable; // get ras client prte = GetRasClientByAddr(dwInputSrcAddr, prt); } NHAddr = bRasClient ? dwInputSrcAddr : 0; // // search for GI entry // pHead = &pge->ListOfGIs; for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) { pgie = CONTAINING_RECORD(ple, GI_ENTRY, LinkByGI); if (pgie->IfIndex>IfIndex) break; // // GI with same interface index // else if (pgie->IfIndex==IfIndex) { // the GI entry might belong to some interface being deleted if ( (pite!=pgie->pIfTableEntry) ||(IS_IF_DELETED(pgie->pIfTableEntry)) ) continue; //multiple entries for ras clients if (bRasClient) { // // I set this even if the ras client is marked to be deleted // bRasNewGroup = FALSE; // the GI entry might belong to some other ras interface // being deleted if ( (prte!=pgie->pRasTableEntry) || (pgie->pRasTableEntry->Status&DELETED_FLAG) ) continue; if (pgie->NHAddr>dwInputSrcAddr) { break; } // found GI entry for ras interface else if (pgie->NHAddr==dwInputSrcAddr) { bFound = TRUE; break; } } // found GI entry for non ras interface else { bFound = TRUE; break; } } }// end for loop:search through list of GIs // // GIentry not found // if ( !bFound) { // dont create new GI entry. Hence, return NULL if (!bCreateLocal) { pgie = NULL; GOTO_END_BLOCK1; } // // create and initialize new GI-entry // pgie = IGMP_ALLOC_AND_ZERO(sizeof(GI_ENTRY), 0x800011, pite->IfIndex); PROCESS_ALLOC_FAILURE2(pgie, "Error %d allocating %d bytes for group-interface entry", Error, sizeof(GI_ENTRY), GOTO_END_BLOCK1); pgie->IfIndex = IfIndex; pgie->Status = CREATED_FLAG; pgie->bRasClient = bRasClient; // insert in GI list InsertTailList(ple, &pgie->LinkByGI); // // set back pointers to the interface entry, and group entry // pgie->pIfTableEntry = pite; pgie->pGroupTableEntry = pge; // // Take lock on Interface-Group List before inserting into it // for ras client, insert it into ras client list also // ACQUIRE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_GetGIFromGIList"); // insert in ras client list if (bRasClient) { PLIST_ENTRY pleTmp, pHeadRasClient; PGI_ENTRY pgieRasClient; pHeadRasClient = &prte->ListOfSameClientGroups; for (pleTmp=pHeadRasClient->Flink; pleTmp!=pHeadRasClient; pleTmp=pleTmp->Flink) { pgieRasClient = CONTAINING_RECORD(pleTmp, GI_ENTRY, LinkBySameClientGroups); if (pge->Group < pgieRasClient->pGroupTableEntry->Group) break; } InsertTailList(pleTmp, &pgie->LinkBySameClientGroups); } InsertInIfGroupsList(pite, pgie); RELEASE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_GetGIFromGIList"); // // if ras // pgie->NHAddr = (bRasClient)? dwInputSrcAddr : 0; pgie->pRasTableEntry = (bRasClient)? prte : NULL; // // initialize GroupMembershipTimer // pgie->GroupMembershipTimer.Function = T_MembershipTimer; pgie->GroupMembershipTimer.Timeout = pite->Config.GroupMembershipTimeout; pgie->GroupMembershipTimer.Context = &pgie->GroupMembershipTimer.Context; pgie->GroupMembershipTimer.Status = TIMER_STATUS_CREATED; // // initialize LastMemQueryTimer timer // pgie->LastMemQueryCount = 0; //last member countdown inactive pgie->LastMemQueryTimer.Function = T_LastMemQueryTimer; pgie->LastMemQueryTimer.Context = &pgie->LastMemQueryTimer.Context; pgie->LastMemQueryTimer.Status = TIMER_STATUS_CREATED; // // initialize the LastVer1ReportTimer // the timeout value is set to GroupMembership timeout pgie->LastVer1ReportTimer.Function = T_LastVer1ReportTimer; pgie->LastVer1ReportTimer.Timeout = pite->Config.GroupMembershipTimeout; pgie->LastVer1ReportTimer.Context = &pgie->LastVer1ReportTimer.Context; pgie->LastVer1ReportTimer.Status = TIMER_STATUS_CREATED; pgie->LastVer2ReportTimer.Function = T_LastVer2ReportTimer; pgie->LastVer2ReportTimer.Timeout = pite->Config.GroupMembershipTimeout; pgie->LastVer2ReportTimer.Context = &pgie->LastVer2ReportTimer.Context; pgie->LastVer2ReportTimer.Status = TIMER_STATUS_CREATED; // set version based on current interface version pgie->Version = (IS_IF_VER1(pite)) ? 1 : ((IS_IF_VER2(pite))?2:3); // // initialize GI_INFO // ZeroMemory(&pgie->Info, sizeof(GI_INFO)); pgie->Info.GroupUpTime = llCurrentTime; if (!bStaticGroup) { pgie->Info.GroupExpiryTime = llCurrentTime + CONFIG_TO_SYSTEM_TIME(pite->Config.GroupMembershipTimeout); } pgie->Info.V1HostPresentTimeLeft = 0; pgie->Info.V2HostPresentTimeLeft = 0; pgie->Info.LastReporter = dwInputSrcAddr; // // v3 fields // pgie->V3InclusionList = (PLIST_ENTRY) IGMP_ALLOC(sizeof(LIST_ENTRY)*SOURCES_BUCKET_SZ, 0x800020, pite->IfIndex); PROCESS_ALLOC_FAILURE2(pgie->V3InclusionList, "Error %d allocating sources table:%d bytes", Error, sizeof(LIST_ENTRY)*SOURCES_BUCKET_SZ, GOTO_END_BLOCK1); for (i=0; iV3InclusionList[i]); InitializeListHead(&pgie->V3InclusionListSorted); pgie->NumSources = 0; pgie->FilterType = INCLUSION; InitializeListHead(&pgie->V3ExclusionList); InitializeListHead(&pgie->V3SourcesQueryList); pgie->V3SourcesQueryCount = 0; // V3SourcesQueryTimer pgie->V3SourcesQueryTimer.Function = T_V3SourcesQueryTimer; pgie->V3SourcesQueryTimer.Context = &pgie->V3SourcesQueryTimer.Context; pgie->V3SourcesQueryTimer.Status = TIMER_STATUS_CREATED; // set static group flag pgie->bStaticGroup = bStaticGroup; // // increment the count of number of If's for that group // I increment once for each virtual interface // InterlockedIncrement(&pge->NumVifs); if (!bRasClient||(bRasClient&bRasNewGroup) ) { InterlockedIncrement(&pite->Info.CurrentGroupMemberships); InterlockedIncrement(&pite->Info.GroupMembershipsAdded); } // // update stats for ras client // if ((bRasClient) && (g_Config.RasClientStats) ) { InterlockedIncrement(&prte->Info.CurrentGroupMemberships); InterlockedIncrement(&prte->Info.GroupMembershipsAdded); } // // Join the group to MGM // // call mgm to join the group only if the interface is // activated, enabled by mgm, either mprotocol exists or else // igmprtr is a querier on this interface if (CAN_ADD_GROUPS_TO_MGM(pite) && (pgie->bStaticGroup||!IS_IF_VER3(pite)) ) { MGM_ADD_GROUP_MEMBERSHIP_ENTRY(pite, NHAddr, 0, 0, pge->Group, 0xffffffff, MGM_JOIN_STATE_FLAG); } // // v3 no MGM calls, as I create an inclusion list with null members. // } // if GI entry not found // GI entry found else { if (bStaticGroup) pgie->bStaticGroup = TRUE; bCreateLocal = FALSE; } } END_BREAKOUT_BLOCK1; if (bCreate!=NULL) *bCreate = bCreateLocal; Trace0(LEAVE1, "Leaving _GetGIFromGIList()"); //Trace1(ENTER1, "GetGiFromGiList returned:%0x", (DWORD)pgie);//deldel return pgie; } //end _GetGIFromGIList //------------------------------------------------------------------------------ // _DebugPrintGIList //------------------------------------------------------------------------------ VOID DebugPrintGIList ( PGROUP_TABLE_ENTRY pge, LONGLONG llCurTime ) { PGI_ENTRY pgie; PLIST_ENTRY pHead, ple; pHead = &pge->ListOfGIs; for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) { pgie = CONTAINING_RECORD(ple, GI_ENTRY, LinkByGI); if (pgie->Status&IF_DELETED_FLAG) continue; // // GI info // Trace4(GROUP, "---If(%d: %d.%d.%d.%d) NHAddr(%d.%d.%d.%d) GroupMembershipTimer(%d sec)", pgie->IfIndex, PRINT_IPADDR(pgie->pIfTableEntry->IpAddr), PRINT_IPADDR(pgie->NHAddr), (pgie->GroupMembershipTimer.Timeout-llCurTime)/1000 ); // // if leave being processed // if (IS_TIMER_ACTIVE(pgie->LastMemQueryTimer)) { Trace2(GROUP, " *Leave received: LastMemQueryCount:%d LastMemQueryTimeLeft(%d ms)", pgie->LastMemQueryCount, (DWORD) (pgie->LastMemQueryTimer.Timeout-llCurTime) ); } } Trace0(GROUP, ""); return; } //------------------------------------------------------------------------------ // DebugPrintGroups //------------------------------------------------------------------------------ VOID APIENTRY DebugPrintGroups ( DWORD Flags ) { DWORD Group, i, j, k; DWORD IfIndex; PLIST_ENTRY pHead, ple; DWORD Count; PGROUP_TABLE_ENTRY pge; //group table entry LONGLONG llCurTime = GetCurrentIgmpTime(); j = 1; Trace0(GROUP, ""); for (i=0; iHashTableByGroup[i].Link; for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) { pge = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, HTLinkByGroup); // // print group info // Trace3(GROUP, "(%d) Group:%d.%d.%d.%d UpTime(%lu sec)", j++, PRINT_IPADDR(pge->Group), (llCurTime-pge->GroupUpTime)/1000); // print GI list DebugPrintGIList(pge, llCurTime); } RELEASE_GROUP_LOCK(i, "_DebugPrintGroups"); } return; } VOID DebugPrintIfGroups( PIF_TABLE_ENTRY pite, DWORD flag ) { PGI_ENTRY pgiTmp; PLIST_ENTRY pHead, ple; BOOL bInsertInNew; DWORD count=0; PPROXY_GROUP_ENTRY proxyge; ACQUIRE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_DebugPrintIfGroups"); Trace0(ERR, "---------------DebugPrintIfGroups---------------------"); Trace1(ERR, "Ipaddr: %d.%d.%d.%d", PRINT_IPADDR(pite->IpAddr) ); Trace1(ERR, "CurrentGroupMemberships: %d",pite->Info.CurrentGroupMemberships); pHead = &pite->ListOfSameIfGroups; for (ple=pHead->Flink; ple!=pHead && count<300; ple=ple->Flink) { if (!(flag&IGMP_IF_PROXY)) { pgiTmp = CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameIfGroups); Trace5(SOURCES, "%d: main list: %x:%x:%x: %d.%d.%d.%d", ++count, (ULONG_PTR)ple, (ULONG_PTR)ple->Flink, (ULONG_PTR)ple->Blink, PRINT_IPADDR(pgiTmp->pGroupTableEntry->Group)); } else { proxyge = CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY, LinkBySameIfGroups); Trace5(SOURCES, "%d: proxyMailList: %x:%x:%x: %d.%d.%d.%d", ++count, (ULONG_PTR)ple, (ULONG_PTR)ple->Flink, (ULONG_PTR)ple->Blink, PRINT_IPADDR(proxyge->Group)); } } pHead = &pite->ListOfSameIfGroupsNew; Trace1(ERR, "NumGIEntriesInNewList:%d", pite->NumGIEntriesInNewList); for (ple=pHead->Flink; ple!=pHead && count<300; ple=ple->Flink) { if (!(flag&IGMP_IF_PROXY)) { pgiTmp = CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameIfGroups); Trace5(ERR, "%d: NewList: %x:%x:%x: %d.%d.%d.%d", ++count, (ULONG_PTR)ple, (ULONG_PTR)ple->Flink, (ULONG_PTR)ple->Blink, PRINT_IPADDR(pgiTmp->pGroupTableEntry->Group)); } else { proxyge = CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY, LinkBySameIfGroups); Trace5(ERR, "%d: ProxyNewList: %x:%x:%x: %d.%d.%d.%d", ++count, (ULONG_PTR)ple, (ULONG_PTR)ple->Flink, (ULONG_PTR)ple->Blink, PRINT_IPADDR(proxyge->Group)); } } Trace0(ERR, "-------------------------------------------------------------"); RELEASE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_DebugPrintIfGroups"); //ASSERT(count<300);//deldel } DWORD APIENTRY DebugPrintLocks( ) { DWORD Group; Trace0(KSL, "QUEUEING WORKER THREAD TO DEBUGPRINTLOCKS"); QueueIgmpWorker(DebugPrintLocks, NULL); Trace0(KSL, "QUEUED WORKER THREAD TO DEBUGPRINTLOCKS"); return NO_ERROR; } VOID DebugPrintLists( PLIST_ENTRY pHead ) { DWORD count=0; PLIST_ENTRY ple; for (ple=pHead->Flink; (ple!=pHead)&&(count<16); ple=ple->Flink,count++) { Trace3(ERR, "ple:%lu ple->Flink:%lu: ple->Blink:%lu", ple, ple->Flink, ple->Blink); } } //------------------------------------------------------------------------------ // _ForcePrintGroupsList //------------------------------------------------------------------------------ VOID DebugForcePrintGroupsList ( DWORD Flags ) { BOOL bMain = FALSE; CHAR str[2][5] = {"new", "main"}; LIST_ENTRY *ple, *pHead; PGROUP_TABLE_ENTRY pge; if (g_Info.CurrentGroupMemberships > 40 && !(Flags&ENSURE_EMPTY) ) return; Trace0(ENTER1, "Entering _ForcePrintGroupsList()"); pHead = &g_pGroupTable->ListByGroupNew; if (Flags&ENSURE_EMPTY) { if (IsListEmpty(pHead)) return;// list empty as expected DbgPrint("Cleanup: Group Lists should be empty\n"); DbgBreakPoint(); } do { for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) { pge = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, LinkByGroup); Trace3(KSL, "%s-group list: <%d.%d.%d.%d> pge:%0x", str[bMain], PRINT_IPADDR(pge->Group), (ULONG_PTR)pge); if (!IS_MCAST_ADDR(pge->Group)) { #if DBG DbgBreakPoint(); #endif Trace0(ERR, "==============================================================="); Trace2(ERR, "bad group(%d.%d.%d.%d)(pge:%0x) while checking main-group", PRINT_IPADDR(pge->Group), (ULONG_PTR)pge); Trace0(ERR, "==============================================================="); return; } } if (!bMain) { pHead = &g_pGroupTable->ListByGroup.Link; bMain = TRUE; } else break; } while (1); Trace0(LEAVE1, "Leaving _ForcePrintGroupsList()"); } //------------------------------------------------------------------------------ // DebugPrintGroupsList //------------------------------------------------------------------------------ VOID DebugPrintGroupsList ( DWORD Flags ) { BOOL bMain = FALSE; CHAR str[2][5] = {"new", "main"}; LIST_ENTRY *ple, *pHead; PGROUP_TABLE_ENTRY pge; static DWORD StaticCount; BOOL bPrint = FALSE; if (StaticCount++==30) { bPrint = TRUE; StaticCount = 0; } if (g_Info.CurrentGroupMemberships > 40) return; pHead = &g_pGroupTable->ListByGroupNew; do { for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) { pge = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, LinkByGroup); //if ((Flags)&&(bPrint)) if (0) Trace3(KSL, "%s-group list: <%d.%d.%d.%d> pge:%0x", str[bMain], PRINT_IPADDR(pge->Group), (ULONG_PTR)pge); if (!IS_MCAST_ADDR(pge->Group)) { if (!bPrint) { DebugForcePrintGroupsList(1); return; } #if DBG DbgBreakPoint(); #endif Trace0(ERR, "==============================================================="); Trace2(ERR, "bad group(%d.%d.%d.%d)(pge:%0x) while checking main-group", PRINT_IPADDR(pge->Group), (ULONG_PTR)pge); Trace0(ERR, "==============================================================="); return; } } if (!bMain) { pHead = &g_pGroupTable->ListByGroup.Link; bMain = TRUE; } else break; } while (1); //Trace0(LEAVE1, "Leaving _PrintGroupsList()"); }