Leaked source code of windows server 2003
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.

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