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.

4535 lines
137 KiB

  1. //=============================================================================
  2. // Copyright (c) 1997 Microsoft Corporation
  3. // Module Name: Mib.c
  4. //
  5. // Abstract:
  6. // This module implements the mib API's:
  7. // MibGet, MibGetFirst and MibGetNext.
  8. // It also implements the Mib Display tracing, which displays the mib
  9. //
  10. // Author: K.S.Lokesh (lokeshs@) 11-1-97
  11. //
  12. // Revision History:
  13. //=============================================================================
  14. #include "pchigmp.h"
  15. #pragma hdrstop
  16. DWORD g_IgmpMibDisplay = 1;
  17. //------------------------------------------------------------------------------
  18. // Functions to display the MibTable on the TraceWindow periodically
  19. //------------------------------------------------------------------------------
  20. #ifdef MIB_DEBUG
  21. #define ClearScreen(h) { \
  22. DWORD _dwin,_dwout; \
  23. COORD _c = {0, 0}; \
  24. CONSOLE_SCREEN_BUFFER_INFO _csbi; \
  25. GetConsoleScreenBufferInfo(h,&_csbi); \
  26. _dwin = _csbi.dwSize.X * _csbi.dwSize.Y; \
  27. FillConsoleOutputCharacter(h,' ',_dwin,_c,&_dwout); \
  28. }
  29. #define WRITELINE(h,c,fmt,arg) { \
  30. DWORD _dw; \
  31. CHAR _sz[200], _fmt[200]; \
  32. wsprintf(_fmt,"%-100s",fmt); \
  33. wsprintf(_sz,_fmt,arg); \
  34. WriteConsoleOutputCharacter(h,_sz,lstrlen(_sz),c,&_dw); \
  35. ++(c).Y; \
  36. }
  37. #define WRITE_NEWLINE(h,c) \
  38. WRITELINE( \
  39. hConsole, c, "%s", \
  40. "" \
  41. );
  42. #define WRITELINE2(h,c,fmt,arg1, arg2) { \
  43. DWORD _dw; \
  44. CHAR _sz[200], _fmt[200]; \
  45. wsprintf(_fmt,"%-100s",fmt); \
  46. wsprintf(_sz,_fmt,arg1, arg2); \
  47. WriteConsoleOutputCharacter(h,_sz,lstrlen(_sz),c,&_dw); \
  48. ++(c).Y; \
  49. }
  50. #define WRITELINE3(h,c,fmt,arg1, arg2, arg3) { \
  51. DWORD _dw; \
  52. CHAR _sz[200], _fmt[200]; \
  53. wsprintf(_fmt,"%-100s",fmt); \
  54. wsprintf(_sz,_fmt,arg1, (arg2), (arg3)); \
  55. WriteConsoleOutputCharacter(h,_sz,lstrlen(_sz),c,&_dw); \
  56. ++(c).Y; \
  57. }
  58. #define WRITELINE4(h,c,fmt,arg1, arg2, arg3, arg4) { \
  59. DWORD _dw; \
  60. CHAR _sz[200], _fmt[200]; \
  61. wsprintf(_fmt,"%-100s",fmt); \
  62. wsprintf(_sz,_fmt,arg1, arg2, arg3, arg4); \
  63. WriteConsoleOutputCharacter(h,_sz,lstrlen(_sz),c,&_dw); \
  64. ++(c).Y; \
  65. }
  66. #define WRITELINE5(h,c,fmt,arg1, arg2, arg3, arg4, arg5) { \
  67. DWORD _dw; \
  68. CHAR _sz[200], _fmt[200]; \
  69. wsprintf(_fmt,"%-100s",fmt); \
  70. wsprintf(_sz,_fmt,arg1, arg2, arg3, arg4, arg5); \
  71. WriteConsoleOutputCharacter(h,_sz,lstrlen(_sz),c,&_dw); \
  72. ++(c).Y; \
  73. }
  74. #define WRITELINE6(h,c,fmt,arg1, arg2, arg3, arg4, arg5, arg6) { \
  75. DWORD _dw; \
  76. CHAR _sz[200], _fmt[200]; \
  77. wsprintf(_fmt,"%-100s",fmt); \
  78. wsprintf(_sz,_fmt,arg1, arg2, arg3, arg4, arg5, arg6); \
  79. WriteConsoleOutputCharacter(h,_sz,lstrlen(_sz),c,&_dw); \
  80. ++(c).Y; \
  81. }
  82. #define WRITELINE7(h,c,fmt,arg1, arg2,arg3,arg4,arg5,arg6,arg7) {\
  83. DWORD _dw; \
  84. CHAR _sz[200], _fmt[200]; \
  85. wsprintf(_fmt,"%-100s",fmt); \
  86. wsprintf(_sz,_fmt,arg1, arg2, arg3, arg4, arg5, arg6, arg7);\
  87. WriteConsoleOutputCharacter(h,_sz,lstrlen(_sz),c,&_dw); \
  88. ++(c).Y; \
  89. }
  90. #define WRITELINE8(h,c,fmt,arg1, arg2,arg3,arg4,arg5,arg6,arg7,arg8) {\
  91. DWORD _dw; \
  92. CHAR _sz[200], _fmt[200]; \
  93. wsprintf(_fmt,"%-100s",fmt); \
  94. wsprintf(_sz,_fmt,arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);\
  95. WriteConsoleOutputCharacter(h,_sz,lstrlen(_sz),c,&_dw); \
  96. ++(c).Y; \
  97. }
  98. #define WRITELINE9(h,c,fmt,arg1, arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9) {\
  99. DWORD _dw; \
  100. CHAR _sz[200], _fmt[200]; \
  101. wsprintf(_fmt,"%-100s",fmt); \
  102. wsprintf(_sz,_fmt,arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);\
  103. WriteConsoleOutputCharacter(h,_sz,lstrlen(_sz),c,&_dw); \
  104. ++(c).Y; \
  105. }
  106. #define WRITELINE10(h,c,fmt,arg1, arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10) {\
  107. DWORD _dw; \
  108. CHAR _sz[200], _fmt[200]; \
  109. wsprintf(_fmt,"%-100s",fmt); \
  110. wsprintf(_sz,_fmt,arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,arg10);\
  111. WriteConsoleOutputCharacter(h,_sz,lstrlen(_sz),c,&_dw); \
  112. ++(c).Y; \
  113. }
  114. DWORD
  115. WT_MibDisplay (
  116. PVOID pContext
  117. )
  118. {
  119. //enter/leaveIgmpApi not required as the timer queue is persistent
  120. QueueIgmpWorker(WF_MibDisplay, NULL);
  121. return 0;
  122. }
  123. //------------------------------------------------------------------------------
  124. // _WF_MibDisplay
  125. //------------------------------------------------------------------------------
  126. VOID
  127. WF_MibDisplay(
  128. PVOID pContext
  129. )
  130. {
  131. COORD c;
  132. HANDLE hConsole;
  133. DWORD Error=NO_ERROR, dwTraceId, dwCurTableId=0, dwEnumCount;
  134. DWORD dwExactSize, dwInSize, dwBufferSize, dwOutSize;
  135. IGMP_MIB_GET_INPUT_DATA Query;
  136. PIGMP_MIB_GET_OUTPUT_DATA pResponse;
  137. LARGE_INTEGER llCurrentTime;
  138. BOOL bChanged, bEndOfTables;
  139. if (!EnterIgmpWorker()) { return; }
  140. if (g_IgmpMibDisplay==0) {
  141. ACQUIRE_TIMER_LOCK("_WF_MibDisplay");
  142. g_MibTimer.Status = TIMER_STATUS_CREATED;
  143. #if DEBUG_TIMER_TIMERID
  144. SET_TIMER_ID(&g_MibTimer, 920, 0, 0, 0);
  145. #endif
  146. if (g_Info.CurrentGroupMemberships<=20)
  147. InsertTimer(&g_MibTimer, 30000, TRUE, DBG_Y);//kslksl
  148. else if (g_Info.CurrentGroupMemberships<=320)
  149. InsertTimer(&g_MibTimer, 120000, TRUE, DBG_N);//kslksl
  150. else
  151. InsertTimer(&g_MibTimer, 1200000, TRUE, DBG_N);
  152. RELEASE_TIMER_LOCK("_WF_MibDisplay");
  153. LeaveIgmpWorker();
  154. return;
  155. }
  156. else if (g_IgmpMibDisplay==0xff) {
  157. LeaveIgmpWorker();
  158. return;
  159. }
  160. TraceGetConsole(g_MibTraceId, &hConsole);
  161. if (hConsole == NULL) {
  162. LeaveIgmpWorker();
  163. return;
  164. }
  165. ClearScreen(hConsole);
  166. Sleep(200);
  167. c.X = c.Y = 0;
  168. dwInSize = sizeof(Query);
  169. Query.GroupAddr = 0;
  170. Query.TypeId = IGMP_GLOBAL_CONFIG_ID;
  171. Query.Flags = IGMP_ENUM_ALL_INTERFACES_GROUPS | IGMP_ENUM_ALL_TABLES
  172. | IGMP_ENUM_SUPPORT_FORMAT_IGMPV3;
  173. Query.Count = 20;
  174. pResponse = NULL;
  175. //
  176. // get size of the first entry in the first table
  177. //
  178. Query.Count = 20;
  179. dwOutSize = dwBufferSize = 0;
  180. Error = MibGetFirst(dwInSize, &Query, &dwOutSize, pResponse);
  181. if (Error == ERROR_INSUFFICIENT_BUFFER) {
  182. //
  183. // allocate a buffer, and set its size
  184. //
  185. dwOutSize = dwBufferSize = (dwOutSize<MIB_DEFAULT_BUFFER_SIZE)
  186. ? MIB_DEFAULT_BUFFER_SIZE : dwOutSize;
  187. pResponse = IGMP_ALLOC(dwOutSize, 0x801,0);
  188. PROCESS_ALLOC_FAILURE2(pResponse,
  189. "error %d allocating %d bytes. stopping mib display",
  190. Error, dwOutSize, return);
  191. //
  192. // perform the query again
  193. //
  194. Error = MibGetFirst(dwInSize, &Query, &dwOutSize, pResponse);
  195. }
  196. //
  197. // now that we have the first element in the first table,
  198. // we can enumerate the elements in the remaining tables using GetNext
  199. //
  200. for (dwEnumCount=1; dwEnumCount<=3; dwEnumCount++) {
  201. while (Error==NO_ERROR) {
  202. //bEndOfTables = FALSE;
  203. //while(bEndOfTables==FALSE) {
  204. if (dwCurTableId!=pResponse->TypeId) {
  205. //
  206. // move to the next line on the console
  207. //
  208. ++c.Y;
  209. WRITELINE(
  210. hConsole, c, "%s",
  211. "---------------------------------------------------------------",
  212. );
  213. dwCurTableId = pResponse->TypeId;
  214. bChanged = TRUE;
  215. }
  216. else
  217. bChanged = FALSE;
  218. //
  219. // print the current element and set up the query
  220. // for the next element (the display functions change Query
  221. // so that it can be used to query the next element)
  222. //
  223. switch(pResponse->TypeId) {
  224. case IGMP_GLOBAL_CONFIG_ID:
  225. {
  226. if (bChanged) {
  227. WRITELINE(
  228. hConsole, c, "%s",
  229. "Global Configuration",
  230. );
  231. WRITELINE(
  232. hConsole, c, "%s",
  233. "--------------------",
  234. );
  235. }
  236. PrintGlobalConfig(hConsole,&c, &Query, pResponse);
  237. break;
  238. }
  239. case IGMP_GLOBAL_STATS_ID:
  240. {
  241. if (bChanged) {
  242. WRITELINE(
  243. hConsole, c, "%s",
  244. "Global Statistics Information",
  245. );
  246. WRITELINE(
  247. hConsole, c, "%s",
  248. "-----------------------------",
  249. );
  250. }
  251. PrintGlobalStats(hConsole, &c, &Query, pResponse);
  252. break;
  253. }
  254. case IGMP_IF_CONFIG_ID:
  255. {
  256. if (bChanged) {
  257. WRITELINE(
  258. hConsole, c, "%s",
  259. "Interface Config Table",
  260. );
  261. WRITELINE(
  262. hConsole, c, "%s",
  263. "----------------------",
  264. );
  265. }
  266. PrintIfConfig(hConsole, &c, &Query, pResponse);
  267. break;
  268. }
  269. case IGMP_IF_STATS_ID:
  270. if (bChanged) {
  271. WRITELINE(
  272. hConsole, c, "%s",
  273. "Interface Statistics Table",
  274. );
  275. WRITELINE(
  276. hConsole, c, "%s",
  277. "--------------------------",
  278. );
  279. }
  280. PrintIfStats(hConsole, &c, &Query, pResponse);
  281. break;
  282. case IGMP_IF_BINDING_ID:
  283. {
  284. if (bChanged) {
  285. WRITELINE(
  286. hConsole, c, "%s",
  287. "Interface Binding Table",
  288. );
  289. WRITELINE(
  290. hConsole, c, "%s",
  291. "-----------------------",
  292. );
  293. }
  294. PrintIfBinding(hConsole, &c, &Query, pResponse);
  295. break;
  296. }
  297. case IGMP_IF_GROUPS_LIST_ID:
  298. {
  299. if (bChanged) {
  300. WRITELINE(
  301. hConsole, c, "%s",
  302. "Interface-MulticastGroups Table",
  303. );
  304. WRITELINE(
  305. hConsole, c, "%s",
  306. "--------------------------------",
  307. );
  308. }
  309. PrintIfGroupsList(hConsole, &c, &Query, pResponse);
  310. break;
  311. }
  312. case IGMP_GROUP_IFS_LIST_ID:
  313. {
  314. if (bChanged) {
  315. WRITELINE(
  316. hConsole, c, "%s",
  317. "MulticastGroups-Interface Table",
  318. );
  319. WRITELINE(
  320. hConsole, c, "%s",
  321. "-------------------------------",
  322. );
  323. WRITELINE(
  324. hConsole, c, "%s",
  325. "(Ver) GroupAddr (Up/Exp)Time Flg <IfIndex:IpAddr> LastReporter "
  326. " V1Host V2Host"
  327. );
  328. WRITE_NEWLINE(hConsole, c);
  329. }
  330. PrintGroupIfsList(hConsole, &c, &Query, pResponse);
  331. break;
  332. }
  333. case IGMP_PROXY_IF_INDEX_ID:
  334. {
  335. WRITELINE(
  336. hConsole, c, "%s",
  337. "Proxy Interface Index",
  338. );
  339. WRITELINE(
  340. hConsole, c, "%s",
  341. "---------------------",
  342. );
  343. PrintProxyIfIndex(hConsole, &c, &Query, pResponse);
  344. break;
  345. }
  346. default:
  347. bEndOfTables = TRUE;
  348. break;
  349. }
  350. //
  351. // query the next MIB element
  352. //
  353. Query.Count = 20;
  354. //kslksl
  355. IGMP_FREE(pResponse);
  356. pResponse = IGMP_ALLOC(dwBufferSize, 0xb000,0);
  357. dwOutSize = dwBufferSize;
  358. Error = MibGetNext(dwInSize, &Query, &dwOutSize, pResponse);
  359. if (Error == ERROR_INSUFFICIENT_BUFFER) {
  360. //
  361. // allocate a new buffer, and set its size
  362. //
  363. dwOutSize = dwBufferSize = (dwOutSize<MIB_DEFAULT_BUFFER_SIZE)
  364. ? MIB_DEFAULT_BUFFER_SIZE : dwOutSize;
  365. IGMP_FREE(pResponse);
  366. pResponse = IGMP_ALLOC(dwOutSize, 0x2000,0);
  367. PROCESS_ALLOC_FAILURE2(pResponse,
  368. "error %d allocating %d bytes. stopping mib display",
  369. Error, dwOutSize, return);
  370. // perform the query again
  371. Error = MibGetNext(dwInSize, &Query, &dwOutSize, pResponse);
  372. }
  373. } // while no_error: print all tables
  374. Query.Flags = IGMP_ENUM_FOR_RAS_CLIENTS;
  375. Query.IfIndex = g_ProxyIfIndex;
  376. Query.TypeId = dwEnumCount==1? IGMP_IF_STATS_ID : IGMP_IF_GROUPS_LIST_ID;
  377. bChanged = TRUE;
  378. }
  379. //
  380. // if memory was allocated, free it now
  381. //
  382. if (pResponse != NULL) { IGMP_FREE(pResponse); }
  383. //
  384. // schedule next MIB display
  385. //
  386. ACQUIRE_TIMER_LOCK("_WF_MibDisplay");
  387. g_MibTimer.Status = TIMER_STATUS_CREATED;
  388. #if DEBUG_TIMER_TIMERID
  389. SET_TIMER_ID(&g_MibTimer, 920, 0, 0, 0);
  390. #endif
  391. if (g_Info.CurrentGroupMemberships<=20)
  392. InsertTimer(&g_MibTimer, 20000, TRUE, DBG_N);
  393. else if (g_Info.CurrentGroupMemberships<=320)
  394. InsertTimer(&g_MibTimer, 120000, TRUE, DBG_N);
  395. else
  396. InsertTimer(&g_MibTimer, 1200000, TRUE, DBG_N);
  397. RELEASE_TIMER_LOCK("_WF_MibDisplay");
  398. LeaveIgmpWorker();
  399. } //end _WF_MibDisplay
  400. //------------------------------------------------------------------------------
  401. // _PrintGlobalStats
  402. //------------------------------------------------------------------------------
  403. VOID
  404. PrintGlobalStats(
  405. HANDLE hConsole,
  406. PCOORD pc,
  407. PIGMP_MIB_GET_INPUT_DATA pQuery,
  408. PIGMP_MIB_GET_OUTPUT_DATA pResponse
  409. )
  410. {
  411. PIGMP_GLOBAL_STATS pgs;
  412. pgs = (PIGMP_GLOBAL_STATS)pResponse->Buffer;
  413. WRITELINE(
  414. hConsole, *pc, "Current Group Memberships: %d",
  415. pgs->CurrentGroupMemberships
  416. );
  417. WRITELINE(
  418. hConsole, *pc, "Group Memberships Added: %d",
  419. pgs->GroupMembershipsAdded
  420. );
  421. pQuery->TypeId = IGMP_GLOBAL_STATS_ID;
  422. }
  423. //------------------------------------------------------------------------------
  424. // _PrintProxyIfIndex
  425. //------------------------------------------------------------------------------
  426. VOID
  427. PrintProxyIfIndex(
  428. HANDLE hConsole,
  429. PCOORD pc,
  430. PIGMP_MIB_GET_INPUT_DATA pQuery,
  431. PIGMP_MIB_GET_OUTPUT_DATA pResponse
  432. )
  433. {
  434. DWORD *pProxyIfIndex = (PDWORD)pResponse->Buffer;
  435. WRITELINE(
  436. hConsole, *pc, "Proxy Interface Index: 0x%0x",
  437. *pProxyIfIndex
  438. );
  439. pQuery->TypeId = IGMP_PROXY_IF_INDEX_ID;
  440. }
  441. //------------------------------------------------------------------------------
  442. // _PrintGlobalConfig
  443. //------------------------------------------------------------------------------
  444. VOID
  445. PrintGlobalConfig(
  446. HANDLE hConsole,
  447. PCOORD pc,
  448. PIGMP_MIB_GET_INPUT_DATA pQuery,
  449. PIGMP_MIB_GET_OUTPUT_DATA pResponse
  450. )
  451. {
  452. PIGMP_MIB_GLOBAL_CONFIG pConfig;
  453. LARGE_INTEGER llTime;
  454. static DWORD dwCount;
  455. llTime.QuadPart = GetCurrentIgmpTime();
  456. pConfig = (PIGMP_MIB_GLOBAL_CONFIG)pResponse->Buffer;
  457. WRITELINE2(
  458. hConsole, *pc, "%d. Seconds since start: %lu",
  459. ++dwCount,
  460. (ULONG)((llTime.QuadPart - g_Info.TimeWhenRtrStarted.QuadPart)/1000)
  461. );
  462. WRITELINE(
  463. hConsole, *pc, "Version: %x",
  464. pConfig->Version
  465. );
  466. WRITELINE(
  467. hConsole, *pc, "Logging Level: %d",
  468. pConfig->LoggingLevel
  469. );
  470. WRITELINE(
  471. hConsole, *pc, "Ras Client Stats kept: %d",
  472. pConfig->RasClientStats
  473. );
  474. pQuery->TypeId = IGMP_GLOBAL_CONFIG_ID;
  475. }
  476. //------------------------------------------------------------------------------
  477. // _PrintIfConfig
  478. //------------------------------------------------------------------------------
  479. VOID
  480. PrintIfConfig(
  481. HANDLE hConsole,
  482. PCOORD pc,
  483. PIGMP_MIB_GET_INPUT_DATA pQuery,
  484. PIGMP_MIB_GET_OUTPUT_DATA pResponse
  485. )
  486. {
  487. PIGMP_MIB_IF_CONFIG pConfig;
  488. CHAR szIfType[50], szProtoType[50];
  489. DWORD LastIfIndex=0, Count;
  490. pConfig = (PIGMP_MIB_IF_CONFIG)pResponse->Buffer;
  491. for (Count=0; Count<pResponse->Count; Count++) {
  492. WRITE_NEWLINE(hConsole, *pc);
  493. LastIfIndex = pConfig->IfIndex;
  494. switch (pConfig->IfType) {
  495. case IGMP_IF_NOT_RAS :
  496. lstrcpy(szIfType, "Permanent");
  497. break;
  498. case IGMP_IF_RAS_ROUTER :
  499. lstrcpy(szIfType, "Demand-dial (Ras router)");
  500. break;
  501. case IGMP_IF_RAS_SERVER :
  502. lstrcpy(szIfType,
  503. "LocalWorkstation-dial (Ras server)");
  504. break;
  505. //ras client config will never be returned
  506. // is proxy type.
  507. default :
  508. if (IS_IFTYPE_PROXY(pConfig->IfType)) {
  509. if (pConfig->IfType&IGMP_IF_NOT_RAS)
  510. lstrcpy(szIfType, "Permanent (Igmp Proxy)");
  511. else
  512. lstrcpy(szIfType, "Demand-dial (Igmp Proxy)");
  513. }
  514. else
  515. lstrcpy(szIfType, "Unknown type");
  516. break;
  517. }
  518. WRITELINE(
  519. hConsole, *pc, "Interface Index: 0x%0x",
  520. pConfig->IfIndex
  521. );
  522. WRITELINE(
  523. hConsole, *pc, "Interface Ip Address: %s",
  524. INET_NTOA(pConfig->IpAddr)
  525. );
  526. WRITELINE(
  527. hConsole, *pc, "Interface Type: %s",
  528. szIfType
  529. );
  530. switch (pConfig->IgmpProtocolType) {
  531. case IGMP_ROUTER_V1 :
  532. lstrcpy(szProtoType, "Igmp Router ver-1"); break;
  533. case IGMP_ROUTER_V2 :
  534. lstrcpy(szProtoType, "Igmp Router ver-2"); break;
  535. case IGMP_ROUTER_V3 :
  536. lstrcpy(szProtoType, "Igmp Router ver-3"); break;
  537. case IGMP_PROXY :
  538. case IGMP_PROXY_V3 :
  539. lstrcpy(szProtoType, "Igmp Proxy"); break;
  540. default:
  541. {
  542. BYTE str[40];
  543. sprintf(str, "Illegal protocol Id: %d", pConfig->IgmpProtocolType);
  544. lstrcpy(szProtoType, str);
  545. break;
  546. }
  547. }
  548. WRITELINE(
  549. hConsole, *pc, "Protocol: %s",
  550. szProtoType
  551. );
  552. //
  553. // No config info for proxy
  554. //
  555. if (IS_CONFIG_IGMPPROXY(pConfig)) {
  556. ;
  557. }
  558. //
  559. // print igmp-router config info
  560. //
  561. else {
  562. WRITELINE(
  563. hConsole, *pc, "Robustness variable: %d",
  564. pConfig->RobustnessVariable
  565. );
  566. WRITELINE(
  567. hConsole, *pc, "Startup query interval: %d",
  568. pConfig->StartupQueryInterval
  569. );
  570. WRITELINE(
  571. hConsole, *pc, "Startup query count: %d",
  572. pConfig->StartupQueryCount
  573. );
  574. WRITELINE(
  575. hConsole, *pc, "General query interval: %d",
  576. pConfig->GenQueryInterval
  577. );
  578. WRITELINE(
  579. hConsole, *pc, "General query max response time: %d",
  580. pConfig->GenQueryMaxResponseTime
  581. );
  582. WRITELINE(
  583. hConsole, *pc, "Last member query interval: %d (ms)",
  584. pConfig->LastMemQueryInterval
  585. );
  586. WRITELINE(
  587. hConsole, *pc, "Last member query count: %d",
  588. pConfig->LastMemQueryCount
  589. );
  590. WRITELINE(
  591. hConsole, *pc, "Other querier present interval: %d",
  592. pConfig->OtherQuerierPresentInterval
  593. );
  594. WRITELINE(
  595. hConsole, *pc, "Group membership timeout: %d",
  596. pConfig->GroupMembershipTimeout
  597. );
  598. } //end if not proxy interface
  599. //
  600. // print static groups
  601. //
  602. if (pConfig->NumStaticGroups>0) {
  603. PIGMP_STATIC_GROUP pStaticGroup;
  604. DWORD i;
  605. PCHAR StaticModes[3] = {"", "IGMP_HOST_JOIN", "IGMPRTR_JOIN_MGM_ONLY"};
  606. WRITELINE(
  607. hConsole, *pc, "NumStaticGroups: %d",
  608. pConfig->NumStaticGroups
  609. );
  610. pStaticGroup = GET_FIRST_IGMP_STATIC_GROUP(pConfig);
  611. for (i=0; i<pConfig->NumStaticGroups; i++,pStaticGroup++) {
  612. WRITELINE3(
  613. hConsole, *pc, " %d. %-15s %s",
  614. i+1, INET_NTOA(pStaticGroup->GroupAddr),
  615. StaticModes[pStaticGroup->Mode]
  616. );
  617. }
  618. }
  619. pConfig = (PIGMP_MIB_IF_CONFIG)
  620. ((PBYTE)(pConfig) + IGMP_MIB_IF_CONFIG_SIZE(pConfig));
  621. } //end for loop; print each global config
  622. pQuery->TypeId = IGMP_IF_CONFIG_ID;
  623. pQuery->IfIndex = LastIfIndex;
  624. return;
  625. } //end _PrintIfConfig
  626. //------------------------------------------------------------------------------
  627. // _PrintIfStats
  628. //------------------------------------------------------------------------------
  629. VOID
  630. PrintIfStats(
  631. HANDLE hConsole,
  632. PCOORD pc,
  633. PIGMP_MIB_GET_INPUT_DATA pQuery,
  634. PIGMP_MIB_GET_OUTPUT_DATA pResponse
  635. )
  636. {
  637. PIGMP_MIB_IF_STATS pStats;
  638. CHAR szIfType[50];
  639. CHAR szProtoType[50], szState[100];
  640. DWORD LastIfIndex=0, Count;
  641. pStats = (PIGMP_MIB_IF_STATS)pResponse->Buffer;
  642. for (Count=0; Count<pResponse->Count; Count++,pStats++) {
  643. WRITE_NEWLINE(hConsole, *pc);
  644. LastIfIndex = pStats->IfIndex;
  645. switch (pStats->IfType) {
  646. case IGMP_IF_NOT_RAS :
  647. lstrcpy(szIfType, "Permanent");
  648. break;
  649. case IGMP_IF_RAS_ROUTER :
  650. lstrcpy(szIfType, "Demand-dial (Ras router)");
  651. break;
  652. case IGMP_IF_RAS_SERVER :
  653. lstrcpy(szIfType,
  654. "LocalWorkstation-dial (Ras server)");
  655. break;
  656. case IGMP_IF_RAS_CLIENT :
  657. lstrcpy(szIfType,
  658. "RemoteWorkstation-dial (Ras client)");
  659. break;
  660. // is proxy type.
  661. default :
  662. if (IS_IFTYPE_PROXY(pStats->IfType)) {
  663. if (pStats->IfType&IGMP_IF_NOT_RAS)
  664. lstrcpy(szIfType, "Permanent (Igmp Proxy)");
  665. else
  666. lstrcpy(szIfType, "Demand-dial (Igmp Proxy)");
  667. }
  668. else
  669. lstrcpy(szIfType, "Unknown type");
  670. break;
  671. }
  672. WRITELINE(
  673. hConsole, *pc, "Interface Index: 0x%0x",
  674. pStats->IfIndex
  675. );
  676. WRITELINE(
  677. hConsole, *pc, "Interface Type: %s",
  678. szIfType
  679. );
  680. WRITELINE(
  681. hConsole, *pc, "Interface Ip Address: %s",
  682. INET_NTOA(pStats->IpAddr)
  683. );
  684. //
  685. // print the protocol type
  686. //
  687. switch (pStats->IgmpProtocolType) {
  688. case IGMP_ROUTER_V1 :
  689. lstrcpy(szProtoType, "Igmp Router ver-1"); break;
  690. case IGMP_ROUTER_V2 :
  691. lstrcpy(szProtoType, "Igmp Router ver-2"); break;
  692. case IGMP_ROUTER_V3 :
  693. lstrcpy(szProtoType, "Igmp Router ver-3"); break;
  694. case IGMP_PROXY :
  695. case IGMP_PROXY_V3 :
  696. lstrcpy(szProtoType, "Igmp Proxy"); break;
  697. }
  698. WRITELINE(
  699. hConsole, *pc, "Protocol: %s",
  700. szProtoType
  701. );
  702. //
  703. // print the state
  704. //
  705. {
  706. PCHAR szBool[2] = {"N", "Y"};
  707. szState[0] = '\0';
  708. if (!(pStats->State&IGMP_STATE_BOUND))
  709. lstrcat(szState, "<NotBound> ");
  710. lstrcat(szState, "<Enabled-By:");
  711. lstrcat(szState, " Rtrmgr-");
  712. lstrcat(szState, szBool[(pStats->State&IGMP_STATE_ENABLED_BY_RTRMGR)>0]);
  713. lstrcat(szState, " Config-");
  714. lstrcat(szState, szBool[(pStats->State&IGMP_STATE_ENABLED_IN_CONFIG)>0]);
  715. lstrcat(szState, " MGM-");
  716. lstrcat(szState, szBool[(pStats->State&IGMP_STATE_ENABLED_BY_MGM)>0]);
  717. lstrcat(szState, "> ");
  718. if (!IS_IFTYPE_PROXY(pStats->IfType)) {
  719. if ( (pStats->State&IGMP_STATE_MGM_JOINS_ENABLED)
  720. ==IGMP_STATE_MGM_JOINS_ENABLED )
  721. {
  722. lstrcat(szState, "JoinsFwdToMGM-Y");
  723. }
  724. else
  725. lstrcat(szState, "JoinsFwdToMGM-N");
  726. }
  727. }
  728. WRITELINE(
  729. hConsole, *pc, "If-Status: %s",
  730. szState
  731. );
  732. //
  733. // if state is not both bound & enabled, I am done
  734. //
  735. if ((pStats->State&IGMP_STATE_ACTIVATED)!=IGMP_STATE_ACTIVATED)
  736. continue;
  737. WRITELINE(
  738. hConsole, *pc, "Uptime: %d",
  739. pStats->Uptime
  740. );
  741. ///////////////////
  742. // Stats for proxy
  743. ///////////////////
  744. if (IS_IFTYPE_PROXY(pStats->IfType)) {
  745. WRITELINE(
  746. hConsole, *pc, "Num current group members: %d",
  747. pStats->CurrentGroupMemberships
  748. );
  749. WRITELINE(
  750. hConsole, *pc, "Num group memberships added: %d",
  751. pStats->GroupMembershipsAdded
  752. );
  753. }
  754. ////////////////////////////////////////////////////////////////
  755. // print igmp-router/ras-server/ras-router/ras client Stats info
  756. ////////////////////////////////////////////////////////////////
  757. else {
  758. //
  759. // if Not ras client, print these
  760. //
  761. if (pStats->IfType!=IGMP_IF_RAS_CLIENT) {
  762. //querier or not querier
  763. if (pStats->QuerierState&QUERIER)
  764. {
  765. WRITELINE(
  766. hConsole, *pc, "State: %s",
  767. "Querier"
  768. );
  769. // querier ip addr
  770. WRITELINE(
  771. hConsole, *pc, "Querier Ip Addr: %s",
  772. INET_NTOA(pStats->QuerierIpAddr)
  773. );
  774. }
  775. else {
  776. WRITELINE(
  777. hConsole, *pc, "State: %s",
  778. "Not Querier"
  779. );
  780. // querier ip addr
  781. WRITELINE(
  782. hConsole, *pc, "Querier Ip Addr: %s",
  783. INET_NTOA(pStats->QuerierIpAddr)
  784. );
  785. // querier present time left
  786. WRITELINE(
  787. hConsole, *pc, "QuerierPresentTimeLeft: %d",
  788. pStats->QuerierPresentTimeLeft
  789. );
  790. }
  791. WRITELINE(
  792. hConsole, *pc, "LastQuerierChangeTime: %d",
  793. pStats->LastQuerierChangeTime
  794. );
  795. if (pStats->V1QuerierPresentTimeLeft) {
  796. WRITELINE(
  797. hConsole, *pc, "V1QuerierPresentTime: %d",
  798. pStats->V1QuerierPresentTimeLeft
  799. );
  800. }
  801. } //end not ras-client
  802. WRITELINE(
  803. hConsole, *pc, "Num current group members: %d",
  804. pStats->CurrentGroupMemberships
  805. );
  806. WRITELINE(
  807. hConsole, *pc, "Num group memberships added: %d",
  808. pStats->GroupMembershipsAdded
  809. );
  810. WRITELINE(
  811. hConsole, *pc, "Num of Igmp packets received: %d",
  812. pStats->TotalIgmpPacketsReceived
  813. );
  814. WRITELINE(
  815. hConsole, *pc, "Num Igmp-router proto packets recv: %d",
  816. pStats->TotalIgmpPacketsForRouter
  817. );
  818. WRITELINE(
  819. hConsole, *pc, "Num general queries received: %d",
  820. pStats->GeneralQueriesReceived
  821. );
  822. WRITELINE(
  823. hConsole, *pc, "Num wrong version queries: %d",
  824. pStats->WrongVersionQueries
  825. );
  826. WRITELINE(
  827. hConsole, *pc, "Num Joins received: %d",
  828. pStats->JoinsReceived
  829. );
  830. WRITELINE(
  831. hConsole, *pc, "Num leaves received: %d",
  832. pStats->LeavesReceived
  833. );
  834. WRITELINE(
  835. hConsole, *pc, "Num wrong checksum packets: %d",
  836. pStats->WrongChecksumPackets
  837. );
  838. WRITELINE(
  839. hConsole, *pc, "Num short packets received: %d",
  840. pStats->ShortPacketsReceived
  841. );
  842. WRITELINE(
  843. hConsole, *pc, "Num long packets received: %d",
  844. pStats->LongPacketsReceived
  845. );
  846. WRITELINE(
  847. hConsole, *pc, "Num packets without RtrAlert: %d",
  848. pStats->PacketsWithoutRtrAlert
  849. );
  850. } //end print igmp-router/ras-router/ras-server Stats info
  851. } //end for loop; print each stats info
  852. pQuery->TypeId = IGMP_IF_STATS_ID;
  853. pQuery->IfIndex = LastIfIndex;
  854. return;
  855. }//end _PrintIfStats
  856. //------------------------------------------------------------------------------
  857. // _PrintIfBinding
  858. //------------------------------------------------------------------------------
  859. VOID
  860. PrintIfBinding(
  861. HANDLE hConsole,
  862. PCOORD pc,
  863. PIGMP_MIB_GET_INPUT_DATA pQuery,
  864. PIGMP_MIB_GET_OUTPUT_DATA pResponse
  865. )
  866. {
  867. DWORD NumIfs, NumAddrs, NumClients, LastIfIndex;
  868. CHAR szAddr[64];
  869. PIGMP_MIB_IF_BINDING pib;
  870. PIGMP_MIB_IP_ADDRESS paddr;
  871. PDWORD pRasClientAddr;
  872. PBYTE ptr; //pointer to next binding
  873. ptr = pResponse->Buffer;
  874. if (pResponse->Count<=0) //prefast
  875. return;
  876. for (NumIfs=0; NumIfs<pResponse->Count; NumIfs++) {
  877. pib = (PIGMP_MIB_IF_BINDING)ptr;
  878. WRITE_NEWLINE(hConsole, *pc);
  879. WRITELINE(
  880. hConsole, *pc, "Interface Index: 0x%0x",
  881. pib->IfIndex
  882. );
  883. WRITELINE(
  884. hConsole, *pc, "Address Count: %d",
  885. pib->AddrCount
  886. );
  887. //
  888. // Not ras client
  889. //
  890. if (pib->IfType!=IGMP_IF_RAS_CLIENT) {
  891. paddr = IGMP_BINDING_FIRST_ADDR(pib);
  892. for (NumAddrs=0; NumAddrs<pib->AddrCount; NumAddrs++,paddr++) {
  893. INET_COPY(szAddr, paddr->IpAddr);
  894. lstrcat(szAddr, " - ");
  895. INET_CAT(szAddr, paddr->SubnetMask);
  896. WRITELINE(
  897. hConsole, *pc, "Address Entry: %s",
  898. szAddr
  899. );
  900. INET_COPY(szAddr, paddr->IpAddr);
  901. lstrcat(szAddr, " - ");
  902. INET_CAT(szAddr, paddr->SubnetMask);
  903. WRITELINE(
  904. hConsole, *pc, "Address Entry: %s",
  905. szAddr
  906. );
  907. }
  908. //Set pointer to the next Interface binding
  909. ptr = (PBYTE) (paddr);
  910. } //end if not ras client
  911. //
  912. // Ras client. Print address of ras server, followed by the clients
  913. //
  914. else {
  915. // print ras server address
  916. paddr = IGMP_BINDING_FIRST_ADDR(pib);
  917. INET_COPY(szAddr, paddr->IpAddr);
  918. lstrcat(szAddr, " - ");
  919. INET_CAT(szAddr, paddr->SubnetMask);
  920. WRITELINE(
  921. hConsole, *pc, "Ras server Addr %s",
  922. szAddr
  923. );
  924. // print addresses of ras clients
  925. pRasClientAddr = (PDWORD)(paddr+1);
  926. for (NumClients= 0; NumClients<pib->AddrCount-1; NumClients++,pRasClientAddr++) {
  927. WRITELINE(
  928. hConsole, *pc, "Ras client Addr: %s",
  929. INET_NTOA(*pRasClientAddr)
  930. );
  931. }
  932. //Set pointer to the next Interface binding
  933. ptr = (PBYTE) (pRasClientAddr);
  934. }
  935. } //end print statistics of the interface
  936. LastIfIndex = pib->IfIndex;
  937. pQuery->TypeId = IGMP_IF_BINDING_ID;
  938. pQuery->IfIndex = LastIfIndex;
  939. return;
  940. }//end _PrintIfBinding
  941. //------------------------------------------------------------------------------
  942. // _PrintIfGroupsList
  943. //------------------------------------------------------------------------------
  944. VOID
  945. PrintIfGroupsList(
  946. HANDLE hConsole,
  947. PCOORD pc,
  948. PIGMP_MIB_GET_INPUT_DATA pQuery,
  949. PIGMP_MIB_GET_OUTPUT_DATA pResponse
  950. )
  951. {
  952. DWORD i, j, LastIfIndex, Flags;
  953. CHAR szAddr[64], szFlags[4];
  954. PIGMP_MIB_IF_GROUPS_LIST pIfGroupList;
  955. PBYTE ptr;
  956. PMIB_GROUP_INFO_V3 pGIInfo;
  957. PMIB_PROXY_GROUP_INFO_V3 pGIProxyInfo;
  958. BOOL bProxy;
  959. DWORD bVer3;
  960. ptr = pResponse->Buffer;
  961. pIfGroupList = (PIGMP_MIB_IF_GROUPS_LIST) ptr;
  962. bProxy = IS_IFTYPE_PROXY(pIfGroupList->IfType);
  963. bVer3 = pResponse->Flags & IGMP_ENUM_FORMAT_IGMPV3;
  964. if (pQuery->Flags&IGMP_ENUM_INTERFACE_TABLE_BEGIN) {
  965. WRITE_NEWLINE(hConsole, *pc);
  966. if (bProxy) {
  967. WRITELINE(
  968. hConsole, *pc, "%s",
  969. "ProxyInterface"
  970. );
  971. }
  972. WRITELINE(
  973. hConsole, *pc, "Interface Index: %0x",
  974. pIfGroupList->IfIndex
  975. );
  976. if (pIfGroupList->NumGroups!=0) {
  977. if (bProxy) {
  978. WRITELINE(
  979. hConsole, *pc, " %s",
  980. "GroupAddr UpTime Flags"
  981. );
  982. }
  983. else {
  984. if (!bVer3) {
  985. WRITELINE(
  986. hConsole, *pc, " %s",
  987. "(Ver)GroupAddr LastReporter (Up/Exp)Time Flags V1Host(TimeLeft)"
  988. );
  989. }
  990. else {
  991. WRITELINE(
  992. hConsole, *pc, "%s",
  993. "(Ver) GroupAddr (Up/Exp)Time Flags V1Host V2Host"
  994. );
  995. }
  996. }
  997. }
  998. }
  999. //
  1000. // print all groups which are members on this interface
  1001. //
  1002. if (bProxy)
  1003. pGIProxyInfo = (PMIB_PROXY_GROUP_INFO_V3)pIfGroupList->Buffer;
  1004. else
  1005. pGIInfo = (PMIB_GROUP_INFO_V3)pIfGroupList->Buffer;
  1006. for (j=0; j<pIfGroupList->NumGroups; j++) {
  1007. Flags = (bProxy)? pGIProxyInfo->Flags: pGIInfo->Flags;
  1008. sprintf(szFlags, " ");
  1009. if (Flags&IGMP_GROUP_TYPE_NON_STATIC)
  1010. szFlags[0] = 'L';
  1011. if (Flags&IGMP_GROUP_TYPE_STATIC)
  1012. szFlags[1] = 'S';
  1013. if (Flags&IGMP_GROUP_FWD_TO_MGM)
  1014. szFlags[2] = 'F';
  1015. //
  1016. // proxy interface
  1017. //
  1018. if (bProxy) {
  1019. WRITELINE3(
  1020. hConsole, *pc, " %-15s %10d %s",
  1021. INET_NTOA(pGIProxyInfo->GroupAddr), pGIProxyInfo->GroupUpTime, szFlags
  1022. );
  1023. if (bVer3) {
  1024. DWORD SrcCnt;
  1025. CHAR JoinMode = ' ';
  1026. CHAR JoinModeIntended = ' ';
  1027. for (SrcCnt=0; SrcCnt<pGIProxyInfo->NumSources; SrcCnt++) {
  1028. if (pGIProxyInfo->Sources[SrcCnt].Flags & IGMP_GROUP_ALLOW)
  1029. JoinMode = 'A';
  1030. if (pGIProxyInfo->Sources[SrcCnt].Flags & IGMP_GROUP_BLOCK)
  1031. JoinMode = 'B';
  1032. if (pGIProxyInfo->Sources[SrcCnt].Flags & IGMP_GROUP_NO_STATE)
  1033. JoinMode = '-';
  1034. if (pGIProxyInfo->Sources[SrcCnt].Flags & (IGMP_GROUP_ALLOW<<4))
  1035. JoinModeIntended = 'A';
  1036. if (pGIProxyInfo->Sources[SrcCnt].Flags & (IGMP_GROUP_BLOCK<<4))
  1037. JoinModeIntended = 'B';
  1038. if (pGIProxyInfo->Sources[SrcCnt].Flags & (IGMP_GROUP_NO_STATE<<4))
  1039. JoinModeIntended = '-';
  1040. WRITELINE3(
  1041. hConsole, *pc, " - %-15s:%c:%c",
  1042. INET_NTOA(pGIProxyInfo->Sources[SrcCnt].Source),
  1043. JoinMode,JoinModeIntended
  1044. );
  1045. }
  1046. }
  1047. }
  1048. //
  1049. // non-proxy interface
  1050. //
  1051. else if (!bProxy && !bVer3){
  1052. CHAR szGroupAddr[64], szLastReporter[64], szExpTime[50];
  1053. DWORD GroupVersion = (pGIInfo->V1HostPresentTimeLeft)?1:2;
  1054. CHAR szV1HostPresent[10];
  1055. INET_COPY(szGroupAddr, pGIInfo->GroupAddr);
  1056. INET_COPY(szLastReporter, pGIInfo->LastReporter);
  1057. szV1HostPresent[0] = 'N'; szV1HostPresent[1] = '\0';
  1058. if (pGIInfo->V1HostPresentTimeLeft!=0)
  1059. sprintf(szV1HostPresent, "%d", pGIInfo->V1HostPresentTimeLeft);
  1060. sprintf(szExpTime, "%d", pGIInfo->GroupExpiryTime);
  1061. if ( (Flags&IGMP_GROUP_TYPE_STATIC)
  1062. && !(Flags&IGMP_GROUP_TYPE_NON_STATIC) ) {
  1063. sprintf(szExpTime, "inf");
  1064. sprintf(szLastReporter, " -");
  1065. }
  1066. WRITELINE7(
  1067. hConsole, *pc, "[%d] %-13s %-15s %7d|%3s %3s %-10s",
  1068. GroupVersion, szGroupAddr, szLastReporter, pGIInfo->GroupUpTime,
  1069. szExpTime, szFlags, szV1HostPresent
  1070. );
  1071. }
  1072. else if (!bProxy && bVer3) {
  1073. CHAR szGroupAddr[64], szExpTime[50], szFilter[10];
  1074. CHAR szV1HostPresent[10], szV2HostPresent[10];
  1075. DWORD GroupVersion = pGIInfo->Version, SrcCnt=0;
  1076. INET_COPY(szGroupAddr, pGIInfo->GroupAddr);
  1077. szV1HostPresent[0] = szV2HostPresent[0] = 'N';
  1078. szV1HostPresent[1] = szV2HostPresent[1] = '\0';
  1079. if (pGIInfo->V1HostPresentTimeLeft!=0)
  1080. sprintf(szV1HostPresent, "%d", pGIInfo->V1HostPresentTimeLeft);
  1081. if (pGIInfo->V2HostPresentTimeLeft!=0)
  1082. sprintf(szV2HostPresent, "%d", pGIInfo->V2HostPresentTimeLeft);
  1083. if (GroupVersion==3 && pGIInfo->FilterType==INCLUSION)
  1084. sprintf(szExpTime, "-na");
  1085. else //if (pGIInfo->FilterType==exclusion)
  1086. sprintf(szExpTime, "%d", pGIInfo->GroupExpiryTime);
  1087. if ( (Flags&IGMP_GROUP_TYPE_STATIC)
  1088. && !(Flags&IGMP_GROUP_TYPE_NON_STATIC) ) {
  1089. sprintf(szExpTime, "inf");
  1090. }
  1091. if (GroupVersion==3) {
  1092. sprintf(szFilter, "%s", pGIInfo->FilterType==INCLUSION? "[IN]" :
  1093. "[EX]");
  1094. }
  1095. else
  1096. strcpy(szFilter, " ");
  1097. WRITELINE8(
  1098. hConsole, *pc, "[%d] %-13s%s %7d|%3s %3s %5s %-5s",
  1099. GroupVersion, szGroupAddr, szFilter, pGIInfo->GroupUpTime,
  1100. szExpTime, szFlags, szV1HostPresent, szV2HostPresent
  1101. );
  1102. if (GroupVersion==3) {
  1103. for (SrcCnt=0; SrcCnt<pGIInfo->NumSources; SrcCnt++) {
  1104. if (pGIInfo->Sources[SrcCnt].SourceExpiryTime==~0)
  1105. sprintf(szExpTime, "%s", "inf");
  1106. else {
  1107. sprintf(szExpTime, "%d",
  1108. pGIInfo->Sources[SrcCnt].SourceExpiryTime/1000);
  1109. }
  1110. WRITELINE3(
  1111. hConsole, *pc, " - %-13s %7d|%-s",
  1112. INET_NTOA(pGIInfo->Sources[SrcCnt].Source),
  1113. pGIInfo->Sources[SrcCnt].SourceUpTime,
  1114. szExpTime
  1115. );
  1116. }
  1117. }
  1118. }
  1119. //
  1120. // increment pGIInfo/pGIProxyInfo
  1121. //
  1122. if (bProxy) {
  1123. if (bVer3)
  1124. pGIProxyInfo = (PMIB_PROXY_GROUP_INFO_V3)
  1125. &pGIProxyInfo->Sources[pGIProxyInfo->NumSources];
  1126. else
  1127. pGIProxyInfo = (PMIB_PROXY_GROUP_INFO_V3)
  1128. ((PMIB_PROXY_GROUP_INFO)pGIProxyInfo+1);
  1129. }
  1130. else {
  1131. if (bVer3)
  1132. pGIInfo = (PMIB_GROUP_INFO_V3)
  1133. &pGIInfo->Sources[pGIInfo->NumSources];
  1134. else
  1135. pGIInfo = (PMIB_GROUP_INFO_V3) ((PMIB_GROUP_INFO)pGIInfo+1);
  1136. }
  1137. }
  1138. pQuery->TypeId = IGMP_IF_GROUPS_LIST_ID;
  1139. pQuery->IfIndex = pIfGroupList->IfIndex;
  1140. return;
  1141. }//end _PrintIfGroupsList
  1142. //------------------------------------------------------------------------------
  1143. // _PrintGroupIfsList
  1144. //------------------------------------------------------------------------------
  1145. VOID
  1146. PrintGroupIfsList(
  1147. HANDLE hConsole,
  1148. PCOORD pc,
  1149. PIGMP_MIB_GET_INPUT_DATA pQuery,
  1150. PIGMP_MIB_GET_OUTPUT_DATA pResponse
  1151. )
  1152. {
  1153. DWORD i, j, LastGroupAddr;
  1154. CHAR szGroupAddr[22];
  1155. PIGMP_MIB_GROUP_IFS_LIST pGroupIfsList;
  1156. PMIB_GROUP_INFO_V3 pGIInfo;
  1157. PBYTE ptr;
  1158. DWORD bVer3;
  1159. ptr = pResponse->Buffer;
  1160. bVer3 = pResponse->Flags & IGMP_ENUM_FORMAT_IGMPV3;
  1161. if (pResponse->Count<=0) //prefast
  1162. return;
  1163. for (i=0; i<pResponse->Count; i++) {
  1164. pGroupIfsList = (PIGMP_MIB_GROUP_IFS_LIST) ptr;
  1165. INET_COPY(szGroupAddr, pGroupIfsList->GroupAddr);
  1166. //
  1167. // print all GIs which are members on this group
  1168. //
  1169. pGIInfo = (PMIB_GROUP_INFO_V3)pGroupIfsList->Buffer;
  1170. for (j=0; j<pGroupIfsList->NumInterfaces; j++) {
  1171. CHAR szIpAddr[16], szLastReporter[16], szV1Host[4],
  1172. szV1HostTimeLeft[10], szFlags[5], szGroupExpTime[10];
  1173. sprintf(szFlags, " ");
  1174. if (pGIInfo->Flags&IGMP_GROUP_TYPE_NON_STATIC)
  1175. szFlags[0] = 'L';
  1176. if (pGIInfo->Flags&IGMP_GROUP_TYPE_STATIC)
  1177. szFlags[1] = 'S';
  1178. if (pGIInfo->Flags&IGMP_GROUP_FWD_TO_MGM)
  1179. szFlags[2] = 'F';
  1180. INET_COPY(szIpAddr, pGIInfo->IpAddr);
  1181. if (!bVer3){
  1182. CHAR szLastReporter[64], szExpTime[50];
  1183. DWORD GroupVersion = (pGIInfo->V1HostPresentTimeLeft)?1:2;
  1184. CHAR szV1HostPresent[10];
  1185. INET_COPY(szGroupAddr, pGIInfo->GroupAddr);
  1186. INET_COPY(szLastReporter, pGIInfo->LastReporter);
  1187. szV1HostPresent[0] = '\0';
  1188. if (pGIInfo->V1HostPresentTimeLeft!=0)
  1189. sprintf(szV1HostPresent, "%d", pGIInfo->V1HostPresentTimeLeft);
  1190. sprintf(szExpTime, "%d", pGIInfo->GroupExpiryTime);
  1191. if ( (pGIInfo->Flags&IGMP_GROUP_TYPE_STATIC)
  1192. && !(pGIInfo->Flags&IGMP_GROUP_TYPE_NON_STATIC) ) {
  1193. sprintf(szExpTime, "inf");
  1194. sprintf(szLastReporter, " -");
  1195. }
  1196. WRITELINE9(
  1197. hConsole, *pc,
  1198. "[%d] %-12s %7d|%-3s %3s <%d:%-14s> %-12s %5s",
  1199. GroupVersion, szGroupAddr,
  1200. pGIInfo->GroupUpTime, szExpTime, szFlags,
  1201. pGIInfo->IfIndex, szIpAddr,
  1202. szLastReporter, szV1HostPresent
  1203. );
  1204. }
  1205. else {
  1206. CHAR szGroupAddr[64], szExpTime[50], szFilter[10];
  1207. CHAR szV1HostPresent[10], szV2HostPresent[10];
  1208. DWORD GroupVersion = pGIInfo->Version, SrcCnt=0;
  1209. INET_COPY(szGroupAddr, pGroupIfsList->GroupAddr);
  1210. szV1HostPresent[0] = szV2HostPresent[0] = 'N';
  1211. szV1HostPresent[1] = szV2HostPresent[1] = '\0';
  1212. if (pGIInfo->V1HostPresentTimeLeft!=0)
  1213. sprintf(szV1HostPresent, "%d", pGIInfo->V1HostPresentTimeLeft);
  1214. if (pGIInfo->V2HostPresentTimeLeft!=0)
  1215. sprintf(szV2HostPresent, "%d", pGIInfo->V2HostPresentTimeLeft);
  1216. if (GroupVersion==3 && pGIInfo->FilterType==INCLUSION)
  1217. sprintf(szExpTime, "-na");
  1218. else //if (pGIInfo->FilterType==exclusion)
  1219. sprintf(szExpTime, "%d", pGIInfo->GroupExpiryTime);
  1220. if ( (pGIInfo->Flags&IGMP_GROUP_TYPE_STATIC)
  1221. && !(pGIInfo->Flags&IGMP_GROUP_TYPE_NON_STATIC) ) {
  1222. sprintf(szExpTime, "inf");
  1223. }
  1224. if (GroupVersion==3) {
  1225. sprintf(szFilter, "%s", pGIInfo->FilterType==INCLUSION? "[IN]" :
  1226. "[EX]");
  1227. }
  1228. else
  1229. strcpy(szFilter, " ");
  1230. WRITELINE10(
  1231. hConsole, *pc,
  1232. "[%d] %-12s%s %7d|%-3s %3s <%d:%-14s> %20s %5s",
  1233. GroupVersion, szGroupAddr, szFilter,
  1234. pGIInfo->GroupUpTime, szExpTime, szFlags,
  1235. pGIInfo->IfIndex, szIpAddr,
  1236. szV1HostPresent, szV2HostPresent
  1237. );
  1238. if (GroupVersion==3) {
  1239. for (SrcCnt=0; SrcCnt<pGIInfo->NumSources; SrcCnt++) {
  1240. if (pGIInfo->Sources[SrcCnt].SourceExpiryTime==~0)
  1241. sprintf(szExpTime, "%s", "inf");
  1242. else {
  1243. sprintf(szExpTime, "%d",
  1244. pGIInfo->Sources[SrcCnt].SourceExpiryTime/1000);
  1245. }
  1246. WRITELINE3(
  1247. hConsole, *pc, " - %-12s %7d|%s",
  1248. INET_NTOA(pGIInfo->Sources[SrcCnt].Source),
  1249. pGIInfo->Sources[SrcCnt].SourceUpTime,
  1250. szExpTime
  1251. );
  1252. }
  1253. }
  1254. }
  1255. if (bVer3)
  1256. pGIInfo = (PMIB_GROUP_INFO_V3)
  1257. &pGIInfo->Sources[pGIInfo->NumSources];
  1258. else
  1259. pGIInfo = (PMIB_GROUP_INFO_V3) ((PMIB_GROUP_INFO)pGIInfo+1);
  1260. } //for loop: end print all GIs
  1261. ptr = (PBYTE)pGIInfo;
  1262. }
  1263. LastGroupAddr= pGroupIfsList->GroupAddr;
  1264. pQuery->TypeId = IGMP_GROUP_IFS_LIST_ID;
  1265. pQuery->GroupAddr = LastGroupAddr;
  1266. return;
  1267. }//end _PrintGroupIfsList
  1268. #endif MIB_DEBUG
  1269. DWORD
  1270. ListLength(
  1271. PLIST_ENTRY pHead
  1272. )
  1273. {
  1274. DWORD Len=0;
  1275. PLIST_ENTRY ple;
  1276. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink,Len++)
  1277. ;
  1278. return Len;
  1279. }
  1280. //------------------------------------------------------------------------------
  1281. // _MibGet
  1282. //
  1283. // Called by an admin (SNMP) utility. It actually passes through the
  1284. // IP Router Manager, but all that does is demux the call to the
  1285. // desired routing protocol
  1286. //
  1287. // Calls: _MibGetInternal() with GETMODE_EXACT.
  1288. // Locks: Takes no locks. _MibGetInternal() will get the locks it requires
  1289. //------------------------------------------------------------------------------
  1290. DWORD
  1291. APIENTRY
  1292. MibGet(
  1293. IN DWORD dwInputSize,
  1294. IN PVOID pInputData,
  1295. IN OUT PDWORD pdwOutputSize,
  1296. OUT PVOID pOutputData
  1297. )
  1298. {
  1299. DWORD Error=NO_ERROR;
  1300. PIGMP_MIB_GET_INPUT_DATA pQuery;
  1301. PIGMP_MIB_GET_OUTPUT_DATA pResponse;
  1302. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  1303. Trace1(MIB, "entering _MibGet(): dwInputSize(%d)", dwInputSize);
  1304. if ( (pInputData == NULL)
  1305. || (dwInputSize < sizeof(IGMP_MIB_GET_INPUT_DATA))
  1306. || (pdwOutputSize == NULL)
  1307. )
  1308. {
  1309. Error = ERROR_INVALID_PARAMETER;
  1310. }
  1311. else {
  1312. pQuery = (PIGMP_MIB_GET_INPUT_DATA)pInputData;
  1313. // with GETMODE_EXACT you can get only one
  1314. pQuery->Count = 1;
  1315. pResponse = (PIGMP_MIB_GET_OUTPUT_DATA)pOutputData;
  1316. Error = MibGetInternal(pQuery, pResponse, pdwOutputSize, GETMODE_EXACT);
  1317. }
  1318. Trace1(MIB, "leaving _MibGet(): %d", Error);
  1319. LeaveIgmpApi();
  1320. return Error;
  1321. }
  1322. //------------------------------------------------------------------------------
  1323. // MibGetFirst
  1324. //
  1325. // Calls: _MibGetInternal() with GETMODE_FIRST
  1326. // Locks: No locks taken here. _MibGetInternal() takes the locks it requires
  1327. //------------------------------------------------------------------------------
  1328. DWORD
  1329. APIENTRY
  1330. MibGetFirst(
  1331. IN DWORD dwInputSize,
  1332. IN PVOID pInputData,
  1333. IN OUT PDWORD pdwOutputSize,
  1334. OUT PVOID pOutputData
  1335. )
  1336. {
  1337. DWORD Error=NO_ERROR;
  1338. PIGMP_MIB_GET_INPUT_DATA pQuery;
  1339. PIGMP_MIB_GET_OUTPUT_DATA pResponse;
  1340. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  1341. Trace4(MIB, "entering _MibGetFirst(): dwInputSize(%d) pInputData(%08x)"
  1342. "pdwOutputSize(%08x) pOutputData(%08x)",
  1343. dwInputSize, pInputData, pdwOutputSize, pOutputData);
  1344. if ( (pInputData == NULL)
  1345. || (dwInputSize < sizeof(IGMP_MIB_GET_INPUT_DATA))
  1346. || (pdwOutputSize == NULL)
  1347. )
  1348. {
  1349. Error = ERROR_INVALID_PARAMETER;
  1350. }
  1351. else {
  1352. pQuery = (PIGMP_MIB_GET_INPUT_DATA)pInputData;
  1353. if (pQuery->Count<=0)
  1354. pQuery->Count = 1;
  1355. pResponse = (PIGMP_MIB_GET_OUTPUT_DATA)pOutputData;
  1356. Error = MibGetInternal(pQuery, pResponse, pdwOutputSize, GETMODE_FIRST);
  1357. }
  1358. Trace1(MIB, "leaving _MibGetFirst: %d", Error);
  1359. LeaveIgmpApi();
  1360. return Error;
  1361. }
  1362. //------------------------------------------------------------------------------
  1363. // _MibGetNext
  1364. //
  1365. // This call returns the entry in the table AFTER the one specified in the input.
  1366. // If the end of the table being queried has been reached, this function will
  1367. // return the FIRST entry from the NEXT table, where "NEXT" here means the
  1368. // table whose ID is one greater than the ID passed in.
  1369. // In any case, this function writes the required size to pdwOutputSize and
  1370. // writes the ID of the object that WOULD have been returned into the output
  1371. // buffer.
  1372. //
  1373. // Calls:
  1374. // _MibGetInternal() with GETMODE_NEXT. If end of table reached, calls
  1375. // _MibGetInternal() again with GETMODE_FIRST for the next table.
  1376. //------------------------------------------------------------------------------
  1377. DWORD
  1378. APIENTRY
  1379. MibGetNext(
  1380. IN DWORD dwInputSize,
  1381. IN PVOID pInputData,
  1382. IN OUT PDWORD pdwOutputSize,
  1383. OUT PVOID pOutputData
  1384. )
  1385. {
  1386. DWORD Error = NO_ERROR;
  1387. DWORD dwOutSize = 0, dwBufSize = 0;
  1388. PIGMP_MIB_GET_INPUT_DATA pQuery;
  1389. PIGMP_MIB_GET_OUTPUT_DATA pResponse;
  1390. if (!EnterIgmpApi()) { return ERROR_CAN_NOT_COMPLETE; }
  1391. Trace4(MIB, "entering _MibGetNext(): dwInputSize(%d) pInputData(%08x) "
  1392. "pdwOutputSize(%08x) pOutputData(%08x)",
  1393. dwInputSize, pInputData, pdwOutputSize, pOutputData);
  1394. if (pInputData == NULL ||
  1395. dwInputSize < sizeof(IGMP_MIB_GET_INPUT_DATA) ||
  1396. pdwOutputSize == NULL) {
  1397. Error = ERROR_INVALID_PARAMETER;
  1398. }
  1399. else {
  1400. pQuery = (PIGMP_MIB_GET_INPUT_DATA)pInputData;
  1401. pResponse = (PIGMP_MIB_GET_OUTPUT_DATA)pOutputData;
  1402. if (pQuery->Count<=0)
  1403. pQuery->Count = 1;
  1404. dwOutSize = *pdwOutputSize;
  1405. Error = MibGetInternal(pQuery, pResponse, pdwOutputSize, GETMODE_NEXT);
  1406. if ((Error==ERROR_NO_MORE_ITEMS) && (pQuery->Flags&IGMP_ENUM_ALL_TABLES) )
  1407. {
  1408. //
  1409. // need to wrap to the first entry in the next table,
  1410. // if there is a next table
  1411. //
  1412. *pdwOutputSize = dwOutSize;
  1413. //
  1414. // wrap to next table by incrementing the type ID
  1415. //
  1416. do {
  1417. ++pQuery->TypeId;
  1418. Error = MibGetInternal(pQuery, pResponse, pdwOutputSize,
  1419. GETMODE_FIRST);
  1420. } while ( (Error==ERROR_INVALID_PARAMETER)&&(pQuery->TypeId<=IGMP_LAST_TABLE_ID) );
  1421. --pQuery->TypeId;
  1422. }
  1423. }
  1424. Trace1(MIB, "leaving _MibGetNext(): %d", Error);
  1425. LeaveIgmpApi();
  1426. return Error;
  1427. }
  1428. //------------------------------------------------------------------------------
  1429. // Function: _MibGetInternal
  1430. //
  1431. // This handles the actual structure access required to read MIB data.
  1432. // Each table supported by IGMP supports three modes of querying;
  1433. // EXACT, FIRST, and NEXT, which correspond to the functions _MibGet(),
  1434. // _MibGetFirst(), and _MibGetNext() respectively.
  1435. //------------------------------------------------------------------------------
  1436. DWORD
  1437. MibGetInternal(
  1438. PIGMP_MIB_GET_INPUT_DATA pQuery,
  1439. PIGMP_MIB_GET_OUTPUT_DATA pResponse,
  1440. PDWORD pdwOutputSize,
  1441. DWORD dwGetMode
  1442. )
  1443. {
  1444. DWORD Error = NO_ERROR, dwBufferSize;
  1445. //
  1446. // first we use pdwOutputSize to compute the size of the buffer
  1447. // available for storing returned structures (the size of Buffer)
  1448. //
  1449. if (pResponse == NULL) {
  1450. dwBufferSize = 0;
  1451. }
  1452. else {
  1453. if (*pdwOutputSize < sizeof(IGMP_MIB_GET_OUTPUT_DATA)) {
  1454. dwBufferSize = 0;
  1455. }
  1456. else {
  1457. dwBufferSize = *pdwOutputSize
  1458. - sizeof(IGMP_MIB_GET_OUTPUT_DATA) + 1;
  1459. //kslksl
  1460. if (dwBufferSize>150)
  1461. dwBufferSize -= 150;
  1462. }
  1463. }
  1464. *pdwOutputSize = 0;
  1465. // set flag for ras stats if pQuery has it and config supports it
  1466. if (pResponse!=NULL) {
  1467. pResponse->Flags = 0;
  1468. if ( (pQuery->Flags&IGMP_ENUM_FOR_RAS_CLIENTS)
  1469. && (g_Config.RasClientStats) )
  1470. {
  1471. pResponse->Flags |= IGMP_ENUM_FOR_RAS_CLIENTS;
  1472. }
  1473. }
  1474. //
  1475. // determine which type of data is to be returned
  1476. //
  1477. switch (pQuery->TypeId) {
  1478. case IGMP_GLOBAL_STATS_ID:
  1479. {
  1480. //
  1481. // there is only one global config object,
  1482. // so GETMODE_NEXT will return ERROR_NO_MORE_ITEMS
  1483. //
  1484. if (pResponse!=NULL)
  1485. pResponse->TypeId = IGMP_GLOBAL_STATS_ID;
  1486. if (dwGetMode == GETMODE_NEXT) {
  1487. Error = ERROR_NO_MORE_ITEMS;
  1488. break;
  1489. }
  1490. *pdwOutputSize = sizeof(IGMP_MIB_GLOBAL_STATS);
  1491. if (pResponse == NULL) {
  1492. Error = ERROR_INSUFFICIENT_BUFFER;
  1493. break;
  1494. }
  1495. // make sure that the buffer size is big enough
  1496. if (dwBufferSize < sizeof(IGMP_MIB_GLOBAL_STATS)) {
  1497. Error = ERROR_INSUFFICIENT_BUFFER;
  1498. break;
  1499. }
  1500. // set the values
  1501. else {
  1502. PIGMP_MIB_GLOBAL_STATS pGlobalStats;
  1503. pGlobalStats = (PIGMP_MIB_GLOBAL_STATS)pResponse->Buffer;
  1504. pGlobalStats->CurrentGroupMemberships
  1505. = g_Info.CurrentGroupMemberships;
  1506. pGlobalStats->GroupMembershipsAdded
  1507. = g_Info.GroupMembershipsAdded;
  1508. }
  1509. pResponse->Count = 1;
  1510. break;
  1511. }//end case IGMP_GLOBAL_STATS_ID
  1512. case IGMP_GLOBAL_CONFIG_ID: {
  1513. //
  1514. // there is only one global config object,
  1515. // so GETMODE_NEXT will return ERROR_NO_MORE_ITEMS
  1516. //
  1517. if (pResponse!=NULL)
  1518. pResponse->TypeId = IGMP_GLOBAL_CONFIG_ID;
  1519. if (dwGetMode == GETMODE_NEXT) {
  1520. Error = ERROR_NO_MORE_ITEMS;
  1521. break;
  1522. }
  1523. *pdwOutputSize = sizeof(IGMP_MIB_GLOBAL_CONFIG);
  1524. if (pResponse == NULL) {
  1525. Error = ERROR_INSUFFICIENT_BUFFER;
  1526. break;
  1527. }
  1528. if (dwBufferSize < sizeof(IGMP_MIB_GLOBAL_CONFIG)) {
  1529. Error = ERROR_INSUFFICIENT_BUFFER;
  1530. }
  1531. else {
  1532. CopyMemory(pResponse->Buffer, &g_Config,
  1533. sizeof(IGMP_MIB_GLOBAL_CONFIG));
  1534. }
  1535. pResponse->Count = 1;
  1536. break;
  1537. } //end case IGMP_GLOBAL_CONFIG_ID
  1538. case IGMP_PROXY_IF_INDEX_ID :
  1539. {
  1540. //
  1541. // there can be only one proxy interface.
  1542. // so GETMODE_NEXT will return ERROR_NO_MORE_ITEMS
  1543. //
  1544. if (pResponse!=NULL)
  1545. pResponse->TypeId = IGMP_PROXY_IF_INDEX_ID;
  1546. if (dwGetMode == GETMODE_NEXT) {
  1547. Error = ERROR_NO_MORE_ITEMS;
  1548. break;
  1549. }
  1550. *pdwOutputSize = sizeof(DWORD);
  1551. if (pResponse == NULL) {
  1552. Error = ERROR_INSUFFICIENT_BUFFER;
  1553. break;
  1554. }
  1555. // make sure that the buffer size is big enough
  1556. if (dwBufferSize < sizeof(DWORD)) {
  1557. Error = ERROR_INSUFFICIENT_BUFFER;
  1558. break;
  1559. }
  1560. // set the values
  1561. else {
  1562. DWORD *pProxyIndex;
  1563. pProxyIndex = (DWORD*)pResponse->Buffer;
  1564. *pProxyIndex = g_ProxyIfIndex;
  1565. }
  1566. pResponse->Count = 1;
  1567. break;
  1568. } //end case IGMP_PROXY_IF_INDEX_ID
  1569. case IGMP_IF_BINDING_ID :
  1570. {
  1571. Error = MibGetInternalIfBindings(pQuery, pResponse, pdwOutputSize,
  1572. dwGetMode, dwBufferSize);
  1573. break;
  1574. }
  1575. case IGMP_IF_STATS_ID: {
  1576. //
  1577. // set the size needed. It will be set again at the end to the
  1578. // exact size used.
  1579. //
  1580. if (pQuery->Count==0) {
  1581. Error = ERROR_INVALID_PARAMETER;
  1582. break;
  1583. }
  1584. Error = MibGetInternalIfStats(pQuery, pResponse, pdwOutputSize, dwGetMode,
  1585. dwBufferSize);
  1586. break;
  1587. } //end case IGMP_IF_STATS_ID
  1588. case IGMP_IF_CONFIG_ID:
  1589. {
  1590. if (pQuery->Count==0) {
  1591. Error = ERROR_INVALID_PARAMETER;
  1592. break;
  1593. }
  1594. Error = MibGetInternalIfConfig(pQuery, pResponse, pdwOutputSize,
  1595. dwGetMode, dwBufferSize);
  1596. break;
  1597. } //end case IGMP_IF_CONFIG_ID
  1598. // I cant get the list of groups for a RAS server interface
  1599. case IGMP_IF_GROUPS_LIST_ID :
  1600. {
  1601. PIGMP_MIB_IF_GROUPS_LIST pIfGroupList;
  1602. if (pQuery->Count==0) {
  1603. Error = ERROR_INVALID_PARAMETER;
  1604. break;
  1605. }
  1606. while (1) {
  1607. Error = MibGetInternalIfGroupsInfo(pQuery, pResponse, pdwOutputSize,
  1608. dwGetMode, dwBufferSize);
  1609. if ( (Error!=NO_ERROR) || (pResponse==NULL) )
  1610. break;
  1611. pIfGroupList = (PIGMP_MIB_IF_GROUPS_LIST)pResponse->Buffer;
  1612. if ( (pIfGroupList->NumGroups==0)
  1613. && (pQuery->Flags&IGMP_ENUM_ALL_INTERFACES_GROUPS)
  1614. && (pQuery->Flags&IGMP_ENUM_INTERFACE_TABLE_END)
  1615. && !(pQuery->Flags&IGMP_ENUM_INTERFACE_TABLE_BEGIN)
  1616. && !(pQuery->Flags&IGMP_ENUM_INTERFACE_TABLE_CONTINUE) )
  1617. {
  1618. continue;
  1619. }
  1620. else
  1621. break;
  1622. }
  1623. break;
  1624. } //end case IGMP_IF_GROUPS_LIST_ID
  1625. case IGMP_GROUP_IFS_LIST_ID :
  1626. {
  1627. if (pQuery->Count==0) {
  1628. Error = ERROR_INVALID_PARAMETER;
  1629. break;
  1630. }
  1631. Error = MibGetInternalGroupIfsInfo(pQuery, pResponse, pdwOutputSize,
  1632. dwGetMode, dwBufferSize);
  1633. break;
  1634. } //end case IGMP_GROUP_IFS_LIST_ID
  1635. // set this for group statistics ERROR_NO_MORE_ITEMS
  1636. default: {
  1637. Error = ERROR_INVALID_PARAMETER;
  1638. }
  1639. } //end switch
  1640. if (pdwOutputSize)
  1641. *pdwOutputSize += sizeof(IGMP_MIB_GET_OUTPUT_DATA);
  1642. //kslksl
  1643. if (pdwOutputSize && Error==ERROR_INSUFFICIENT_BUFFER)
  1644. *pdwOutputSize = *pdwOutputSize+500;
  1645. return Error;
  1646. } //_MibGetInternal
  1647. //------------------------------------------------------------------------------
  1648. // MibGetInternalIfBindings
  1649. //
  1650. // Returns the binding info of pQuery->Count number of interfaces.
  1651. //
  1652. //Locks:
  1653. // Takes the IfLists lock so that the InterfaceList does not change in between.
  1654. // It also prevents the bindings from being changed, as (Un)Bind If takes this lock.
  1655. //------------------------------------------------------------------------------
  1656. DWORD
  1657. MibGetInternalIfBindings (
  1658. PIGMP_MIB_GET_INPUT_DATA pQuery,
  1659. PIGMP_MIB_GET_OUTPUT_DATA pResponse,
  1660. PDWORD pdwOutputSize,
  1661. DWORD dwGetMode,
  1662. DWORD dwBufferSize
  1663. )
  1664. {
  1665. PIF_TABLE_ENTRY pite;
  1666. PIGMP_MIB_IF_BINDING pBindingDst;
  1667. PIGMP_IF_BINDING pBindingSrc;
  1668. DWORD dwSize, dwSizeCur=0, dwCount, Error=NO_ERROR;
  1669. Trace0(MIB, "Entering _MibGetInternalIfBinding");
  1670. if (pResponse!=NULL) {
  1671. pResponse->TypeId = IGMP_IF_BINDING_ID;
  1672. pBindingDst = (PIGMP_MIB_IF_BINDING)pResponse->Buffer;
  1673. }
  1674. ACQUIRE_IF_LIST_LOCK("_MibGetInternalBindings");
  1675. for (dwCount=0, dwSize=0; dwCount<pQuery->Count; ) {
  1676. //
  1677. // retrieve the interface whose binding is to be read
  1678. //
  1679. pite = GetIfByListIndex(pQuery->IfIndex, dwGetMode, &Error);
  1680. //
  1681. // if the interface was found, it may mean that the index
  1682. // specified was invalid, or it may mean that a GETMODE_NEXT
  1683. // retrieval was attempted on the last interface, in which case
  1684. // ERROR_NO_MORE_ITEMS would have been returned.
  1685. //
  1686. if (pite == NULL) {
  1687. if (dwCount>0)
  1688. Error = NO_ERROR;
  1689. // count==0
  1690. else {
  1691. if (Error == NO_ERROR)
  1692. Error = ERROR_INVALID_PARAMETER;
  1693. *pdwOutputSize = 0;
  1694. }
  1695. break; //from for loop
  1696. }
  1697. // dont have to take the interface lock, as IfLists lock is
  1698. // taken before bindings are changed.
  1699. //
  1700. // compute the size of the interface binding retrieved,
  1701. // and write it over the caller's supplied size
  1702. //
  1703. pBindingSrc = pite->pBinding;
  1704. dwSizeCur = (pBindingSrc
  1705. ? sizeof(IGMP_MIB_IF_BINDING)
  1706. +pBindingSrc->AddrCount*(sizeof(IGMP_MIB_IP_ADDRESS))
  1707. : sizeof(IGMP_MIB_IF_BINDING));
  1708. //
  1709. // if no buffer was specified, indicate one should be allocated
  1710. //
  1711. if (pResponse == NULL) {
  1712. Error = ERROR_INSUFFICIENT_BUFFER;
  1713. break; //for loop
  1714. }
  1715. //
  1716. // if the buffer is not large enough,
  1717. // indicate that it should be enlarged
  1718. //
  1719. if (dwBufferSize < dwSize + dwSizeCur) {
  1720. if (dwCount==0)
  1721. Error = ERROR_INSUFFICIENT_BUFFER;
  1722. break; //from for loop
  1723. }
  1724. //
  1725. // copy the binding
  1726. //
  1727. if (pBindingSrc!=NULL) {
  1728. pBindingDst->AddrCount = pBindingSrc->AddrCount;
  1729. CopyMemory(pBindingDst+1, pBindingSrc+1,
  1730. pBindingSrc->AddrCount*(sizeof(IGMP_MIB_IP_ADDRESS)));
  1731. }
  1732. else {
  1733. pBindingDst->AddrCount = 0;
  1734. }
  1735. pBindingDst->IfIndex = pite->IfIndex;
  1736. pBindingDst->IfType = GET_EXTERNAL_IF_TYPE(pite);
  1737. GET_EXTERNAL_IF_STATE(pite, pBindingDst->State);
  1738. pQuery->IfIndex = pite->IfIndex;
  1739. pQuery->RasClientAddr = 0;
  1740. dwCount++;
  1741. dwSize += dwSizeCur;
  1742. pBindingDst = (PIGMP_MIB_IF_BINDING) ((PBYTE)pBindingDst + dwSizeCur);
  1743. // if GetMode==GETMODE_FIRST change it to GETMODE_NEXT.
  1744. if (dwGetMode==GETMODE_FIRST)
  1745. dwGetMode = GETMODE_NEXT;
  1746. }//end for loop
  1747. //set size if bindings have been copied. else it has already been set
  1748. if (dwCount>0) {
  1749. *pdwOutputSize = dwSize;
  1750. }
  1751. else {
  1752. *pdwOutputSize = dwSizeCur;
  1753. }
  1754. if (pResponse!=NULL) {
  1755. pResponse->Count = dwCount;
  1756. }
  1757. RELEASE_IF_LIST_LOCK("_MibGetInternalBindings");
  1758. Trace0(MIB, "Leaving _MibGetInternalIfBinding");
  1759. return Error;
  1760. } //end _MibGetInternalIfBindings
  1761. //------------------------------------------------------------------------------
  1762. // _MibGetInternalGroupIfsInfo
  1763. //------------------------------------------------------------------------------
  1764. DWORD
  1765. MibGetInternalGroupIfsInfo (
  1766. PIGMP_MIB_GET_INPUT_DATA pQuery,
  1767. PIGMP_MIB_GET_OUTPUT_DATA pResponse,
  1768. PDWORD pdwOutputSize,
  1769. DWORD dwGetMode,
  1770. DWORD dwBufferSize
  1771. )
  1772. {
  1773. LONGLONG llCurTime = GetCurrentIgmpTime();
  1774. BOOL bRasTableLock=FALSE, bGroupBucketLock=FALSE;
  1775. PIGMP_MIB_GROUP_IFS_LIST pHeader;
  1776. PMIB_GROUP_INFO_V3 pGIInfo;
  1777. PGI_ENTRY pgie;
  1778. PLIST_ENTRY pHead, ple;
  1779. DWORD dwSize, dwCurSize, Error=NO_ERROR, dwCount, dwNumIfs, i;
  1780. DWORD PrevGroup, Group, dwNumIfsCopied;
  1781. PRAS_TABLE_ENTRY prte;
  1782. PRAS_TABLE prt, prtOld;
  1783. PGROUP_TABLE_ENTRY pge;
  1784. BOOL bEnumV3;
  1785. //Trace3(MEM, "_MibGetInternalGroupIfsInfo buffer: %0x -> %0x: %d",
  1786. //(DWORD)pResponse->Buffer, ((DWORD)pResponse->Buffer)+dwBufferSize, dwBufferSize);//deldel
  1787. Trace0(MIB, "Entering _MibGetInternalGroupIfsInfo()");
  1788. bEnumV3 = pQuery->Flags & IGMP_ENUM_SUPPORT_FORMAT_IGMPV3;
  1789. //
  1790. // The data returned for each Interface is variable length
  1791. //
  1792. if (pResponse!=NULL) {
  1793. pResponse->TypeId = IGMP_GROUP_IFS_LIST_ID;
  1794. pHeader = (PIGMP_MIB_GROUP_IFS_LIST) pResponse->Buffer;
  1795. //
  1796. // if GETMODE_FIRST: merge the new and main group lists
  1797. //
  1798. if (dwGetMode==GETMODE_FIRST) {
  1799. ACQUIRE_GROUP_LIST_LOCK("_MibGetInternalGroupIfsInfo");
  1800. MergeGroupLists();
  1801. RELEASE_GROUP_LIST_LOCK("_MibGetInternalGroupIfsInfo");
  1802. }
  1803. }
  1804. PrevGroup = pQuery->GroupAddr;
  1805. for (dwCount=0, dwSize=0; dwCount<pQuery->Count; ) {
  1806. ACQUIRE_GROUP_LIST_LOCK("_MibGetInternalGroupIfsInfo");
  1807. bRasTableLock = FALSE;
  1808. //
  1809. // retrieve the groups whose information is to be retrieved
  1810. //
  1811. pge = GetGroupByAddr(PrevGroup, dwGetMode, &Error);
  1812. if (pge == NULL) {
  1813. if (dwCount>0)
  1814. Error = NO_ERROR;
  1815. else {
  1816. if (Error==NO_ERROR)
  1817. Error = ERROR_INVALID_PARAMETER;
  1818. *pdwOutputSize = 0;
  1819. }
  1820. RELEASE_GROUP_LIST_LOCK("_MibGetInternalGroupIfsInfo");
  1821. break;
  1822. }
  1823. Group = pge->Group;
  1824. if (!IS_MCAST_ADDR(Group)) {
  1825. Trace0(ERR, "==========================================================");
  1826. Trace2(ERR, "bad group(%d.%d.%d.%d)(pge:%0x) MibGetInternalGroupIfsInfo",
  1827. PRINT_IPADDR(pge->Group), (ULONG_PTR)pge);
  1828. Trace0(ERR, "==========================================================");
  1829. IgmpAssert(FALSE);
  1830. }
  1831. RELEASE_GROUP_LIST_LOCK("_MibGetInternalGroupIfsInfo");
  1832. //
  1833. // have to release the group list lock before I acquire the group bucket
  1834. // lock to prevent deadlock.
  1835. //
  1836. //
  1837. // take group bucket lock
  1838. //
  1839. ACQUIRE_GROUP_LOCK(Group, "_MibGetInternalGroupIfsInfo");
  1840. bGroupBucketLock = TRUE;
  1841. // get the group again as it could have been deleted.
  1842. pge = GetGroupFromGroupTable (Group, NULL, 0);
  1843. // if the group has been meanwhile deleted, then continue
  1844. if (pge==NULL) {
  1845. RELEASE_GROUP_LOCK(Group, "_MibGetInternalGroupIfsInfo");
  1846. bGroupBucketLock = FALSE;
  1847. continue;
  1848. }
  1849. //
  1850. // compute the size of the data returned
  1851. //
  1852. dwNumIfs = pge->NumVifs;
  1853. if (bEnumV3) {
  1854. pHead = &pge->ListOfGIs;
  1855. dwCurSize = sizeof(IGMP_MIB_GROUP_IFS_LIST) +
  1856. dwNumIfs*sizeof(MIB_GROUP_INFO_V3);
  1857. i = 0;
  1858. for (ple=pHead->Flink; (ple!=pHead)&&(i<dwNumIfs);
  1859. ple=ple->Flink,i++)
  1860. {
  1861. pgie = CONTAINING_RECORD(ple, GI_ENTRY, LinkByGI);
  1862. if (pgie->Version==3) {
  1863. dwCurSize += ( (pgie->NumSources +
  1864. ListLength(&pgie->V3ExclusionList))
  1865. *sizeof(IGMP_MIB_GROUP_SOURCE_INFO_V3) );
  1866. }
  1867. }
  1868. }
  1869. else {
  1870. dwCurSize = sizeof(IGMP_MIB_GROUP_IFS_LIST) +
  1871. dwNumIfs*sizeof(IGMP_MIB_GROUP_INFO);
  1872. if (pResponse == NULL) {
  1873. Error = ERROR_INSUFFICIENT_BUFFER;
  1874. break;
  1875. }
  1876. }
  1877. //
  1878. // if the buffer is not large enough, break from the loop
  1879. //
  1880. if (dwBufferSize < dwSize + dwCurSize) {
  1881. if (dwCount==0)
  1882. Error = ERROR_INSUFFICIENT_BUFFER;
  1883. break;//from for loop
  1884. }
  1885. // set fields for group info
  1886. pHeader->GroupAddr = pge->Group;
  1887. pHeader->NumInterfaces = dwNumIfs;
  1888. //
  1889. // set groupAddr in pQuery so that in the next query, the info for other groups will
  1890. // be passed
  1891. //
  1892. pQuery->GroupAddr = pge->Group;
  1893. //
  1894. // copy stats for interfaces that have joined the group.
  1895. //
  1896. pGIInfo = (PMIB_GROUP_INFO_V3)pHeader->Buffer;
  1897. pHead = &pge->ListOfGIs;
  1898. dwNumIfsCopied = 0;
  1899. for (ple=pHead->Flink; (ple!=pHead)&&(dwNumIfsCopied<dwNumIfs);
  1900. ple=ple->Flink,dwNumIfsCopied++)
  1901. {
  1902. DWORD GIVersion;
  1903. pgie = CONTAINING_RECORD(ple, GI_ENTRY, LinkByGI);
  1904. GIVersion = pgie->Version;
  1905. pGIInfo->IfIndex = pgie->IfIndex;
  1906. //
  1907. // if rasServerIf, then I return the NHAddr in IpAddr field
  1908. // else return the IpAddr of this field
  1909. //
  1910. pGIInfo->IpAddr = (IS_RAS_SERVER_IF(pgie->pIfTableEntry->IfType))
  1911. ? pgie->NHAddr
  1912. : pgie->pIfTableEntry->IpAddr;
  1913. pGIInfo->GroupExpiryTime
  1914. = (pgie->Info.GroupExpiryTime==~0)
  1915. ? ~0
  1916. : SYSTEM_TIME_TO_SEC(pgie->Info.GroupExpiryTime-llCurTime);
  1917. pGIInfo->LastReporter = pgie->Info.LastReporter;
  1918. pGIInfo->GroupUpTime =
  1919. SYSTEM_TIME_TO_SEC(llCurTime-pgie->Info.GroupUpTime);
  1920. if (llCurTime<pgie->Info.V1HostPresentTimeLeft)
  1921. pGIInfo->V1HostPresentTimeLeft =
  1922. SYSTEM_TIME_TO_SEC(pgie->Info.V1HostPresentTimeLeft-llCurTime);
  1923. else
  1924. pGIInfo->V1HostPresentTimeLeft = 0;
  1925. if ( llCurTime>=pgie->Info.V2HostPresentTimeLeft)
  1926. pGIInfo->V2HostPresentTimeLeft = 0;
  1927. else {
  1928. pGIInfo->V2HostPresentTimeLeft =
  1929. SYSTEM_TIME_TO_SEC(pgie->Info.V2HostPresentTimeLeft-llCurTime);
  1930. }
  1931. pGIInfo->Flags = 0;
  1932. if (pgie->bStaticGroup)
  1933. pGIInfo->Flags |= IGMP_GROUP_TYPE_STATIC;
  1934. if (pgie->GroupMembershipTimer.Status&TIMER_STATUS_ACTIVE)
  1935. pGIInfo->Flags |= IGMP_GROUP_TYPE_NON_STATIC;
  1936. if (CAN_ADD_GROUPS_TO_MGM(pgie->pIfTableEntry))
  1937. pGIInfo->Flags |= IGMP_GROUP_FWD_TO_MGM;
  1938. if (bEnumV3) {
  1939. PGI_SOURCE_ENTRY pSourceEntry;
  1940. DWORD i, V3NumSources, V3SourcesSize;
  1941. PLIST_ENTRY pHeadSrc, pLESrc;
  1942. V3NumSources = pgie->NumSources + ListLength(&pgie->V3ExclusionList);
  1943. V3SourcesSize = sizeof(IGMP_MIB_GROUP_SOURCE_INFO_V3)*V3NumSources;
  1944. pGIInfo->Version = pgie->Version;
  1945. pGIInfo->Size = sizeof(MIB_GROUP_INFO_V3) + V3SourcesSize;
  1946. pGIInfo->FilterType = pgie->FilterType;
  1947. pGIInfo->NumSources = V3NumSources;
  1948. pHeadSrc = &pgie->V3InclusionListSorted;
  1949. i = 0;
  1950. for (pLESrc=pHeadSrc->Flink; pLESrc!=pHeadSrc; pLESrc=pLESrc->Flink,i++) {
  1951. pSourceEntry = CONTAINING_RECORD(pLESrc, GI_SOURCE_ENTRY,
  1952. LinkSourcesInclListSorted);
  1953. pGIInfo->Sources[i].Source = pSourceEntry->IpAddr;
  1954. pGIInfo->Sources[i].SourceExpiryTime
  1955. = (pSourceEntry->bInclusionList)
  1956. ? QueryRemainingTime(&pSourceEntry->SourceExpTimer, 0)
  1957. : ~0;
  1958. pGIInfo->Sources[i].SourceUpTime
  1959. = (DWORD)(llCurTime - pSourceEntry->SourceInListTime)/1000;
  1960. }
  1961. pHeadSrc = &pgie->V3ExclusionList;
  1962. for (pLESrc=pHeadSrc->Flink; pLESrc!=pHeadSrc; pLESrc=pLESrc->Flink,i++){
  1963. pSourceEntry = CONTAINING_RECORD(pLESrc, GI_SOURCE_ENTRY, LinkSources);
  1964. pGIInfo->Sources[i].Source = pSourceEntry->IpAddr;
  1965. pGIInfo->Sources[i].SourceExpiryTime
  1966. = (pSourceEntry->bInclusionList)
  1967. ? QueryRemainingTime(&pSourceEntry->SourceExpTimer, 0)
  1968. : ~0;
  1969. pGIInfo->Sources[i].SourceUpTime
  1970. = (DWORD)(llCurTime - pSourceEntry->SourceInListTime)/1000;
  1971. }
  1972. pGIInfo = (PMIB_GROUP_INFO_V3)
  1973. ((PCHAR)pGIInfo + pGIInfo->Size);
  1974. //Trace1(MEM, "NextPGIInfo: %0x:", (DWORD)pGIInfo);//deldel
  1975. }
  1976. else {
  1977. pGIInfo = (PMIB_GROUP_INFO_V3)((PMIB_GROUP_INFO)pGIInfo + 1);
  1978. //Trace1(MEM, "NextPGIInfo: %0x:", (DWORD)pGIInfo);//deldel
  1979. }
  1980. }
  1981. //
  1982. // everything fine. Copied one more stats struct
  1983. //
  1984. dwCount++;
  1985. dwSize += dwCurSize;
  1986. pHeader = (PIGMP_MIB_GROUP_IFS_LIST) pGIInfo;
  1987. PrevGroup = pge->Group;
  1988. // release the group bucket lock
  1989. RELEASE_GROUP_LOCK(Group, "_MibGetInternalGroupIfsInfo");
  1990. bGroupBucketLock = FALSE;
  1991. // if GetMode==GETMODE_FIRST change it to GETMODE_NEXT.
  1992. if (dwGetMode==GETMODE_FIRST)
  1993. dwGetMode = GETMODE_NEXT;
  1994. } //end for loop
  1995. // check if group bucket lock has to be released
  1996. if (bGroupBucketLock==TRUE) {
  1997. RELEASE_GROUP_LOCK(Group, "_MibGetInternalGroupIfsInfo");
  1998. bGroupBucketLock = FALSE;
  1999. }
  2000. if (pResponse!=NULL) {
  2001. pResponse->Count = dwCount;
  2002. pResponse->Flags |= IGMP_ENUM_FORMAT_IGMPV3;
  2003. }
  2004. //
  2005. // set the actual size if some info was copied, else let size
  2006. // remain
  2007. //
  2008. if (dwCount>0)
  2009. *pdwOutputSize = dwSize;
  2010. else
  2011. *pdwOutputSize = dwCurSize;
  2012. Trace0(MIB, "Leaving _MibGetInternalGroupIfsInfo");
  2013. return Error;
  2014. } //end _MibGetInternalGroupIfsInfo
  2015. //------------------------------------------------------------------------------
  2016. // _MibGetInternalIfConfig
  2017. //
  2018. // no locks assumed. takes IfList lock
  2019. //------------------------------------------------------------------------------
  2020. DWORD
  2021. MibGetInternalIfConfig (
  2022. PIGMP_MIB_GET_INPUT_DATA pQuery,
  2023. PIGMP_MIB_GET_OUTPUT_DATA pResponse,
  2024. PDWORD pdwOutputSize,
  2025. DWORD dwGetMode,
  2026. DWORD dwBufferSize
  2027. )
  2028. {
  2029. //
  2030. // the interface config struct is variable size.
  2031. // there may be multiple instances.
  2032. //
  2033. PIGMP_IF_TABLE pTable = g_pIfTable;
  2034. PIF_TABLE_ENTRY pite;
  2035. PIGMP_MIB_IF_CONFIG pIfConfigDst;
  2036. PIGMP_IF_CONFIG pIfConfigSrc;
  2037. DWORD dwCount, dwSize, dwSizeCur=0, Error = NO_ERROR;
  2038. if (pResponse!=NULL) {
  2039. pResponse->TypeId = IGMP_IF_CONFIG_ID;
  2040. pIfConfigDst = (PIGMP_MIB_IF_CONFIG)pResponse->Buffer;
  2041. }
  2042. // acquire IfLists lock so that you can access the interface lists
  2043. ACQUIRE_IF_LIST_LOCK("MibGetInternalIfConfig");
  2044. for (dwCount=0,dwSize=0; dwCount<pQuery->Count; ) {
  2045. //
  2046. // retrieve the interface whose config are to be read
  2047. //
  2048. pite = GetIfByListIndex(pQuery->IfIndex, dwGetMode, &Error);
  2049. // I dont have to take the interface lock, as the IfLists lock is
  2050. // taken before interface config is changed or interface is deleted.
  2051. //ACQUIRE_IF_LOCK_SHARED(IfIndex, "MibGetInternal");
  2052. //
  2053. // if the interface was not found, it may mean
  2054. // the specified index was invalid, or it may mean
  2055. // that the GETMODE_NEXT was called on the last interface
  2056. // in which case ERROR_NO_MORE_ITEMS was returned.
  2057. // In any case, we make sure Error indicates an error
  2058. // and then return the value.
  2059. //
  2060. // if the interface was found but no output buffer was passed,
  2061. // indicate in the error that memory needs to be allocated.
  2062. //
  2063. // otherwise, copy the config struct of the interface
  2064. //
  2065. if (pite == NULL) {
  2066. if (dwCount>0) {
  2067. Error = NO_ERROR;
  2068. }
  2069. // count==0
  2070. else {
  2071. if (Error == NO_ERROR)
  2072. Error = ERROR_INVALID_PARAMETER;
  2073. *pdwOutputSize = 0;
  2074. }
  2075. break; //from for loop
  2076. }
  2077. pIfConfigSrc = &pite->Config;
  2078. dwSizeCur = pIfConfigSrc->ExtSize;
  2079. //
  2080. // if no buffer was specified, indicate one should be allocated
  2081. //
  2082. if (pResponse==NULL) {
  2083. Error = ERROR_INSUFFICIENT_BUFFER;
  2084. break;
  2085. }
  2086. //
  2087. // see if adequate buffer is left for the next struct
  2088. //
  2089. if (dwBufferSize < dwSize+dwSizeCur) {
  2090. if (dwCount==0) {
  2091. Error = ERROR_INSUFFICIENT_BUFFER;
  2092. }
  2093. break;//from for loop
  2094. }
  2095. //
  2096. // copy the interface config, and set the IP address
  2097. //
  2098. CopyoutIfConfig(pIfConfigDst, pite);
  2099. pQuery->IfIndex = pite->IfIndex;
  2100. pQuery->RasClientAddr = 0;
  2101. dwCount++;
  2102. dwSize += dwSizeCur;
  2103. pIfConfigDst = (PIGMP_MIB_IF_CONFIG) (((PBYTE)pIfConfigDst)+ dwSizeCur);
  2104. // if GetMode==GETMODE_FIRST change it to GETMODE_NEXT.
  2105. if (dwGetMode==GETMODE_FIRST)
  2106. dwGetMode = GETMODE_NEXT;
  2107. }//end for loop
  2108. //
  2109. //set the actual size if some info was copied, else let size set earlier
  2110. //remain
  2111. //
  2112. if (dwCount>0) {
  2113. *pdwOutputSize = dwSize;
  2114. }
  2115. else {
  2116. *pdwOutputSize = dwSizeCur;
  2117. }
  2118. if (pResponse!=NULL)
  2119. pResponse->Count = dwCount;
  2120. RELEASE_IF_LIST_LOCK("_MibGetInternalIfConfig");
  2121. Trace0(MIB, "Leaving _MibGetInternalIfConfig");
  2122. return Error;
  2123. } //end _MibGetInternalIfConfig
  2124. //------------------------------------------------------------------------------
  2125. // _MibGetInternalIfGroupsInfo
  2126. //
  2127. // Enumerates the list of GIs hanging from an interface
  2128. // Locks: no locks assumed.
  2129. //------------------------------------------------------------------------------
  2130. DWORD
  2131. MibGetInternalIfGroupsInfo (
  2132. PIGMP_MIB_GET_INPUT_DATA pQuery,
  2133. PIGMP_MIB_GET_OUTPUT_DATA pResponse,
  2134. PDWORD pdwOutputSize,
  2135. DWORD dwGetMode,
  2136. DWORD dwBufferSize
  2137. )
  2138. {
  2139. LONGLONG llCurTime = GetCurrentIgmpTime();
  2140. PIGMP_MIB_IF_GROUPS_LIST pHeader;
  2141. PMIB_GROUP_INFO_V3 pGroupInfo;
  2142. PMIB_PROXY_GROUP_INFO_V3 pProxyGroupInfo;
  2143. PGI_ENTRY pgie;
  2144. PLIST_ENTRY pHead, ple;
  2145. DWORD dwCurSize=0, Error=NO_ERROR, dwNumGroups,
  2146. dwNumIfGroups, dwNumGroupsCopied, SizeofGroupEntry,
  2147. PrevQueryFlags = pQuery->Flags;
  2148. PIF_TABLE_ENTRY pite;
  2149. PRAS_TABLE_ENTRY prte;
  2150. PRAS_TABLE prt;
  2151. BOOL bCopied, bProxy=FALSE,
  2152. bRasClientEnum=FALSE, bRasServerEnum=FALSE, bRasIfLock=FALSE;
  2153. DWORD lePrevGroup = NETWORK_TO_LITTLE_ENDIAN(pQuery->GroupAddr);
  2154. USHORT PrevEnumSignature = pQuery->Signature;
  2155. BOOL bEnumV3, bInsufficientBuffer=FALSE;
  2156. //kslksl
  2157. PPROXY_GROUP_ENTRY pProxyEntry;
  2158. PLIST_ENTRY pHeadSrc, pleSrc;
  2159. DWORD SrcCnt;
  2160. PPROXY_SOURCE_ENTRY pSourceEntry;
  2161. //Trace3(MEM, "_MibGetInternalIfGroupsInfo buffer: %0x -> %0x: %d",
  2162. //(DWORD)pResponse->Buffer, ((DWORD)pResponse->Buffer)+dwBufferSize, dwBufferSize);//deldel
  2163. Trace0(MIB, "Entering _MibGetInternalIfGroupsInfo()");
  2164. bEnumV3 = PrevQueryFlags & IGMP_ENUM_SUPPORT_FORMAT_IGMPV3;
  2165. CLEAR_IGMP_ENUM_INTERFACE_TABLE_FLAGS(pQuery->Flags);
  2166. if ( (PrevQueryFlags & IGMP_ENUM_INTERFACE_TABLE_END)
  2167. && !(PrevQueryFlags & IGMP_ENUM_ALL_INTERFACES_GROUPS)
  2168. && !(PrevQueryFlags & IGMP_ENUM_FOR_RAS_CLIENTS) )
  2169. {
  2170. pQuery->GroupAddr = 0;
  2171. pQuery->Signature = 0;
  2172. return ERROR_NO_MORE_ITEMS;
  2173. }
  2174. //
  2175. // Initialize
  2176. //
  2177. if (pResponse!=NULL) {
  2178. pResponse->TypeId = IGMP_IF_GROUPS_LIST_ID;
  2179. pHeader = (PIGMP_MIB_IF_GROUPS_LIST) pResponse->Buffer;
  2180. }
  2181. //
  2182. // acquire IfLists lock so that the interfaces list can be accessed
  2183. //
  2184. ACQUIRE_IF_LIST_LOCK("_MibGetInternalIfGroupsInfo");
  2185. //
  2186. // retrieve the interface (and ras client)
  2187. //
  2188. if (PrevQueryFlags & IGMP_ENUM_FOR_RAS_CLIENTS) {
  2189. if (pQuery->IfIndex==0)
  2190. pQuery->IfIndex = g_RasIfIndex;
  2191. Error = GetIfOrRasForEnum(pQuery, pResponse, dwGetMode,
  2192. &pite, &prt, &prte, &bRasIfLock,
  2193. IGMP_ENUM_FOR_RAS_CLIENTS);
  2194. }
  2195. else if ( (PrevQueryFlags & IGMP_ENUM_INTERFACE_TABLE_CONTINUE)
  2196. || ((pQuery->IfIndex!=0)&&(pQuery->GroupAddr!=0)&&
  2197. (!(PrevQueryFlags & IGMP_ENUM_INTERFACE_TABLE_END)) ) )
  2198. {
  2199. // continuing from the previous call. so get the same interface again.
  2200. Error = GetIfOrRasForEnum(pQuery, pResponse, GETMODE_EXACT,
  2201. &pite, &prt, &prte, &bRasIfLock, 0);
  2202. //
  2203. // if the interface has meanwhile been deleted, then get the next interface
  2204. // only if all interface group lists are being enumerated.
  2205. //
  2206. if ( (pite==NULL) && (pQuery->Flags&IGMP_ENUM_ALL_INTERFACES_GROUPS) ) {
  2207. // the interface was deleted. so I continue with the next interface
  2208. Error = GetIfOrRasForEnum(pQuery, pResponse, GETMODE_NEXT,
  2209. &pite, &prt, &prte, &bRasIfLock, 0);
  2210. if (pResponse) {
  2211. pResponse->Flags |= IGMP_ENUM_INTERFACE_TABLE_BEGIN;
  2212. pQuery->Flags |= IGMP_ENUM_INTERFACE_TABLE_BEGIN;
  2213. }
  2214. }
  2215. }
  2216. else {
  2217. // enumerating a new interface
  2218. Error = GetIfOrRasForEnum(pQuery, pResponse, dwGetMode,
  2219. &pite, &prt, &prte, &bRasIfLock, 0);
  2220. if (pResponse) {
  2221. pResponse->Flags |= IGMP_ENUM_INTERFACE_TABLE_BEGIN;
  2222. pQuery->Flags |= IGMP_ENUM_INTERFACE_TABLE_BEGIN;
  2223. }
  2224. }
  2225. //
  2226. // The required interface or the next interface not found. Return error.
  2227. //
  2228. if (pite == NULL) {
  2229. //
  2230. // GetIfOrRasForEnum returns no_error if there are no interfaces.
  2231. // but I will return invalid_parameter
  2232. //
  2233. if (Error == NO_ERROR)
  2234. Error = ERROR_INVALID_PARAMETER;
  2235. *pdwOutputSize = 0;
  2236. if (pResponse)
  2237. pResponse->Count = 0;
  2238. RELEASE_IF_LIST_LOCK("_MibGetInternalIfGroupsInfo");
  2239. Trace1(MIB, "Leaving _MibGetInternalIfGroupsInfo(%d)", Error);
  2240. return Error;
  2241. }
  2242. //
  2243. // get the shared interface lock so that its fields can no longer be
  2244. // changed. As IF_LISTS lock is taken, the inteface state cannot get changed
  2245. //
  2246. if (!bRasIfLock)
  2247. ACQUIRE_IF_LOCK_SHARED(pite->IfIndex, "_MibGetInternalIfGroupsInfo");
  2248. ACQUIRE_ENUM_LOCK_EXCLUSIVE("_MibGetInternalIfGroupsInfo");
  2249. bRasClientEnum = prte != NULL;
  2250. bRasServerEnum = IS_RAS_SERVER_IF(pite->IfType) && !bRasClientEnum;
  2251. bEnumV3 = bEnumV3 && (IS_PROTOCOL_TYPE_IGMPV3(pite)||IS_PROTOCOL_TYPE_PROXY(pite));
  2252. BEGIN_BREAKOUT_BLOCK1 {
  2253. bProxy = IS_PROTOCOL_TYPE_PROXY(pite);
  2254. // set size for groupEntry
  2255. SizeofGroupEntry = (bProxy)
  2256. ? (bEnumV3?sizeof(MIB_PROXY_GROUP_INFO_V3):sizeof(MIB_PROXY_GROUP_INFO))
  2257. : (bEnumV3?sizeof(MIB_GROUP_INFO_V3):sizeof(IGMP_MIB_GROUP_INFO));
  2258. //
  2259. // if no buffer passed or buffer less than that required for 1 group entry,
  2260. // set the required buffer size to MIB_DEFAULT_BUFFER_SIZE and break.
  2261. //
  2262. if ( (pResponse==NULL)
  2263. || (!bEnumV3 && !bRasClientEnum&&
  2264. (dwBufferSize < sizeof(IGMP_MIB_IF_GROUPS_LIST) + SizeofGroupEntry))
  2265. || (!bEnumV3 && bRasClientEnum
  2266. &&(dwBufferSize<sizeof(IGMP_MIB_IF_GROUPS_LIST)
  2267. + SizeofGroupEntry*prte->Info.CurrentGroupMemberships) )
  2268. || (bEnumV3 && (dwBufferSize<MIB_DEFAULT_BUFFER_SIZE)) )
  2269. {
  2270. Error = ERROR_INSUFFICIENT_BUFFER;
  2271. if (bEnumV3) {
  2272. dwCurSize = MIB_DEFAULT_BUFFER_SIZE;
  2273. }
  2274. else {
  2275. dwCurSize = (pQuery->Flags&IGMP_ENUM_ONE_ENTRY)
  2276. ? sizeof(IGMP_MIB_IF_GROUPS_LIST) + sizeof(IGMP_MIB_GROUP_INFO)
  2277. : bRasClientEnum
  2278. ? sizeof(IGMP_MIB_IF_GROUPS_LIST)
  2279. + SizeofGroupEntry*(prte->Info.CurrentGroupMemberships+5)
  2280. : MIB_DEFAULT_BUFFER_SIZE;
  2281. }
  2282. // dont change pQuery->GroupAddr
  2283. bCopied = FALSE;
  2284. bInsufficientBuffer = TRUE;
  2285. GOTO_END_BLOCK1;
  2286. }
  2287. //
  2288. // set dwNumIfGroups
  2289. //
  2290. if (!IS_IF_ACTIVATED(pite)) {
  2291. dwNumIfGroups = 0;
  2292. }
  2293. else {
  2294. if (bProxy) {
  2295. dwNumIfGroups = pite->Info.CurrentGroupMemberships;
  2296. }
  2297. //
  2298. // if no ras client stats (if flag not set in the query, or ras
  2299. // stats not being kept).
  2300. //
  2301. else if ( bRasClientEnum && !g_Config.RasClientStats )
  2302. {
  2303. dwNumIfGroups = 0;
  2304. }
  2305. else {
  2306. dwNumIfGroups = (bRasClientEnum)
  2307. ? prte->Info.CurrentGroupMemberships
  2308. : pite->Info.CurrentGroupMemberships;
  2309. }
  2310. }
  2311. //
  2312. // calculate how many group entries will fit in the buffer left.
  2313. // dwNumGroups cannot be greater than dwNumIfGroups and
  2314. // enumerate only 1 group if IGMP_ENUM_ONE_ENTRY flag set.
  2315. //
  2316. // note: dwNumGroups can be 0, only if dwNumIfGroups is 0
  2317. dwNumGroups = bEnumV3? 100
  2318. : (dwBufferSize - sizeof(IGMP_MIB_IF_GROUPS_LIST))
  2319. / SizeofGroupEntry;
  2320. dwNumGroups = MIN(dwNumIfGroups, dwNumGroups);
  2321. if (pQuery->Flags&IGMP_ENUM_ONE_ENTRY)
  2322. dwNumGroups = MIN(dwNumGroups, 1);
  2323. // initialize size required for this interface groups
  2324. dwCurSize = sizeof(IGMP_MIB_IF_GROUPS_LIST);
  2325. //
  2326. // set fields in the Interface header that will be returned to the caller
  2327. //
  2328. pHeader->IfIndex = pite->IfIndex;
  2329. if (bRasClientEnum) {
  2330. pHeader->IpAddr = prte->NHAddr;
  2331. pHeader->IfType = IGMP_IF_RAS_CLIENT;
  2332. }
  2333. else {
  2334. pHeader->IpAddr = pite->IpAddr;
  2335. pHeader->IfType = GET_EXTERNAL_IF_TYPE(pite);
  2336. }
  2337. //
  2338. // set fields in pQuery
  2339. //
  2340. pQuery->IfIndex = pite->IfIndex;
  2341. pQuery->RasClientAddr = (bRasClientEnum) ? prte->NHAddr : 0;
  2342. //
  2343. // if not activated, just copy the interface header and return with 0 groups
  2344. //
  2345. if (!IS_IF_ACTIVATED(pite)) {
  2346. dwNumGroupsCopied = 0;
  2347. // set pQuery fields
  2348. pQuery->GroupAddr = 0;
  2349. pQuery->Flags |= (IGMP_ENUM_INTERFACE_TABLE_BEGIN
  2350. | IGMP_ENUM_INTERFACE_TABLE_END);
  2351. pResponse->Flags |= (IGMP_ENUM_INTERFACE_TABLE_BEGIN
  2352. | IGMP_ENUM_INTERFACE_TABLE_END);
  2353. // set interface header fields
  2354. pHeader->NumGroups = 0;
  2355. dwCurSize = sizeof(IGMP_MIB_IF_GROUPS_LIST);
  2356. bCopied = TRUE;
  2357. GOTO_END_BLOCK1;
  2358. }
  2359. ACQUIRE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_MibGetInternalIfGroupsInfo");
  2360. ple = NULL;
  2361. //--------------------------------------------------
  2362. // if interface not proxy, then copy the group info.
  2363. //---------------------------------------------------
  2364. if (!bProxy) {
  2365. pGroupInfo = (PMIB_GROUP_INFO_V3)(pHeader->Buffer);
  2366. // merge the lists if this interface is being enumerated for the first time.
  2367. if (lePrevGroup==0)
  2368. MergeIfGroupsLists(pite);
  2369. pHead = (bRasClientEnum) ? &prte->ListOfSameClientGroups
  2370. : &pite->ListOfSameIfGroups;
  2371. // if continuing enumeration, then walk down to the next group
  2372. // ras client wont get into this block
  2373. if (lePrevGroup!=0) {
  2374. //
  2375. // get next entry from where we left off last time
  2376. //
  2377. if ( (PrevEnumSignature==pite->PrevIfGroupEnumSignature)
  2378. && (PrevEnumSignature!=0) ){
  2379. // had reached end of enumeration
  2380. if (pite->pPrevIfGroupEnumPtr==NULL)
  2381. dwNumGroups = 0;
  2382. else
  2383. ple = &((PGI_ENTRY)pite->pPrevIfGroupEnumPtr)->LinkBySameIfGroups;
  2384. }
  2385. //
  2386. // get next entry by searching through the list
  2387. //
  2388. else {
  2389. for (ple=pHead->Flink; (ple!=pHead); ple=ple->Flink) {
  2390. pgie = CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameIfGroups);
  2391. if (lePrevGroup<pgie->pGroupTableEntry->GroupLittleEndian)
  2392. break;
  2393. }
  2394. }
  2395. }
  2396. //
  2397. // starting enumeration from the beginning of the list
  2398. //
  2399. else {
  2400. ple = pHead->Flink;
  2401. }
  2402. //
  2403. // finally copy the groups(!proxy)
  2404. //
  2405. dwNumGroupsCopied = 0;
  2406. for ( ; (ple!=pHead)&&(dwNumGroupsCopied<dwNumGroups);
  2407. ple=ple->Flink,dwNumGroupsCopied++)
  2408. {
  2409. PLIST_ENTRY pleNext;
  2410. DWORD LastReporter, GroupUpTime, GroupExpiryTime;
  2411. DWORD V3SourcesSize=0, i;
  2412. DWORD IncrementSize=0, V3NumSources=0;
  2413. pgie = bRasClientEnum
  2414. ? CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameClientGroups)
  2415. : CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameIfGroups);
  2416. if (bEnumV3){
  2417. V3NumSources = pgie->NumSources + ListLength(&pgie->V3ExclusionList);
  2418. V3SourcesSize = sizeof(IGMP_MIB_GROUP_SOURCE_INFO_V3)*V3NumSources;
  2419. }
  2420. IncrementSize = SizeofGroupEntry+V3SourcesSize;
  2421. if (dwCurSize+IncrementSize > dwBufferSize){
  2422. if (dwNumGroupsCopied==0) {
  2423. dwCurSize += IncrementSize;
  2424. bCopied = FALSE;
  2425. bInsufficientBuffer = TRUE;
  2426. }
  2427. break;
  2428. }
  2429. dwCurSize += IncrementSize;
  2430. pGroupInfo->GroupAddr = pgie->pGroupTableEntry->Group;
  2431. pGroupInfo->IpAddr = pgie->pIfTableEntry->IpAddr;
  2432. GroupUpTime = SYSTEM_TIME_TO_SEC(llCurTime-pgie->Info.GroupUpTime);
  2433. GroupExpiryTime = (pgie->Info.GroupExpiryTime==~0)
  2434. ? ~0
  2435. : SYSTEM_TIME_TO_SEC(pgie->Info.GroupExpiryTime-llCurTime);
  2436. LastReporter = pgie->Info.LastReporter;
  2437. if (bRasServerEnum) {
  2438. DWORD GroupExpiryTimeTmp;
  2439. PGI_ENTRY pgieNext;
  2440. for (pleNext=ple->Flink; pleNext!=pHead; pleNext=pleNext->Flink) {
  2441. pgieNext = CONTAINING_RECORD(pleNext, GI_ENTRY, LinkBySameIfGroups);
  2442. if (pgieNext->pGroupTableEntry->Group != pgie->pGroupTableEntry->Group)
  2443. break;
  2444. GroupUpTime = MAX(GroupUpTime,
  2445. SYSTEM_TIME_TO_SEC(llCurTime-pgieNext->Info.GroupUpTime));
  2446. GroupExpiryTimeTmp = (pgieNext->Info.GroupExpiryTime==~0)
  2447. ? ~0
  2448. : SYSTEM_TIME_TO_SEC(pgieNext->Info.GroupExpiryTime-llCurTime);
  2449. if (GroupExpiryTimeTmp > GroupExpiryTime) {
  2450. GroupExpiryTime = GroupExpiryTimeTmp;
  2451. LastReporter = pgieNext->Info.LastReporter;
  2452. }
  2453. }
  2454. ple = pleNext->Blink;
  2455. }
  2456. pGroupInfo->GroupUpTime = GroupUpTime;
  2457. pGroupInfo->GroupExpiryTime = GroupExpiryTime;
  2458. pGroupInfo->LastReporter = LastReporter;
  2459. if ( (llCurTime>=pgie->Info.V1HostPresentTimeLeft) || bRasServerEnum)
  2460. pGroupInfo->V1HostPresentTimeLeft = 0;
  2461. else {
  2462. pGroupInfo->V1HostPresentTimeLeft =
  2463. SYSTEM_TIME_TO_SEC(pgie->Info.V1HostPresentTimeLeft-llCurTime);
  2464. }
  2465. if ( (llCurTime>=pgie->Info.V2HostPresentTimeLeft) || bRasServerEnum)
  2466. pGroupInfo->V2HostPresentTimeLeft = 0;
  2467. else {
  2468. pGroupInfo->V2HostPresentTimeLeft =
  2469. SYSTEM_TIME_TO_SEC(pgie->Info.V2HostPresentTimeLeft-llCurTime);
  2470. }
  2471. pGroupInfo->Flags = 0;
  2472. if ( (pgie->bStaticGroup) && (!bRasServerEnum) )
  2473. pGroupInfo->Flags |= IGMP_GROUP_TYPE_STATIC;
  2474. if ( (pgie->GroupMembershipTimer.Status&TIMER_STATUS_ACTIVE) || (bRasServerEnum) )
  2475. pGroupInfo->Flags |= IGMP_GROUP_TYPE_NON_STATIC;
  2476. if (CAN_ADD_GROUPS_TO_MGM(pite))
  2477. pGroupInfo->Flags |= IGMP_GROUP_FWD_TO_MGM;
  2478. if (bEnumV3) {
  2479. PGI_SOURCE_ENTRY pSourceEntry;
  2480. DWORD i=0;
  2481. PLIST_ENTRY pHeadSrc, pLESrc;
  2482. pGroupInfo->Version = pgie->Version;
  2483. pGroupInfo->Size = sizeof(MIB_GROUP_INFO_V3) + V3SourcesSize;
  2484. pGroupInfo->FilterType = pgie->FilterType;
  2485. pGroupInfo->NumSources = V3NumSources;
  2486. pHeadSrc = &pgie->V3InclusionListSorted;
  2487. for (pLESrc=pHeadSrc->Flink; pLESrc!=pHeadSrc; pLESrc=pLESrc->Flink,i++) {
  2488. pSourceEntry = CONTAINING_RECORD(pLESrc, GI_SOURCE_ENTRY,
  2489. LinkSourcesInclListSorted);
  2490. pGroupInfo->Sources[i].Source = pSourceEntry->IpAddr;
  2491. //kslksl
  2492. ASSERT(pGroupInfo->Sources[i].Source !=0);
  2493. pGroupInfo->Sources[i].SourceExpiryTime
  2494. = (pSourceEntry->bInclusionList)
  2495. ? QueryRemainingTime(&pSourceEntry->SourceExpTimer, 0)
  2496. : ~0;
  2497. pGroupInfo->Sources[i].SourceUpTime
  2498. = (DWORD)(llCurTime - pSourceEntry->SourceInListTime)/1000;
  2499. }
  2500. pHeadSrc = &pgie->V3ExclusionList;
  2501. for (pLESrc=pHeadSrc->Flink; pLESrc!=pHeadSrc; pLESrc=pLESrc->Flink,i++) {
  2502. pSourceEntry = CONTAINING_RECORD(pLESrc, GI_SOURCE_ENTRY, LinkSources);
  2503. pGroupInfo->Sources[i].Source = pSourceEntry->IpAddr;
  2504. pGroupInfo->Sources[i].SourceExpiryTime
  2505. = (pSourceEntry->bInclusionList)
  2506. ? QueryRemainingTime(&pSourceEntry->SourceExpTimer, 0)
  2507. : ~0;
  2508. pGroupInfo->Sources[i].SourceUpTime
  2509. = (DWORD)(llCurTime - pSourceEntry->SourceInListTime)/1000;
  2510. }
  2511. pGroupInfo = (PMIB_GROUP_INFO_V3)
  2512. ((PCHAR)pGroupInfo + pGroupInfo->Size);
  2513. }
  2514. else
  2515. pGroupInfo = (PMIB_GROUP_INFO_V3)((PMIB_GROUP_INFO)pGroupInfo + 1);
  2516. //Trace1(MEM, "NextpGroupInfo:%0x", (DWORD)pGroupInfo);//deldel
  2517. }
  2518. //
  2519. // if reached the end of the group list or the group list is empty
  2520. //
  2521. if (((ple==pHead&&dwNumGroupsCopied!=0) || (dwNumIfGroups==0)||(dwNumGroups==0))
  2522. &&!bInsufficientBuffer && !bRasClientEnum)
  2523. {
  2524. pQuery->Flags |= IGMP_ENUM_INTERFACE_TABLE_END;
  2525. pQuery->GroupAddr = 0;
  2526. // reset pointers for next enumeration
  2527. pite->pPrevIfGroupEnumPtr = NULL;
  2528. pite->PrevIfGroupEnumSignature = 0;
  2529. }
  2530. //
  2531. // else have more GI entries to enumerate
  2532. //
  2533. else if (!bRasClientEnum) {
  2534. pQuery->Flags |= IGMP_ENUM_INTERFACE_TABLE_CONTINUE;
  2535. if (ple!=pHead) {
  2536. PGI_ENTRY pgieNext;
  2537. // get the next entry from which enum should continue
  2538. pgieNext = CONTAINING_RECORD(ple, GI_ENTRY, LinkBySameIfGroups);
  2539. // update pQuery->GroupAddr
  2540. pQuery->GroupAddr = pgieNext->pGroupTableEntry->Group;
  2541. // update pointers for next enumeration
  2542. pite->pPrevIfGroupEnumPtr = pgieNext;
  2543. }
  2544. else {
  2545. pQuery->GroupAddr = 0xffffffff;
  2546. pite->pPrevIfGroupEnumPtr = NULL;
  2547. }
  2548. pite->PrevIfGroupEnumSignature = GET_NEXT_SIGNATURE();
  2549. SET_SIGNATURE(pQuery->Signature, pite->PrevIfGroupEnumSignature);
  2550. }
  2551. }
  2552. //--------------------------
  2553. // proxy interface
  2554. //--------------------------
  2555. else {
  2556. //kslksl
  2557. //PPROXY_GROUP_ENTRY pProxyEntry;
  2558. pProxyGroupInfo = (PMIB_PROXY_GROUP_INFO_V3)(pHeader->Buffer);
  2559. // merge the lists if this interface is being enumerated for the first time.
  2560. if (lePrevGroup==0)
  2561. MergeProxyLists(pite);
  2562. pHead = &pite->ListOfSameIfGroups;
  2563. // if continuing enumeration, then walk down to the next group
  2564. if (lePrevGroup!=0) {
  2565. //
  2566. // get next entry from where we left off last time
  2567. //
  2568. if ( (PrevEnumSignature==pite->PrevIfGroupEnumSignature)
  2569. && (PrevEnumSignature!=0) )
  2570. {
  2571. // had reached end of enumeration
  2572. if (pite->pPrevIfGroupEnumPtr==NULL)
  2573. dwNumGroups = 0;
  2574. else
  2575. ple = &((PPROXY_GROUP_ENTRY)pite->pPrevIfGroupEnumPtr)->LinkBySameIfGroups;
  2576. }
  2577. //
  2578. // get next entry by searching through the list
  2579. //
  2580. else {
  2581. for (ple=pHead->Flink; (ple!=pHead); ple=ple->Flink) {
  2582. pProxyEntry = CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY,
  2583. LinkBySameIfGroups);
  2584. if (lePrevGroup<pProxyEntry->GroupLittleEndian)
  2585. break;
  2586. }
  2587. }
  2588. }
  2589. //
  2590. // starting enumeration from the beginning of the list
  2591. //
  2592. else {
  2593. ple = pHead->Flink;
  2594. }
  2595. //
  2596. // finally copy the groups
  2597. //
  2598. dwNumGroupsCopied = 0;
  2599. for ( ; (ple!=pHead)&&(dwNumGroupsCopied<dwNumGroups);
  2600. ple=ple->Flink,dwNumGroupsCopied++)
  2601. {
  2602. DWORD V3SourcesSize=0, IncrementSize;
  2603. pProxyEntry= CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY,
  2604. LinkBySameIfGroups);
  2605. if (bEnumV3){
  2606. V3SourcesSize
  2607. = pProxyEntry->NumSources*sizeof(IGMP_MIB_GROUP_SOURCE_INFO_V3);
  2608. }
  2609. IncrementSize = SizeofGroupEntry+V3SourcesSize;
  2610. if (dwCurSize+IncrementSize > dwBufferSize){
  2611. if (dwNumGroupsCopied==0) {
  2612. dwCurSize += IncrementSize;
  2613. bCopied = FALSE;
  2614. bInsufficientBuffer = TRUE;
  2615. }
  2616. break;
  2617. }
  2618. dwCurSize += IncrementSize;
  2619. pProxyGroupInfo->GroupAddr = pProxyEntry->Group;
  2620. pProxyGroupInfo->GroupUpTime
  2621. = SYSTEM_TIME_TO_SEC(llCurTime-pProxyEntry->InitTime);
  2622. pProxyGroupInfo->Flags = 0;
  2623. if (pProxyEntry->bStaticGroup) {
  2624. pProxyGroupInfo->Flags |= IGMP_GROUP_TYPE_STATIC;
  2625. if (pProxyEntry->RefCount>0)
  2626. pProxyGroupInfo->Flags |= IGMP_GROUP_TYPE_NON_STATIC;
  2627. }
  2628. else {
  2629. pProxyGroupInfo->Flags |= IGMP_GROUP_TYPE_NON_STATIC;
  2630. }
  2631. if (!bEnumV3) {
  2632. pProxyGroupInfo = (PMIB_PROXY_GROUP_INFO_V3)
  2633. ((PMIB_PROXY_GROUP_INFO)pProxyGroupInfo+1);
  2634. }
  2635. else {
  2636. //kslksl
  2637. /* PLIST_ENTRY pHeadSrc, pleSrc;
  2638. DWORD SrcCnt;
  2639. PPROXY_SOURCE_ENTRY pSourceEntry;
  2640. */
  2641. pProxyGroupInfo->NumSources = pProxyEntry->NumSources;
  2642. pProxyGroupInfo->Size = IncrementSize;
  2643. pHeadSrc = &pProxyEntry->ListSources;
  2644. for (pleSrc=pHeadSrc->Flink,SrcCnt=0; pleSrc!=pHeadSrc;
  2645. pleSrc=pleSrc->Flink,SrcCnt++)
  2646. {
  2647. pSourceEntry = CONTAINING_RECORD(pleSrc,
  2648. PROXY_SOURCE_ENTRY, LinkSources);
  2649. pProxyGroupInfo->Sources[SrcCnt].Source
  2650. = pSourceEntry->IpAddr;
  2651. pProxyGroupInfo->Sources[SrcCnt].Flags = pSourceEntry->JoinMode;
  2652. pProxyGroupInfo->Sources[SrcCnt].Flags +=
  2653. (pSourceEntry->JoinModeIntended<<4);
  2654. }
  2655. pProxyGroupInfo = (PMIB_PROXY_GROUP_INFO_V3)
  2656. &pProxyGroupInfo->Sources[pProxyGroupInfo->NumSources];
  2657. //Trace1(MEM, "next proxy: %0x:", (DWORD)pProxyGroupInfo);//deldel
  2658. }
  2659. }//copy all sources
  2660. //
  2661. // if reached the end of the group list or the group list is empty
  2662. //
  2663. if ( ((ple==pHead&&dwNumGroupsCopied!=0)||(dwNumIfGroups==0)||(dwNumGroups==0))
  2664. && !bInsufficientBuffer)
  2665. //||(ple->Flink==pHead))
  2666. {
  2667. pQuery->Flags |= IGMP_ENUM_INTERFACE_TABLE_END;
  2668. pQuery->GroupAddr = 0;
  2669. // reset pointers for next enumeration
  2670. pite->pPrevIfGroupEnumPtr = NULL;
  2671. pite->PrevIfGroupEnumSignature = 0;
  2672. }
  2673. //
  2674. // else have more GI entries to enumerate
  2675. //
  2676. else {
  2677. PPROXY_GROUP_ENTRY pProxyNext;
  2678. pQuery->Flags |= IGMP_ENUM_INTERFACE_TABLE_CONTINUE;
  2679. if (ple!=pHead) {
  2680. // get the next entry from which enum should continue
  2681. pProxyNext = CONTAINING_RECORD(ple, PROXY_GROUP_ENTRY,
  2682. LinkBySameIfGroups);
  2683. // update pQuery->GroupAddr
  2684. pQuery->GroupAddr = pProxyNext->Group;
  2685. // update pointers for next enumeration
  2686. pite->pPrevIfGroupEnumPtr = pProxyNext;
  2687. }
  2688. else {
  2689. pQuery->GroupAddr = 0xffffffff;
  2690. pite->pPrevIfGroupEnumPtr = NULL;
  2691. }
  2692. pite->PrevIfGroupEnumSignature = GET_NEXT_SIGNATURE();
  2693. SET_SIGNATURE(pQuery->Signature, pite->PrevIfGroupEnumSignature);
  2694. }
  2695. } //end proxy interface
  2696. //
  2697. // if only one interface is being enumerated, and the number of groups being
  2698. // enumerated is 0 inspite of adequate buffer, then return NO_MORE_ITEMS
  2699. //
  2700. if ( !bInsufficientBuffer && (dwNumGroupsCopied==0)
  2701. &&(!(pQuery->Flags&IGMP_ENUM_ALL_INTERFACES_GROUPS)) )
  2702. {
  2703. pQuery->GroupAddr = 0;
  2704. Error = ERROR_NO_MORE_ITEMS;
  2705. }
  2706. RELEASE_IF_GROUP_LIST_LOCK(pite->IfIndex, "_MibGetInternalIfGroupsInfo");
  2707. if (!bInsufficientBuffer)
  2708. bCopied = TRUE;
  2709. } END_BREAKOUT_BLOCK1; // inside shared interface lock.
  2710. // release the shared interface lock
  2711. RELEASE_IF_LOCK_SHARED(pite->IfIndex, "_MibGetInternalIfGroupsInfo");
  2712. RELEASE_ENUM_LOCK_EXCLUSIVE("_MibGetInternalIfGroupsInfo");
  2713. if (pResponse!=NULL) {
  2714. pResponse->Count = (bCopied) ? 1 : 0;
  2715. if (bCopied)
  2716. pHeader->NumGroups = dwNumGroupsCopied;
  2717. if (bEnumV3)
  2718. pResponse->Flags |= IGMP_ENUM_FORMAT_IGMPV3;
  2719. }
  2720. if (bInsufficientBuffer)
  2721. pQuery->Flags |= PrevQueryFlags;
  2722. //
  2723. //set the actual size if some info was copied, else let size
  2724. //remain
  2725. //
  2726. *pdwOutputSize = dwCurSize;
  2727. RELEASE_IF_LIST_LOCK("_MibGetInternalIfGroupsInfo");
  2728. Trace0(MIB, "Leaving _MibGetInternalIfGroupsInfo()");
  2729. return Error;
  2730. } //end _MibGetInternalIfGroupsInfo
  2731. //------------------------------------------------------------------------------
  2732. // MibGetInternalIfStats
  2733. //------------------------------------------------------------------------------
  2734. DWORD
  2735. MibGetInternalIfStats (
  2736. PIGMP_MIB_GET_INPUT_DATA pQuery,
  2737. PIGMP_MIB_GET_OUTPUT_DATA pResponse,
  2738. PDWORD pdwOutputSize,
  2739. DWORD dwGetMode,
  2740. DWORD dwBufferSize
  2741. )
  2742. {
  2743. DWORD Error = NO_ERROR, dwCount, dwSize;
  2744. PIGMP_IF_TABLE pTable = g_pIfTable;
  2745. PIF_TABLE_ENTRY pite;
  2746. PRAS_TABLE_ENTRY prte;
  2747. PRAS_TABLE prt;
  2748. PIGMP_MIB_IF_STATS pStatsDst;
  2749. PIF_INFO pIfStatsSrc;
  2750. LONGLONG llCurTime = GetCurrentIgmpTime();
  2751. BOOL bDone, bCopied, bRasIfLock;
  2752. Trace0(MIB, "Entering _MibGetInternalIfStats()");
  2753. *pdwOutputSize = pQuery->Count*sizeof(IGMP_MIB_IF_STATS);
  2754. //
  2755. // the interface statistics struct is fixed-length.
  2756. // there may be multiple instances.
  2757. //
  2758. if (pResponse!=NULL) {
  2759. pResponse->TypeId = IGMP_IF_STATS_ID;
  2760. pStatsDst = (PIGMP_MIB_IF_STATS) pResponse->Buffer;
  2761. }
  2762. // acquire IfLists lock so that the interfaces list can be accessed
  2763. ACQUIRE_IF_LIST_LOCK("_MibGetInternalIfStats");
  2764. for (dwCount=0, dwSize=0; dwCount<pQuery->Count; ) {
  2765. //
  2766. // retrieve the interface. If the ras flag was set and ras statistics
  2767. // are kept, then ras client statistics are also returned.
  2768. // If no more relevant structures, then return ERROR_NO_MORE_ITEMS.
  2769. //
  2770. //
  2771. // the pResponse IfIndex,RasClientAddr fields are updated appropriately.
  2772. // if a lock is acquired on the ras table, then bRasIfLock is set to
  2773. // TRUE;
  2774. //
  2775. bRasIfLock = FALSE;
  2776. Error = GetIfOrRasForEnum(pQuery, pResponse, dwGetMode,
  2777. &pite, &prt, &prte, &bRasIfLock, 0);
  2778. if (pite == NULL) {
  2779. if (dwCount>0) {
  2780. Error = NO_ERROR;
  2781. }
  2782. // count==0
  2783. else {
  2784. if (Error == NO_ERROR)
  2785. Error = ERROR_INVALID_PARAMETER;
  2786. *pdwOutputSize = 0;
  2787. }
  2788. break; //from for loop
  2789. }
  2790. //
  2791. // if no buffer was specified, indicate one should be allocated
  2792. // the required buffer size has already been set.
  2793. //
  2794. if (pResponse==NULL) {
  2795. Error = ERROR_INSUFFICIENT_BUFFER;
  2796. break;
  2797. }
  2798. //
  2799. // acquire IfLists locks so that interfaces list cannot be changed
  2800. //
  2801. if (!bRasIfLock)
  2802. ACQUIRE_IF_LOCK_SHARED(pite->IfIndex, "_MibGetInternalIfStats");
  2803. BEGIN_BREAKOUT_BLOCK1 {
  2804. //
  2805. // if the buffer is not large enough, break from the loop
  2806. //
  2807. if (dwBufferSize < dwSize+sizeof(IGMP_MIB_IF_STATS)) {
  2808. if (dwCount==0)
  2809. Error = ERROR_INSUFFICIENT_BUFFER;
  2810. bDone = TRUE;
  2811. bCopied = FALSE;
  2812. GOTO_END_BLOCK1;
  2813. }
  2814. //
  2815. // copy the interface stats. Copy field by field as access to this
  2816. // structure is not synchronized
  2817. //
  2818. //
  2819. // copy interface stats
  2820. //
  2821. if (prte==NULL) {
  2822. pIfStatsSrc = &pite->Info;
  2823. if (!IS_IF_ACTIVATED(pite))
  2824. ZeroMemory(pStatsDst, sizeof(*pStatsDst));
  2825. //
  2826. //copy if index, addr
  2827. //
  2828. pStatsDst->IfIndex = pite->IfIndex;
  2829. pStatsDst->IpAddr = pite->IpAddr;
  2830. pStatsDst->IfType = GET_EXTERNAL_IF_TYPE(pite);
  2831. GET_EXTERNAL_IF_STATE(pite, pStatsDst->State);
  2832. pQuery->IfIndex = pite->IfIndex;
  2833. pQuery->RasClientAddr = 0;
  2834. pStatsDst->IgmpProtocolType =
  2835. pite->Config.IgmpProtocolType;
  2836. //
  2837. // if this interface is not activated, then continue from the
  2838. // next one
  2839. //
  2840. if (!IS_IF_ACTIVATED(pite)) {
  2841. bDone = FALSE; bCopied = TRUE;
  2842. GOTO_END_BLOCK1;
  2843. }
  2844. pStatsDst->QuerierState = pIfStatsSrc->QuerierState;
  2845. pStatsDst->QuerierIpAddr =
  2846. pIfStatsSrc->QuerierIpAddr;
  2847. pStatsDst->ProxyIfIndex = g_ProxyIfIndex;
  2848. //if I am the querier set to 0
  2849. pStatsDst->QuerierPresentTimeLeft = IS_QUERIER(pite) ?
  2850. 0 :
  2851. SYSTEM_TIME_TO_SEC(pIfStatsSrc->QuerierPresentTimeout - llCurTime);
  2852. pStatsDst->LastQuerierChangeTime
  2853. = SYSTEM_TIME_TO_SEC(llCurTime - pIfStatsSrc->LastQuerierChangeTime);
  2854. pStatsDst->V1QuerierPresentTimeLeft =
  2855. (IS_IF_VER2(pite) && (pIfStatsSrc->V1QuerierPresentTime > llCurTime))
  2856. ? SYSTEM_TIME_TO_SEC(pIfStatsSrc->V1QuerierPresentTime - llCurTime)
  2857. : 0;
  2858. {
  2859. LARGE_INTEGER liUptime;
  2860. liUptime.QuadPart = (llCurTime-pIfStatsSrc->TimeWhenActivated)/1000;
  2861. pStatsDst->Uptime = liUptime.LowPart;
  2862. }
  2863. pStatsDst->TotalIgmpPacketsReceived
  2864. = pIfStatsSrc->TotalIgmpPacketsReceived;
  2865. pStatsDst->TotalIgmpPacketsForRouter
  2866. = pIfStatsSrc->TotalIgmpPacketsForRouter;
  2867. pStatsDst->GeneralQueriesReceived
  2868. = pIfStatsSrc->GenQueriesReceived;
  2869. pStatsDst->WrongVersionQueries
  2870. = pIfStatsSrc->WrongVersionQueries;
  2871. pStatsDst->JoinsReceived
  2872. = pIfStatsSrc->JoinsReceived;
  2873. pStatsDst->LeavesReceived
  2874. = pIfStatsSrc->LeavesReceived;
  2875. pStatsDst->CurrentGroupMemberships
  2876. = pIfStatsSrc->CurrentGroupMemberships;
  2877. pStatsDst->GroupMembershipsAdded
  2878. = pIfStatsSrc->GroupMembershipsAdded;
  2879. pStatsDst->WrongChecksumPackets
  2880. = pIfStatsSrc->WrongChecksumPackets;
  2881. pStatsDst->ShortPacketsReceived
  2882. = pIfStatsSrc->ShortPacketsReceived;
  2883. pStatsDst->LongPacketsReceived
  2884. = pIfStatsSrc->LongPacketsReceived;
  2885. pStatsDst->PacketsWithoutRtrAlert
  2886. = pIfStatsSrc->PacketsWithoutRtrAlert;
  2887. }
  2888. //
  2889. // copy ras client statistics
  2890. //
  2891. else {
  2892. ZeroMemory(pStatsDst, sizeof(*pStatsDst));
  2893. pStatsDst->IfIndex = pite->IfIndex;
  2894. pStatsDst->IpAddr = pite->IpAddr;
  2895. pStatsDst->IfType = IGMP_IF_RAS_CLIENT;
  2896. GET_EXTERNAL_IF_STATE(pite, pStatsDst->State);
  2897. pQuery->IfIndex = pite->IfIndex;
  2898. pQuery->RasClientAddr = prte->NHAddr;
  2899. //
  2900. // if this interface is not activated, then continue from the
  2901. // next one
  2902. //
  2903. if (!IS_IF_ACTIVATED(pite)) {
  2904. bDone = FALSE; bCopied = TRUE;
  2905. GOTO_END_BLOCK1;
  2906. }
  2907. pStatsDst-> TotalIgmpPacketsReceived
  2908. = prte->Info.TotalIgmpPacketsReceived;
  2909. pStatsDst->TotalIgmpPacketsForRouter
  2910. = prte->Info.TotalIgmpPacketsForRouter;
  2911. pStatsDst->GeneralQueriesReceived
  2912. = prte->Info.GenQueriesReceived;
  2913. pStatsDst->JoinsReceived
  2914. = prte->Info.JoinsReceived;
  2915. pStatsDst->LeavesReceived
  2916. = prte->Info.LeavesReceived;
  2917. pStatsDst->CurrentGroupMemberships
  2918. = prte->Info.CurrentGroupMemberships;
  2919. pStatsDst->GroupMembershipsAdded
  2920. = prte->Info.GroupMembershipsAdded;
  2921. pStatsDst->WrongChecksumPackets
  2922. = prte->Info.WrongChecksumPackets;
  2923. pStatsDst->ShortPacketsReceived
  2924. = prte->Info.ShortPacketsReceived;
  2925. pStatsDst->LongPacketsReceived
  2926. = prte->Info.LongPacketsReceived;
  2927. }
  2928. bCopied = TRUE;
  2929. bDone = FALSE;
  2930. } END_BREAKOUT_BLOCK1;
  2931. RELEASE_IF_LOCK_SHARED(pite->IfIndex, "_MibGetInternalIfStats");
  2932. bRasIfLock = FALSE;
  2933. if (bCopied) {
  2934. //
  2935. // everything fine. Copied one more stats struct
  2936. //
  2937. dwCount++;
  2938. dwSize += sizeof(IGMP_MIB_IF_STATS);
  2939. pStatsDst++;
  2940. }
  2941. // if current mode is get first, then change it to get next
  2942. if (dwGetMode==GETMODE_FIRST)
  2943. dwGetMode = GETMODE_NEXT;
  2944. if (bDone)
  2945. break;
  2946. }//end for loop
  2947. if (pResponse!=NULL)
  2948. pResponse->Count = dwCount;
  2949. //
  2950. //set the actual size if some info was copied, else let size set earlier
  2951. //remain
  2952. //
  2953. if (dwCount>0) {
  2954. *pdwOutputSize = dwSize;
  2955. }
  2956. // release interface lock
  2957. if (bRasIfLock && pite)
  2958. RELEASE_IF_LOCK_SHARED(pite->IfIndex, "_MibGetInternalIfStats");
  2959. RELEASE_IF_LIST_LOCK("_MibGetInternalIfStats");
  2960. Trace0(MIB, "Leaving _MibGetInternalIfStats()");
  2961. return Error;
  2962. } //end _MibGetInternalIfStats
  2963. //------------------------------------------------------------------------------
  2964. // GetIfOrRasForEnum
  2965. // First gets the required interface. If ras stats enabled and asked,
  2966. // then gets the ras client.
  2967. //
  2968. // Locks On return:
  2969. // if *bRasTableLock==TRUE then this procedure has taken read lock on the
  2970. // ras table and has not released it.
  2971. // Assumes shared interface lock.
  2972. //------------------------------------------------------------------------------
  2973. DWORD
  2974. GetIfOrRasForEnum(
  2975. PIGMP_MIB_GET_INPUT_DATA pQuery,
  2976. PIGMP_MIB_GET_OUTPUT_DATA pResponse,
  2977. DWORD dwGetMode,
  2978. PIF_TABLE_ENTRY *ppite,
  2979. PRAS_TABLE *pprt,
  2980. PRAS_TABLE_ENTRY *pprte, // on return set to null if no ras stats
  2981. BOOL *bRasIfLock,
  2982. DWORD dwEnumForRasClients
  2983. )
  2984. {
  2985. DWORD Error = NO_ERROR,
  2986. bRasClientsEnum = dwEnumForRasClients & IGMP_ENUM_FOR_RAS_CLIENTS;
  2987. *ppite = NULL;
  2988. *pprt = NULL;
  2989. *pprte = NULL;
  2990. //
  2991. // get the interface depending on the mode
  2992. //
  2993. if (bRasClientsEnum)
  2994. *ppite = GetIfByListIndex(pQuery->IfIndex, GETMODE_EXACT, &Error);
  2995. else
  2996. *ppite = GetIfByListIndex(pQuery->IfIndex, dwGetMode, &Error);
  2997. //
  2998. // return if valid interface could not be found or not rasClient
  2999. //
  3000. if ( (*ppite==NULL) || (Error!=NO_ERROR) || !bRasClientsEnum)
  3001. return Error;
  3002. //
  3003. // do ras client processing
  3004. //
  3005. BEGIN_BREAKOUT_BLOCK1 {
  3006. ACQUIRE_IF_LOCK_SHARED((*ppite)->IfIndex, "_GetIfOrRasForEnum");
  3007. *bRasIfLock = TRUE;
  3008. //
  3009. // current interface not ras server interface. So done.
  3010. //
  3011. if (!IS_RAS_SERVER_IF((*ppite)->IfType))
  3012. GOTO_END_BLOCK1;
  3013. //
  3014. // no ras client stats (if flag not set in the query, or ras
  3015. // stats not being kept). So done.
  3016. //
  3017. if ( !bRasClientsEnum || !g_Config.RasClientStats )
  3018. {
  3019. GOTO_END_BLOCK1;
  3020. }
  3021. //
  3022. // if mode: GETMODE_EXACT: then search for the ras client.
  3023. // if ras client not found, then I set the interface to null
  3024. //
  3025. if (dwGetMode==GETMODE_EXACT) {
  3026. // if pQuery->RasClientAddr==0, then he is not asking for ras client
  3027. // So done.
  3028. if (pQuery->RasClientAddr==0)
  3029. GOTO_END_BLOCK1;
  3030. *pprte = GetRasClientByAddr(pQuery->RasClientAddr,
  3031. (*ppite)->pRasTable);
  3032. //
  3033. // if ras client not found in GETMODE_EXACT, then dont return IF
  3034. // and release read lock on ras table.
  3035. //
  3036. if (*pprte==NULL) {
  3037. *ppite = NULL;
  3038. GOTO_END_BLOCK1;
  3039. }
  3040. *pprt = (*ppite)->pRasTable;
  3041. }
  3042. //
  3043. // GETMODE_NEXT : if pQuery->RasClientAddr, then find the first ras
  3044. // client, else find the next ras client
  3045. //
  3046. else if ( (dwGetMode==GETMODE_NEXT) || (dwGetMode==GETMODE_FIRST) ){
  3047. BOOL bFoundRasClient = FALSE;
  3048. *pprt = (*ppite)->pRasTable;
  3049. //
  3050. // if the pQuery->RasClientAddr==0, then get the first ras client
  3051. //
  3052. if (pQuery->RasClientAddr==0) {
  3053. if (!IsListEmpty(&(*pprt)->ListByAddr)) {
  3054. bFoundRasClient = TRUE;
  3055. *pprte = CONTAINING_RECORD((*pprt)->ListByAddr.Flink,
  3056. RAS_TABLE_ENTRY, LinkByAddr);
  3057. }
  3058. }
  3059. else {
  3060. PRAS_TABLE_ENTRY prtePrev, prteCur;
  3061. PLIST_ENTRY pHead, ple;
  3062. // get the prev ras client through hash table
  3063. prtePrev = GetRasClientByAddr(pQuery->RasClientAddr,
  3064. (*ppite)->pRasTable);
  3065. //
  3066. // if ras client not found, then go through the ordered list
  3067. // and get a ras client with next higher addr
  3068. //
  3069. if (prtePrev==NULL) {
  3070. pHead = &(*pprt)->ListByAddr;
  3071. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  3072. prteCur = CONTAINING_RECORD(ple, RAS_TABLE_ENTRY,
  3073. LinkByAddr);
  3074. if (pQuery->RasClientAddr>prteCur->NHAddr)
  3075. break;
  3076. }
  3077. if (ple!=pHead) {
  3078. bFoundRasClient = TRUE;
  3079. *pprte = prteCur;
  3080. }
  3081. }
  3082. //
  3083. // get the next ras client through the ras client list
  3084. //
  3085. else {
  3086. ple = prtePrev->LinkByAddr.Flink;
  3087. // more entries present. found next ras client entry
  3088. if (ple != &(*pprt)->ListByAddr) {
  3089. bFoundRasClient = TRUE;
  3090. *pprte = CONTAINING_RECORD(ple, RAS_TABLE_ENTRY,
  3091. LinkByAddr);
  3092. *pprt = (*ppite)->pRasTable;
  3093. }
  3094. }
  3095. }
  3096. // if ras client is not found, then I set the interface also to NULL
  3097. if (bFoundRasClient==FALSE) {
  3098. if (*bRasIfLock)
  3099. RELEASE_IF_LOCK_SHARED((*ppite)->IfIndex, "_GetIfOrRasForEnum");
  3100. *bRasIfLock = FALSE;
  3101. *ppite = NULL;
  3102. *pprte = NULL;
  3103. *pprt = NULL;
  3104. Error = ERROR_NO_MORE_ITEMS;
  3105. }
  3106. else
  3107. *pprt = (*ppite)->pRasTable;
  3108. } //getmode==GETMODE_NEXT
  3109. } END_BREAKOUT_BLOCK1;
  3110. if ( (Error!= NO_ERROR) && (*bRasIfLock) ) {
  3111. *bRasIfLock = FALSE;
  3112. RELEASE_IF_LOCK_SHARED((*ppite)->IfIndex, "_GetIfOrRasForEnum");
  3113. }
  3114. return Error;
  3115. } //end _GetIfOrRasForEnum
  3116. //------------------------------------------------------------------------------
  3117. // Function: _GetIfByListIndex
  3118. //
  3119. // if GETMODE_FIRST: retrieves the 1st entry in the list ordered by index.
  3120. // if GETMODE_EXACT: retrieves the entry from the hash table
  3121. // if GETMODE_NEXT: retrieves the prev entry from hash table, and then
  3122. // retrieves the next entry from the list ordered by index.
  3123. //
  3124. // Locks: Assumes IfList lock.
  3125. //------------------------------------------------------------------------------
  3126. PIF_TABLE_ENTRY
  3127. GetIfByListIndex(
  3128. DWORD IfIndex,
  3129. DWORD dwGetMode,
  3130. PDWORD pdwErr
  3131. )
  3132. {
  3133. PIF_TABLE_ENTRY pite;
  3134. PLIST_ENTRY ple, pHead;
  3135. if (pdwErr != NULL) { *pdwErr = NO_ERROR; }
  3136. pite = NULL;
  3137. //
  3138. // GETMODE_FIRST: return record at head of list;
  3139. // if list is empty, return NULL.
  3140. //
  3141. if (dwGetMode == GETMODE_FIRST) {
  3142. if (IsListEmpty(&g_pIfTable->ListByIndex)) {
  3143. //*pdwErr = ERROR_NO_MORE_ITEMS;
  3144. return NULL;
  3145. }
  3146. else {
  3147. ple = g_pIfTable->ListByIndex.Flink;
  3148. return CONTAINING_RECORD(ple, IF_TABLE_ENTRY, LinkByIndex);
  3149. }
  3150. }
  3151. //
  3152. // get the entry requested from the hash table.
  3153. //
  3154. pite = GetIfByIndex(IfIndex);
  3155. //
  3156. // GETMODE_EXACT: return the entry
  3157. //
  3158. if (dwGetMode==GETMODE_EXACT)
  3159. return pite;
  3160. //
  3161. // GETMODE_NEXT: return the item after the one retrieved
  3162. //
  3163. if (dwGetMode==GETMODE_NEXT) {
  3164. // the previous entry was found. return the next one.
  3165. if (pite!=NULL) {
  3166. ple = &pite->LinkByIndex;
  3167. //
  3168. // if entry found is last one, return NULL,
  3169. // otherwise return the following entry
  3170. //
  3171. if (ple->Flink == &g_pIfTable->ListByIndex) {
  3172. if (pdwErr != NULL) { *pdwErr = ERROR_NO_MORE_ITEMS; }
  3173. pite = NULL;
  3174. }
  3175. else {
  3176. ple = ple->Flink;
  3177. pite = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, LinkByIndex);
  3178. }
  3179. }
  3180. //
  3181. // the previous entry was not found.
  3182. // go throught the list of interfaces ordered by index, and retrieve the
  3183. // interface with next higher index
  3184. //
  3185. else {
  3186. pHead = &g_pIfTable->ListByIndex;
  3187. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  3188. pite = CONTAINING_RECORD(ple, IF_TABLE_ENTRY, LinkByIndex);
  3189. if (pite->IfIndex>IfIndex)
  3190. break;
  3191. }
  3192. }
  3193. }
  3194. return pite;
  3195. }//end _GetIfByListIndex
  3196. //------------------------------------------------------------------------------
  3197. // _GetGroupByAddr
  3198. //
  3199. // Locks: assumes lock on the group list
  3200. //------------------------------------------------------------------------------
  3201. PGROUP_TABLE_ENTRY
  3202. GetGroupByAddr (
  3203. DWORD Group,
  3204. DWORD dwGetMode,
  3205. PDWORD pdwErr
  3206. )
  3207. {
  3208. PLIST_ENTRY ple, pHead;
  3209. PGROUP_TABLE_ENTRY pge;
  3210. DWORD GroupLittleEndian = NETWORK_TO_LITTLE_ENDIAN(Group);
  3211. if (pdwErr != NULL) { *pdwErr = NO_ERROR; }
  3212. pHead = &g_pGroupTable->ListByGroup.Link;
  3213. pge = NULL;
  3214. //
  3215. // return record at head of list if mode is GETMODE_FIRST;
  3216. // if list is empty, return NULL.
  3217. //
  3218. if (dwGetMode == GETMODE_FIRST) {
  3219. if (pHead->Flink == pHead) { return NULL; }
  3220. else {
  3221. ple = pHead->Flink;
  3222. return CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, LinkByGroup);
  3223. }
  3224. }
  3225. // get the entry requested
  3226. pge = GetGroupFromGroupTable (Group, NULL, 0);
  3227. //
  3228. // if mode is GETMODE_NEXT, return the item after the one retrieved
  3229. //
  3230. if (dwGetMode == GETMODE_NEXT) {
  3231. //
  3232. // if the previous group was found, then return the one following it in the list
  3233. //
  3234. if (pge != NULL) {
  3235. ple = &pge->LinkByGroup;
  3236. //
  3237. // if entry found is last one, return NULL,
  3238. // otherwise return the following entry
  3239. //
  3240. if (ple->Flink == pHead) {
  3241. if (pdwErr != NULL) { *pdwErr = ERROR_NO_MORE_ITEMS; }
  3242. pge = NULL;
  3243. }
  3244. else {
  3245. ple = ple->Flink;
  3246. pge = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, LinkByGroup);
  3247. }
  3248. }
  3249. //
  3250. // previous group was not found. Go through the list and return the greater group.
  3251. //
  3252. else {
  3253. pHead = &g_pGroupTable->ListByGroup.Link;
  3254. for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {
  3255. pge = CONTAINING_RECORD(ple, GROUP_TABLE_ENTRY, LinkByGroup);
  3256. if (pge->GroupLittleEndian > GroupLittleEndian)
  3257. break;
  3258. }
  3259. if (ple==pHead) {
  3260. if (pdwErr != NULL) { *pdwErr = ERROR_NO_MORE_ITEMS; }
  3261. pge = NULL;
  3262. }
  3263. // else pge points to the entry to be returned.
  3264. }
  3265. }
  3266. return pge;
  3267. }//end _GetGroupByAddr
  3268. DWORD
  3269. APIENTRY
  3270. MibCreate(
  3271. IN DWORD dwInputSize,
  3272. IN PVOID pInputData
  3273. )
  3274. {
  3275. //
  3276. // Not supported
  3277. //
  3278. return NO_ERROR;
  3279. }
  3280. DWORD
  3281. APIENTRY
  3282. MibDelete(
  3283. IN DWORD dwInputSize,
  3284. IN PVOID pInputData
  3285. )
  3286. {
  3287. //
  3288. // Not supported
  3289. //
  3290. return NO_ERROR;
  3291. }
  3292. DWORD
  3293. APIENTRY
  3294. MibSet(
  3295. IN DWORD dwInputSize,
  3296. IN PVOID pInputData
  3297. )
  3298. {
  3299. //
  3300. // Not supported
  3301. //
  3302. return NO_ERROR;
  3303. }