Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1185 lines
33 KiB

  1. /* dwRetval = MgmAddGroupMembershipEntry(g_MgmIgmprtrHandle, 0, 0,
  2. pge->Group, 0, IfIndex, NHAddr);
  3. dwRetval = MgmDeleteGroupMembershipEntry(g_MgmIgmprtrHandle, 0, 0, pge->Group,
  4. 0, pite->IfIndex, NHAddr);
  5. */
  6. //=============================================================================
  7. // Copyright (c) 1997 Microsoft Corporation
  8. // File: table2.c
  9. //
  10. // Abstract:
  11. // This module implements some of the routines associated with getting
  12. // entries. and some debug routines
  13. //
  14. // GetRasClientByAddr, GetIfByIndex, InsertIfByAddr, MatchIpAddrBinding,
  15. // GetGroupFromGroupTable, GetGIFromGIList, GetGIFromGIList.
  16. //
  17. // DebugPrintGIList, DebugPrintGroups, DebugPrintLocks
  18. //
  19. // Author: K.S.Lokesh (lokeshs@) 11-1-97
  20. //
  21. // Revision History:
  22. //=============================================================================
  23. #include "pchigmp.h"
  24. #pragma hdrstop
  25. //------------------------------------------------------------------------------
  26. // _GetRasClientByAddr
  27. // Returns pointer to Ras clients RasTableEntry
  28. //------------------------------------------------------------------------------
  29. PRAS_TABLE_ENTRY
  30. GetRasClientByAddr (
  31. DWORD NHAddr,
  32. PRAS_TABLE prt
  33. )
  34. {
  35. PRAS_TABLE_ENTRY pite = NULL;
  36. PLIST_ENTRY phead, ple;
  37. PRAS_TABLE_ENTRY prte=NULL;
  38. phead = &prt->HashTableByAddr[RAS_HASH_VALUE(NHAddr)];
  39. for (ple=phead->Flink; ple!=phead; ple=ple->Flink) {
  40. prte = CONTAINING_RECORD(ple, RAS_TABLE_ENTRY, HTLinkByAddr);
  41. if (prte->NHAddr == NHAddr) {
  42. break;
  43. }
  44. }
  45. return (ple == phead) ? NULL: prte;
  46. }
  47. //------------------------------------------------------------------------------
  48. // _GetIfByIndex
  49. //
  50. // returns the interface with the given index.
  51. // assumes the interface bucket is either read or write locked
  52. //------------------------------------------------------------------------------
  53. PIF_TABLE_ENTRY
  54. GetIfByIndex(
  55. DWORD IfIndex
  56. )
  57. {
  58. PIF_TABLE_ENTRY pite = NULL;
  59. PLIST_ENTRY phead, ple;
  60. phead = &g_pIfTable->HashTableByIndex[IF_HASH_VALUE(IfIndex)];
  61. for (ple=phead->Flink; ple!=phead; ple=ple->Flink) {
  62. pite = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, HTLinkByIndex);
  63. if (pite->IfIndex == IfIndex) {
  64. break;
  65. }
  66. }
  67. return (ple == phead) ? NULL: pite;
  68. }
  69. //------------------------------------------------------------------------------
  70. // _InsertIfByAddr
  71. //
  72. // inserts the activated interface into the list of interfaces sorted by address.
  73. // assumes the table is locked for writing
  74. //------------------------------------------------------------------------------
  75. DWORD
  76. InsertIfByAddr(
  77. PIF_TABLE_ENTRY piteInsert
  78. )
  79. {
  80. PIF_TABLE_ENTRY pite;
  81. INT cmp, cmp1;
  82. DWORD InsertAddr;
  83. PLIST_ENTRY phead, ple;
  84. phead = &g_pIfTable->ListByAddr;
  85. InsertAddr = piteInsert->IpAddr;
  86. //
  87. // search for the insertion point
  88. //
  89. for (ple=phead->Flink; ple!=phead; ple=ple->Flink) {
  90. pite = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, LinkByAddr);
  91. if ( (cmp1 = INET_CMP(InsertAddr, pite->IpAddr, cmp)) < 0)
  92. break;
  93. //
  94. // return error if there are duplicate addresses.
  95. // no error for unnumbered interfaces, ie for addr==0
  96. //
  97. else if ( (cmp1==0) && (InsertAddr!=0) )
  98. return ERROR_ALREADY_EXISTS;
  99. }
  100. InsertTailList(ple, &piteInsert->LinkByAddr);
  101. return NO_ERROR;
  102. }
  103. //------------------------------------------------------------------------------
  104. // MatchIpAddrBinding //
  105. // finds if the interface is bound to any address equal to IpAddr //
  106. //------------------------------------------------------------------------------
  107. BOOL
  108. MatchIpAddrBinding(
  109. PIF_TABLE_ENTRY pite,
  110. DWORD IpAddr
  111. )
  112. {
  113. PIGMP_IP_ADDRESS paddr;
  114. DWORD i;
  115. PIGMP_IF_BINDING pib;
  116. pib = pite->pBinding;
  117. paddr = IGMP_BINDING_FIRST_ADDR(pib);
  118. for (i=0; i<pib->AddrCount; i++,paddr++) {
  119. if (IpAddr==paddr->IpAddr)
  120. break;
  121. }
  122. return (i<pib->AddrCount)? TRUE: FALSE;
  123. }
  124. //------------------------------------------------------------------------------
  125. // _InsertInGroupsList
  126. //
  127. // Inserts a newly created group in the New or Main group list.
  128. // Calls: May call _MergeGroupLists() to merge the New and Main lists
  129. //------------------------------------------------------------------------------
  130. VOID
  131. InsertInGroupsList (
  132. PGROUP_TABLE_ENTRY pgeNew
  133. )
  134. {
  135. PGROUP_TABLE_ENTRY pgeTmp;
  136. PLIST_ENTRY pHead, ple;
  137. DWORD GroupLittleEndian = pgeNew->GroupLittleEndian;
  138. BOOL bInsertInNew;
  139. //
  140. // insert the group in main list if less than 20 entries, else insert in
  141. // the New list
  142. //
  143. bInsertInNew = (g_Info.CurrentGroupMemberships > 20);
  144. pHead = bInsertInNew ?
  145. &g_pGroupTable->ListByGroupNew :
  146. &g_pGroupTable->ListByGroup.Link;
  147. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  148. pgeTmp = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, LinkByGroup);
  149. if (GroupLittleEndian<pgeTmp->GroupLittleEndian)
  150. break;
  151. }
  152. InsertTailList(ple, &pgeNew->LinkByGroup);
  153. if (bInsertInNew) {
  154. // increment count of
  155. g_pGroupTable->NumGroupsInNewList++;
  156. //
  157. // merge lists if required
  158. //
  159. if (MERGE_GROUP_LISTS_REQUIRED()) {
  160. MergeGroupLists();
  161. }
  162. }
  163. return;
  164. }
  165. //------------------------------------------------------------------------------
  166. // _InsertInIfGroupsList
  167. // Inserts a newly created group in the New or Main group list.
  168. // Calls: May call MergeIfGroupLists() to merge the New and Main lists
  169. //------------------------------------------------------------------------------
  170. VOID
  171. InsertInIfGroupsList (
  172. PIF_TABLE_ENTRY pite,
  173. PGI_ENTRY pgiNew
  174. )
  175. {
  176. PGI_ENTRY pgiTmp;
  177. PLIST_ENTRY pHead, ple;
  178. DWORD GroupLittleEndian = pgiNew->pGroupTableEntry->GroupLittleEndian;
  179. BOOL bInsertInNew;
  180. //
  181. // insert the group in main list if less than 20 entries, else insert in
  182. // the New list
  183. //
  184. bInsertInNew = (pite->Info.CurrentGroupMemberships > 20);
  185. pHead = bInsertInNew ?
  186. &pite->ListOfSameIfGroupsNew :
  187. &pite->ListOfSameIfGroups;
  188. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  189. pgiTmp = CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameIfGroups);
  190. if (GroupLittleEndian<pgiTmp->pGroupTableEntry->GroupLittleEndian)
  191. break;
  192. }
  193. InsertTailList(ple, &pgiNew->LinkBySameIfGroups);
  194. if (bInsertInNew) {
  195. // increment count of
  196. pite->NumGIEntriesInNewList++;
  197. //
  198. // merge lists if required
  199. //
  200. if (MERGE_IF_GROUPS_LISTS_REQUIRED(pite)) {
  201. MergeIfGroupsLists(pite);
  202. }
  203. }
  204. return;
  205. }//end _InsertInIfGroupsList
  206. //------------------------------------------------------------------------------
  207. // InsertInProxyList
  208. //------------------------------------------------------------------------------
  209. VOID
  210. InsertInProxyList (
  211. PIF_TABLE_ENTRY pite,
  212. PPROXY_GROUP_ENTRY pNewProxyEntry
  213. )
  214. {
  215. PPROXY_GROUP_ENTRY pTmpProxyEntry;
  216. PLIST_ENTRY pHead, ple;
  217. DWORD GroupLittleEndian = pNewProxyEntry->GroupLittleEndian;
  218. BOOL bInsertInNew;
  219. //
  220. // dont insert in new list if less than 20 entries, else insert in
  221. // the New list
  222. //
  223. bInsertInNew = (pite->NumGIEntriesInNewList > 20);
  224. pHead = bInsertInNew ?
  225. &pite->ListOfSameIfGroupsNew :
  226. &pite->ListOfSameIfGroups;
  227. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  228. pTmpProxyEntry = CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY,
  229. LinkBySameIfGroups);
  230. if (GroupLittleEndian<pTmpProxyEntry->GroupLittleEndian)
  231. break;
  232. }
  233. InsertTailList(ple, &pNewProxyEntry->LinkBySameIfGroups);
  234. if (bInsertInNew) {
  235. // increment count of
  236. pite->NumGIEntriesInNewList++;
  237. //
  238. // merge lists if required
  239. //
  240. if (MERGE_PROXY_LISTS_REQUIRED(pite)) {
  241. MergeProxyLists(pite);
  242. }
  243. }
  244. return;
  245. }//end _InsertInProxyList
  246. //------------------------------------------------------------------------------
  247. // _GetGroupFromGroupTable
  248. // Returns the group entry. If group entry does not exist and bCreateFlag is
  249. // set, then it will take a group-list lock and create a new entry.
  250. // Locks:
  251. // Assumes lock on group bucket.
  252. // takes group-list lock if new group is being created.
  253. // If read only, assumes lock on group list
  254. //------------------------------------------------------------------------------
  255. PGROUP_TABLE_ENTRY
  256. GetGroupFromGroupTable (
  257. DWORD Group,
  258. BOOL *bCreate, //set to true if new one created
  259. LONGLONG llCurrentTime
  260. )
  261. {
  262. PGROUP_TABLE_ENTRY pge; //group table entry
  263. PLIST_ENTRY pHead, ple;
  264. DWORD Error = NO_ERROR;
  265. DWORD bCreateLocal;
  266. DWORD GroupLittleEndian = NETWORK_TO_LITTLE_ENDIAN(Group);
  267. bCreateLocal = (bCreate==NULL) ? FALSE : *bCreate;
  268. if (llCurrentTime==0)
  269. llCurrentTime = GetCurrentIgmpTime();
  270. BEGIN_BREAKOUT_BLOCK1 {
  271. // get pointer to the head of the group bucket
  272. pHead = &g_pGroupTable->HashTableByGroup[GROUP_HASH_VALUE(Group)].Link;
  273. // search for the group
  274. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  275. pge = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, HTLinkByGroup);
  276. if (GroupLittleEndian>=pge->GroupLittleEndian) {
  277. break;
  278. }
  279. }
  280. //
  281. // group entry not found
  282. //
  283. if ( (ple==pHead) || (pge->GroupLittleEndian!=GroupLittleEndian) ) {
  284. //
  285. // create and initialize new entry
  286. //
  287. if (bCreateLocal) {
  288. bCreateLocal = TRUE;
  289. pge = IGMP_ALLOC(sizeof(GROUP_TABLE_ENTRY), 0x800010,0xaaaa);
  290. PROCESS_ALLOC_FAILURE2(pge,
  291. "Error %d allocation %d bytes for Group table entry",
  292. Error, sizeof(GROUP_TABLE_ENTRY),
  293. GOTO_END_BLOCK1);
  294. InsertTailList(ple, &pge->HTLinkByGroup);
  295. InitializeListHead(&pge->LinkByGroup);
  296. pge->Group = Group;
  297. pge->GroupLittleEndian = GroupLittleEndian;
  298. pge->NumVifs = 0;
  299. pge->Status = CREATED_FLAG;
  300. pge->GroupUpTime = llCurrentTime;
  301. //
  302. // insert it into the list of all groups after taking the group
  303. // list lock
  304. //
  305. {
  306. PGROUP_TABLE_ENTRY pgeTmp;
  307. PLIST_ENTRY pHeadTmp, pleTmp;
  308. // take group list lock
  309. ACQUIRE_GROUP_LIST_LOCK("_GetGroupFromGroupTable");
  310. // initialize GI list head
  311. InitializeListHead(&pge->ListOfGIs);
  312. // insert in group list
  313. InsertInGroupsList(pge);
  314. // release group lock
  315. RELEASE_GROUP_LIST_LOCK("_GetGroupFromGroupTable");
  316. }
  317. // update statistics
  318. InterlockedIncrement(&g_Info.CurrentGroupMemberships);
  319. InterlockedIncrement(&g_Info.GroupMembershipsAdded);
  320. }
  321. // not found group, and do not create new group. So return NULL.
  322. else {
  323. pge = NULL;
  324. GOTO_END_BLOCK1;
  325. }
  326. }
  327. //
  328. // group entry found
  329. //
  330. else {
  331. bCreateLocal = FALSE;
  332. }
  333. } END_BREAKOUT_BLOCK1;
  334. if (bCreate!=NULL)
  335. *bCreate = bCreateLocal;
  336. #if DBG
  337. DebugPrintGroupsList(1);
  338. #endif
  339. return pge;
  340. } //end _GetGroupFromGroupTable
  341. //------------------------------------------------------------------------------
  342. // _GetGIFromGIList
  343. //
  344. // returns the GI entry if it exists. If the bCreate flag is set, then it creates
  345. // a new GI entry if it does not exist.
  346. //
  347. // Locks: Assumes shared interface lock. If ras interface, also assumes shared
  348. // Ras interface lock.
  349. // Assumes lock on group bucket.
  350. // Takes IF_GROUP_LIST_LOCK if new entry is to be created.
  351. // On return: bCreate is set to TRUE if a new entry was created
  352. //------------------------------------------------------------------------------
  353. PGI_ENTRY
  354. GetGIFromGIList (
  355. PGROUP_TABLE_ENTRY pge,
  356. PIF_TABLE_ENTRY pite,
  357. DWORD dwInputSrcAddr, //used for NHAddr
  358. BOOL bStaticGroup,
  359. BOOL *bCreate,
  360. LONGLONG llCurrentTime
  361. )
  362. {
  363. DWORD IfIndex = pite->IfIndex;
  364. BOOL bRasClient;
  365. PLIST_ENTRY pHead, ple;
  366. PGI_ENTRY pgie;
  367. PRAS_TABLE_ENTRY prte;
  368. PRAS_TABLE prt;
  369. BOOL bRasNewGroup = TRUE; //true if 1st ras group
  370. DWORD NHAddr;
  371. DWORD Error = NO_ERROR, dwRetval, i;
  372. BOOL bFound = FALSE, bCreateLocal;
  373. Trace2(ENTER1, "Entering _GetGIFromGIList() IfIndex(%0x) Group(%d.%d.%d.%d)",
  374. IfIndex, PRINT_IPADDR(pge->Group));
  375. //DebugPrintIfGroups(pite,0);//deldel
  376. bCreateLocal = (bCreate==NULL) ? FALSE : *bCreate;
  377. if (llCurrentTime==0)
  378. llCurrentTime = GetCurrentIgmpTime();
  379. BEGIN_BREAKOUT_BLOCK1 {
  380. //
  381. // find out if ras-server.
  382. //
  383. bRasClient = IS_RAS_SERVER_IF(pite->IfType);
  384. if (bRasClient) {
  385. prt = pite->pRasTable;
  386. // get ras client
  387. prte = GetRasClientByAddr(dwInputSrcAddr, prt);
  388. }
  389. NHAddr = bRasClient ? dwInputSrcAddr : 0;
  390. //
  391. // search for GI entry
  392. //
  393. pHead = &pge->ListOfGIs;
  394. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  395. pgie = CONTAINING_RECORD(ple, GI_ENTRY, LinkByGI);
  396. if (pgie->IfIndex>IfIndex)
  397. break;
  398. //
  399. // GI with same interface index
  400. //
  401. else if (pgie->IfIndex==IfIndex) {
  402. // the GI entry might belong to some interface being deleted
  403. if ( (pite!=pgie->pIfTableEntry)
  404. ||(IS_IF_DELETED(pgie->pIfTableEntry)) )
  405. continue;
  406. //multiple entries for ras clients
  407. if (bRasClient) {
  408. //
  409. // I set this even if the ras client is marked to be deleted
  410. //
  411. bRasNewGroup = FALSE;
  412. // the GI entry might belong to some other ras interface
  413. // being deleted
  414. if ( (prte!=pgie->pRasTableEntry)
  415. || (pgie->pRasTableEntry->Status&DELETED_FLAG) )
  416. continue;
  417. if (pgie->NHAddr>dwInputSrcAddr) {
  418. break;
  419. }
  420. // found GI entry for ras interface
  421. else if (pgie->NHAddr==dwInputSrcAddr) {
  422. bFound = TRUE;
  423. break;
  424. }
  425. }
  426. // found GI entry for non ras interface
  427. else {
  428. bFound = TRUE;
  429. break;
  430. }
  431. }
  432. }// end for loop:search through list of GIs
  433. //
  434. // GIentry not found
  435. //
  436. if ( !bFound) {
  437. // dont create new GI entry. Hence, return NULL
  438. if (!bCreateLocal) {
  439. pgie = NULL;
  440. GOTO_END_BLOCK1;
  441. }
  442. //
  443. // create and initialize new GI-entry
  444. //
  445. pgie = IGMP_ALLOC_AND_ZERO(sizeof(GI_ENTRY), 0x800011, pite->IfIndex);
  446. PROCESS_ALLOC_FAILURE2(pgie,
  447. "Error %d allocating %d bytes for group-interface entry",
  448. Error, sizeof(GI_ENTRY),
  449. GOTO_END_BLOCK1);
  450. pgie->IfIndex = IfIndex;
  451. pgie->Status = CREATED_FLAG;
  452. pgie->bRasClient = bRasClient;
  453. // insert in GI list
  454. InsertTailList(ple, &pgie->LinkByGI);
  455. //
  456. // set back pointers to the interface entry, and group entry
  457. //
  458. pgie->pIfTableEntry = pite;
  459. pgie->pGroupTableEntry = pge;
  460. //
  461. // Take lock on Interface-Group List before inserting into it
  462. // for ras client, insert it into ras client list also
  463. //
  464. ACQUIRE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_GetGIFromGIList");
  465. // insert in ras client list
  466. if (bRasClient) {
  467. PLIST_ENTRY pleTmp, pHeadRasClient;
  468. PGI_ENTRY pgieRasClient;
  469. pHeadRasClient = &prte->ListOfSameClientGroups;
  470. for (pleTmp=pHeadRasClient->Flink; pleTmp!=pHeadRasClient;
  471. pleTmp=pleTmp->Flink)
  472. {
  473. pgieRasClient = CONTAINING_RECORD(pleTmp, GI_ENTRY,
  474. LinkBySameClientGroups);
  475. if (pge->Group < pgieRasClient->pGroupTableEntry->Group)
  476. break;
  477. }
  478. InsertTailList(pleTmp, &pgie->LinkBySameClientGroups);
  479. }
  480. InsertInIfGroupsList(pite, pgie);
  481. RELEASE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_GetGIFromGIList");
  482. //
  483. // if ras
  484. //
  485. pgie->NHAddr = (bRasClient)? dwInputSrcAddr : 0;
  486. pgie->pRasTableEntry = (bRasClient)? prte : NULL;
  487. //
  488. // initialize GroupMembershipTimer
  489. //
  490. pgie->GroupMembershipTimer.Function = T_MembershipTimer;
  491. pgie->GroupMembershipTimer.Timeout = pite->Config.GroupMembershipTimeout;
  492. pgie->GroupMembershipTimer.Context = &pgie->GroupMembershipTimer.Context;
  493. pgie->GroupMembershipTimer.Status = TIMER_STATUS_CREATED;
  494. //
  495. // initialize LastMemQueryTimer timer
  496. //
  497. pgie->LastMemQueryCount = 0; //last member countdown inactive
  498. pgie->LastMemQueryTimer.Function = T_LastMemQueryTimer;
  499. pgie->LastMemQueryTimer.Context = &pgie->LastMemQueryTimer.Context;
  500. pgie->LastMemQueryTimer.Status = TIMER_STATUS_CREATED;
  501. //
  502. // initialize the LastVer1ReportTimer
  503. // the timeout value is set to GroupMembership timeout
  504. pgie->LastVer1ReportTimer.Function = T_LastVer1ReportTimer;
  505. pgie->LastVer1ReportTimer.Timeout
  506. = pite->Config.GroupMembershipTimeout;
  507. pgie->LastVer1ReportTimer.Context
  508. = &pgie->LastVer1ReportTimer.Context;
  509. pgie->LastVer1ReportTimer.Status = TIMER_STATUS_CREATED;
  510. pgie->LastVer2ReportTimer.Function = T_LastVer2ReportTimer;
  511. pgie->LastVer2ReportTimer.Timeout
  512. = pite->Config.GroupMembershipTimeout;
  513. pgie->LastVer2ReportTimer.Context
  514. = &pgie->LastVer2ReportTimer.Context;
  515. pgie->LastVer2ReportTimer.Status = TIMER_STATUS_CREATED;
  516. // set version based on current interface version
  517. pgie->Version = (IS_IF_VER1(pite)) ? 1 : ((IS_IF_VER2(pite))?2:3);
  518. //
  519. // initialize GI_INFO
  520. //
  521. ZeroMemory(&pgie->Info, sizeof(GI_INFO));
  522. pgie->Info.GroupUpTime = llCurrentTime;
  523. if (!bStaticGroup) {
  524. pgie->Info.GroupExpiryTime = llCurrentTime
  525. + CONFIG_TO_SYSTEM_TIME(pite->Config.GroupMembershipTimeout);
  526. }
  527. pgie->Info.V1HostPresentTimeLeft = 0;
  528. pgie->Info.V2HostPresentTimeLeft = 0;
  529. pgie->Info.LastReporter = dwInputSrcAddr;
  530. //
  531. // v3 fields
  532. //
  533. pgie->V3InclusionList = (PLIST_ENTRY)
  534. IGMP_ALLOC(sizeof(LIST_ENTRY)*SOURCES_BUCKET_SZ,
  535. 0x800020, pite->IfIndex);
  536. PROCESS_ALLOC_FAILURE2(pgie->V3InclusionList,
  537. "Error %d allocating sources table:%d bytes", Error,
  538. sizeof(LIST_ENTRY)*SOURCES_BUCKET_SZ,
  539. GOTO_END_BLOCK1);
  540. for (i=0; i<SOURCES_BUCKET_SZ; i++)
  541. InitializeListHead(&pgie->V3InclusionList[i]);
  542. InitializeListHead(&pgie->V3InclusionListSorted);
  543. pgie->NumSources = 0;
  544. pgie->FilterType = INCLUSION;
  545. InitializeListHead(&pgie->V3ExclusionList);
  546. InitializeListHead(&pgie->V3SourcesQueryList);
  547. pgie->V3SourcesQueryCount = 0;
  548. // V3SourcesQueryTimer
  549. pgie->V3SourcesQueryTimer.Function = T_V3SourcesQueryTimer;
  550. pgie->V3SourcesQueryTimer.Context =
  551. &pgie->V3SourcesQueryTimer.Context;
  552. pgie->V3SourcesQueryTimer.Status = TIMER_STATUS_CREATED;
  553. // set static group flag
  554. pgie->bStaticGroup = bStaticGroup;
  555. //
  556. // increment the count of number of If's for that group
  557. // I increment once for each virtual interface
  558. //
  559. InterlockedIncrement(&pge->NumVifs);
  560. if (!bRasClient||(bRasClient&bRasNewGroup) ) {
  561. InterlockedIncrement(&pite->Info.CurrentGroupMemberships);
  562. InterlockedIncrement(&pite->Info.GroupMembershipsAdded);
  563. }
  564. //
  565. // update stats for ras client
  566. //
  567. if ((bRasClient) && (g_Config.RasClientStats) ) {
  568. InterlockedIncrement(&prte->Info.CurrentGroupMemberships);
  569. InterlockedIncrement(&prte->Info.GroupMembershipsAdded);
  570. }
  571. //
  572. // Join the group to MGM
  573. //
  574. // call mgm to join the group only if the interface is
  575. // activated, enabled by mgm, either mprotocol exists or else
  576. // igmprtr is a querier on this interface
  577. if (CAN_ADD_GROUPS_TO_MGM(pite)
  578. && (pgie->bStaticGroup||!IS_IF_VER3(pite)) )
  579. {
  580. MGM_ADD_GROUP_MEMBERSHIP_ENTRY(pite, NHAddr, 0, 0,
  581. pge->Group, 0xffffffff, MGM_JOIN_STATE_FLAG);
  582. }
  583. //
  584. // v3 no MGM calls, as I create an inclusion list with null members.
  585. //
  586. } // if GI entry not found
  587. // GI entry found
  588. else {
  589. if (bStaticGroup)
  590. pgie->bStaticGroup = TRUE;
  591. bCreateLocal = FALSE;
  592. }
  593. } END_BREAKOUT_BLOCK1;
  594. if (bCreate!=NULL)
  595. *bCreate = bCreateLocal;
  596. Trace0(LEAVE1, "Leaving _GetGIFromGIList()");
  597. //Trace1(ENTER1, "GetGiFromGiList returned:%0x", (DWORD)pgie);//deldel
  598. return pgie;
  599. } //end _GetGIFromGIList
  600. //------------------------------------------------------------------------------
  601. // _DebugPrintGIList
  602. //------------------------------------------------------------------------------
  603. VOID
  604. DebugPrintGIList (
  605. PGROUP_TABLE_ENTRY pge,
  606. LONGLONG llCurTime
  607. )
  608. {
  609. PGI_ENTRY pgie;
  610. PLIST_ENTRY pHead, ple;
  611. pHead = &pge->ListOfGIs;
  612. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  613. pgie = CONTAINING_RECORD(ple, GI_ENTRY, LinkByGI);
  614. if (pgie->Status&IF_DELETED_FLAG)
  615. continue;
  616. //
  617. // GI info
  618. //
  619. Trace4(GROUP,
  620. "---If(%d: %d.%d.%d.%d) NHAddr(%d.%d.%d.%d) GroupMembershipTimer(%d sec)",
  621. pgie->IfIndex, PRINT_IPADDR(pgie->pIfTableEntry->IpAddr),
  622. PRINT_IPADDR(pgie->NHAddr),
  623. (pgie->GroupMembershipTimer.Timeout-llCurTime)/1000
  624. );
  625. //
  626. // if leave being processed
  627. //
  628. if (IS_TIMER_ACTIVE(pgie->LastMemQueryTimer)) {
  629. Trace2(GROUP,
  630. " *Leave received: LastMemQueryCount:%d LastMemQueryTimeLeft(%d ms)",
  631. pgie->LastMemQueryCount,
  632. (DWORD) (pgie->LastMemQueryTimer.Timeout-llCurTime)
  633. );
  634. }
  635. }
  636. Trace0(GROUP, "");
  637. return;
  638. }
  639. //------------------------------------------------------------------------------
  640. // DebugPrintGroups
  641. //------------------------------------------------------------------------------
  642. VOID
  643. APIENTRY
  644. DebugPrintGroups (
  645. DWORD Flags
  646. )
  647. {
  648. DWORD Group, i, j, k;
  649. DWORD IfIndex;
  650. PLIST_ENTRY pHead, ple;
  651. DWORD Count;
  652. PGROUP_TABLE_ENTRY pge; //group table entry
  653. LONGLONG llCurTime = GetCurrentIgmpTime();
  654. j = 1;
  655. Trace0(GROUP, "");
  656. for (i=0; i<GROUP_HASH_TABLE_SZ; i++) {
  657. ACQUIRE_GROUP_LOCK(i, "_DebugPrintGroups");
  658. pHead = &g_pGroupTable->HashTableByGroup[i].Link;
  659. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  660. pge = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, HTLinkByGroup);
  661. //
  662. // print group info
  663. //
  664. Trace3(GROUP, "(%d) Group:%d.%d.%d.%d UpTime(%lu sec)",
  665. j++, PRINT_IPADDR(pge->Group),
  666. (llCurTime-pge->GroupUpTime)/1000);
  667. // print GI list
  668. DebugPrintGIList(pge, llCurTime);
  669. }
  670. RELEASE_GROUP_LOCK(i, "_DebugPrintGroups");
  671. }
  672. return;
  673. }
  674. VOID
  675. DebugPrintIfGroups(
  676. PIF_TABLE_ENTRY pite,
  677. DWORD flag
  678. )
  679. {
  680. PGI_ENTRY pgiTmp;
  681. PLIST_ENTRY pHead, ple;
  682. BOOL bInsertInNew;
  683. DWORD count=0;
  684. PPROXY_GROUP_ENTRY proxyge;
  685. ACQUIRE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_DebugPrintIfGroups");
  686. Trace0(ERR, "---------------DebugPrintIfGroups---------------------");
  687. Trace1(ERR, "Ipaddr: %d.%d.%d.%d", PRINT_IPADDR(pite->IpAddr) );
  688. Trace1(ERR, "CurrentGroupMemberships: %d",pite->Info.CurrentGroupMemberships);
  689. pHead = &pite->ListOfSameIfGroups;
  690. for (ple=pHead->Flink; ple!=pHead && count<300; ple=ple->Flink) {
  691. if (!(flag&IGMP_IF_PROXY)) {
  692. pgiTmp = CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameIfGroups);
  693. Trace5(SOURCES, "%d: main list: %x:%x:%x: %d.%d.%d.%d", ++count, (ULONG_PTR)ple,
  694. (ULONG_PTR)ple->Flink, (ULONG_PTR)ple->Blink,
  695. PRINT_IPADDR(pgiTmp->pGroupTableEntry->Group));
  696. }
  697. else {
  698. proxyge = CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY, LinkBySameIfGroups);
  699. Trace5(SOURCES, "%d: proxyMailList: %x:%x:%x: %d.%d.%d.%d", ++count,
  700. (ULONG_PTR)ple,
  701. (ULONG_PTR)ple->Flink, (ULONG_PTR)ple->Blink,
  702. PRINT_IPADDR(proxyge->Group));
  703. }
  704. }
  705. pHead = &pite->ListOfSameIfGroupsNew;
  706. Trace1(ERR, "NumGIEntriesInNewList:%d", pite->NumGIEntriesInNewList);
  707. for (ple=pHead->Flink; ple!=pHead && count<300; ple=ple->Flink) {
  708. if (!(flag&IGMP_IF_PROXY)) {
  709. pgiTmp = CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameIfGroups);
  710. Trace5(ERR, "%d: NewList: %x:%x:%x: %d.%d.%d.%d", ++count, (ULONG_PTR)ple,
  711. (ULONG_PTR)ple->Flink, (ULONG_PTR)ple->Blink,
  712. PRINT_IPADDR(pgiTmp->pGroupTableEntry->Group));
  713. }
  714. else {
  715. proxyge = CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY, LinkBySameIfGroups);
  716. Trace5(ERR, "%d: ProxyNewList: %x:%x:%x: %d.%d.%d.%d", ++count, (ULONG_PTR)ple,
  717. (ULONG_PTR)ple->Flink, (ULONG_PTR)ple->Blink,
  718. PRINT_IPADDR(proxyge->Group));
  719. }
  720. }
  721. Trace0(ERR, "-------------------------------------------------------------");
  722. RELEASE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_DebugPrintIfGroups");
  723. //ASSERT(count<300);//deldel
  724. }
  725. DWORD
  726. APIENTRY
  727. DebugPrintLocks(
  728. )
  729. {
  730. DWORD Group;
  731. Trace0(KSL, "QUEUEING WORKER THREAD TO DEBUGPRINTLOCKS");
  732. QueueIgmpWorker(DebugPrintLocks, NULL);
  733. Trace0(KSL, "QUEUED WORKER THREAD TO DEBUGPRINTLOCKS");
  734. return NO_ERROR;
  735. }
  736. VOID
  737. DebugPrintLists(
  738. PLIST_ENTRY pHead
  739. )
  740. { DWORD count=0;
  741. PLIST_ENTRY ple;
  742. for (ple=pHead->Flink; (ple!=pHead)&&(count<16); ple=ple->Flink,count++) {
  743. Trace3(ERR, "ple:%lu ple->Flink:%lu: ple->Blink:%lu",
  744. ple, ple->Flink, ple->Blink);
  745. }
  746. }
  747. //------------------------------------------------------------------------------
  748. // _ForcePrintGroupsList
  749. //------------------------------------------------------------------------------
  750. VOID
  751. DebugForcePrintGroupsList (
  752. DWORD Flags
  753. )
  754. {
  755. BOOL bMain = FALSE;
  756. CHAR str[2][5] = {"new", "main"};
  757. LIST_ENTRY *ple, *pHead;
  758. PGROUP_TABLE_ENTRY pge;
  759. if (g_Info.CurrentGroupMemberships > 40 && !(Flags&ENSURE_EMPTY) )
  760. return;
  761. Trace0(ENTER1, "Entering _ForcePrintGroupsList()");
  762. pHead = &g_pGroupTable->ListByGroupNew;
  763. if (Flags&ENSURE_EMPTY) {
  764. if (IsListEmpty(pHead))
  765. return;// list empty as expected
  766. DbgPrint("Cleanup: Group Lists should be empty\n");
  767. DbgBreakPoint();
  768. }
  769. do {
  770. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  771. pge = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, LinkByGroup);
  772. Trace3(KSL, "%s-group list: <%d.%d.%d.%d> pge:%0x", str[bMain],
  773. PRINT_IPADDR(pge->Group), (ULONG_PTR)pge);
  774. if (!IS_MCAST_ADDR(pge->Group)) {
  775. #if DBG
  776. DbgBreakPoint();
  777. #endif
  778. Trace0(ERR, "===============================================================");
  779. Trace2(ERR, "bad group(%d.%d.%d.%d)(pge:%0x) while checking main-group",
  780. PRINT_IPADDR(pge->Group), (ULONG_PTR)pge);
  781. Trace0(ERR, "===============================================================");
  782. return;
  783. }
  784. }
  785. if (!bMain) {
  786. pHead = &g_pGroupTable->ListByGroup.Link;
  787. bMain = TRUE;
  788. }
  789. else
  790. break;
  791. } while (1);
  792. Trace0(LEAVE1, "Leaving _ForcePrintGroupsList()");
  793. }
  794. //------------------------------------------------------------------------------
  795. // DebugPrintGroupsList
  796. //------------------------------------------------------------------------------
  797. VOID
  798. DebugPrintGroupsList (
  799. DWORD Flags
  800. )
  801. {
  802. BOOL bMain = FALSE;
  803. CHAR str[2][5] = {"new", "main"};
  804. LIST_ENTRY *ple, *pHead;
  805. PGROUP_TABLE_ENTRY pge;
  806. static DWORD StaticCount;
  807. BOOL bPrint = FALSE;
  808. if (StaticCount++==30) {
  809. bPrint = TRUE;
  810. StaticCount = 0;
  811. }
  812. if (g_Info.CurrentGroupMemberships > 40)
  813. return;
  814. pHead = &g_pGroupTable->ListByGroupNew;
  815. do {
  816. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  817. pge = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, LinkByGroup);
  818. //if ((Flags)&&(bPrint))
  819. if (0)
  820. Trace3(KSL, "%s-group list: <%d.%d.%d.%d> pge:%0x", str[bMain],
  821. PRINT_IPADDR(pge->Group), (ULONG_PTR)pge);
  822. if (!IS_MCAST_ADDR(pge->Group)) {
  823. if (!bPrint) {
  824. DebugForcePrintGroupsList(1);
  825. return;
  826. }
  827. #if DBG
  828. DbgBreakPoint();
  829. #endif
  830. Trace0(ERR, "===============================================================");
  831. Trace2(ERR, "bad group(%d.%d.%d.%d)(pge:%0x) while checking main-group",
  832. PRINT_IPADDR(pge->Group), (ULONG_PTR)pge);
  833. Trace0(ERR, "===============================================================");
  834. return;
  835. }
  836. }
  837. if (!bMain) {
  838. pHead = &g_pGroupTable->ListByGroup.Link;
  839. bMain = TRUE;
  840. }
  841. else
  842. break;
  843. } while (1);
  844. //Trace0(LEAVE1, "Leaving _PrintGroupsList()");
  845. }