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

1130 lines
27 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. mibfuncs.c
  5. Abstract:
  6. Sample subagent instrumentation callbacks.
  7. --*/
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. // defined in iphlpapi.dll. This is a private api, which is
  11. // not declared in any header file.
  12. DWORD
  13. GetIgmpList(IN IPAddr NTEAddr,
  14. OUT IPAddr *pIgmpList,
  15. OUT PULONG dwOutBufLen
  16. );
  17. //------------------------------------------------------------------------------
  18. // local typedefs
  19. //------------------------------------------------------------------------------
  20. typedef enum {
  21. CONFIG_TYPE, STATS_TYPE
  22. } INFO_TYPE;
  23. //------------------------------------------------------------------------------
  24. // Local Prototypes
  25. //------------------------------------------------------------------------------
  26. DWORD
  27. ConnectToRouter(
  28. );
  29. DWORD
  30. GetInterfaceInfo(
  31. DWORD ActionId,
  32. DWORD *IfIndex,
  33. PIGMP_MIB_GET_OUTPUT_DATA *ppResponse,
  34. INFO_TYPE InfoType
  35. );
  36. DWORD
  37. GetCacheEntry(
  38. DWORD ActionId,
  39. DWORD IfIndex,
  40. DWORD Group,
  41. DWORD *pNextGroup,
  42. PIGMP_MIB_GET_OUTPUT_DATA *ppResponse
  43. );
  44. //------------------------------------------------------------------------------
  45. // GetInterfaceInfo
  46. //------------------------------------------------------------------------------
  47. DWORD
  48. GetInterfaceInfo(
  49. DWORD ActionId,
  50. DWORD *pIfIndex,
  51. PIGMP_MIB_GET_OUTPUT_DATA *ppResponse,
  52. INFO_TYPE infoType
  53. )
  54. /*++
  55. Routine Description:
  56. Makes a call to igmp to get the interface config and stats and
  57. returns that info to mib.
  58. Return values:
  59. MIB_S_ENTRY_NOT_FOUND MIB_S_NO_MORE_ENTRIES MIB_S_INVALID_PARAMETER
  60. --*/
  61. {
  62. IGMP_MIB_GET_INPUT_DATA Query;
  63. DWORD dwErr = NO_ERROR, dwOutSize;
  64. *ppResponse = NULL;
  65. ZeroMemory(&Query, sizeof(Query));
  66. Query.TypeId = (infoType==CONFIG_TYPE) ? IGMP_IF_CONFIG_ID: IGMP_IF_STATS_ID;
  67. Query.Flags = 0;
  68. Query.Count = 1;
  69. Query.IfIndex = *pIfIndex;
  70. if ( (*pIfIndex==0) && (ActionId==MIB_ACTION_GETNEXT) )
  71. ActionId = MIB_ACTION_GETFIRST;
  72. switch (ActionId) {
  73. //
  74. // ERROR_INVALID_PARAMETER is returned when there is no
  75. // interface with the given index
  76. // RPC_S_SERVER_UNAVAILABLE is returned when the router
  77. // isn't running.
  78. //
  79. case MIB_ACTION_GET :
  80. {
  81. IGMP_MIB_GET(&Query, sizeof(Query), ppResponse,
  82. &dwOutSize, dwErr);
  83. if (dwErr==ERROR_INVALID_PARAMETER
  84. || dwErr==RPC_S_SERVER_UNAVAILABLE
  85. || dwErr==MIB_S_NO_MORE_ENTRIES)
  86. {
  87. dwErr = MIB_S_ENTRY_NOT_FOUND;
  88. }
  89. break;
  90. }
  91. case MIB_ACTION_GETFIRST :
  92. {
  93. IGMP_MIB_GETFIRST(&Query, sizeof(Query), ppResponse,
  94. &dwOutSize, dwErr);
  95. if (dwErr==ERROR_INVALID_PARAMETER
  96. || dwErr==RPC_S_SERVER_UNAVAILABLE
  97. || dwErr==MIB_S_NO_MORE_ENTRIES)
  98. {
  99. dwErr = MIB_S_NO_MORE_ENTRIES;
  100. }
  101. break;
  102. }
  103. case MIB_ACTION_GETNEXT :
  104. {
  105. IGMP_MIB_GETNEXT(&Query, sizeof(Query), ppResponse,
  106. &dwOutSize, dwErr);
  107. if (dwErr==ERROR_INVALID_PARAMETER
  108. || dwErr==RPC_S_SERVER_UNAVAILABLE
  109. || dwErr==MIB_S_NO_MORE_ENTRIES)
  110. {
  111. dwErr = MIB_S_NO_MORE_ENTRIES;
  112. }
  113. break;
  114. }
  115. default :
  116. {
  117. dwErr = MIB_S_INVALID_PARAMETER;
  118. break;
  119. }
  120. }
  121. if (dwErr!=NO_ERROR)
  122. *ppResponse = NULL;
  123. else
  124. *pIfIndex = Query.IfIndex;
  125. return dwErr;
  126. } //end GetInterfaceInfo
  127. ///////////////////////////////////////////////////////////////////////////////
  128. // //
  129. // igmpInterfaceEntry table (1,3,6,1,3,59,1,1,1,1) //
  130. // //
  131. ///////////////////////////////////////////////////////////////////////////////
  132. UINT
  133. get_igmpInterfaceEntry(
  134. UINT ActionId,
  135. AsnAny *ObjectArray,
  136. UINT *ErrorIndex
  137. )
  138. /*++
  139. Routine Description:
  140. Get the InterfaceEntry for snmp. Have to get the InterfaceConfig and
  141. InterfaceStats for the interface from igmp router.
  142. --*/
  143. {
  144. DWORD dwErr=NO_ERROR;
  145. PIGMP_MIB_GET_OUTPUT_DATA pResponseConfig, pResponseStats;
  146. PIGMP_MIB_IF_CONFIG pConfig;
  147. PIGMP_MIB_IF_STATS pStats;
  148. DWORD IfIndex, dwValue;
  149. buf_igmpInterfaceEntry *pMibIfEntry
  150. = (buf_igmpInterfaceEntry*)ObjectArray;
  151. DWORD dwTmpActionId;
  152. TraceEnter("get_igmpInterfaceEntry");
  153. // get the interface index
  154. IfIndex = GET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceIfIndex, 0);
  155. TRACE1("get_igmpInterfaceEntry called with IfIndex:%d", IfIndex);
  156. //
  157. // get interface config
  158. //
  159. dwTmpActionId = ActionId;
  160. while (1) {
  161. dwErr = GetInterfaceInfo(
  162. dwTmpActionId,
  163. &IfIndex,
  164. &pResponseConfig,
  165. CONFIG_TYPE
  166. );
  167. // return if error
  168. if (dwErr!=NO_ERROR) {
  169. TraceError(dwErr);
  170. return dwErr;
  171. }
  172. pConfig = (PIGMP_MIB_IF_CONFIG) pResponseConfig->Buffer;
  173. //
  174. // should ignore proxy interface (unless the mode is MIB_ACTION_GET)
  175. //
  176. if ( (pConfig->IgmpProtocolType==IGMP_PROXY)
  177. && ( (ActionId==MIB_ACTION_GETFIRST)||(ActionId==MIB_ACTION_GETNEXT)) )
  178. {
  179. dwTmpActionId = MIB_ACTION_GETNEXT;
  180. MprAdminMIBBufferFree(pResponseConfig);
  181. continue;
  182. }
  183. else
  184. break;
  185. }
  186. //
  187. // get interface stats
  188. // use MIB_GET as IfIndex has been updated by the previous call
  189. //
  190. dwErr = GetInterfaceInfo(
  191. MIB_ACTION_GET,
  192. &IfIndex,
  193. &pResponseStats,
  194. STATS_TYPE
  195. );
  196. // return if error
  197. if (dwErr!=NO_ERROR) {
  198. MprAdminMIBBufferFree(pResponseConfig);
  199. TraceError(dwErr);
  200. return dwErr;
  201. }
  202. TRACE1("get_igmpInterfaceEntry returned info for interface:%d",
  203. IfIndex);
  204. //
  205. // fill in the required fields and return the MibIfEntry
  206. //
  207. pStats = (PIGMP_MIB_IF_STATS) pResponseStats->Buffer;
  208. //
  209. // set index for following getnext operation, (if any)
  210. //
  211. FORCE_SET_ASN_INTEGER(&(pMibIfEntry->igmpInterfaceIfIndex),
  212. IfIndex);
  213. // get igmpInterfaceQueryInterval in seconds
  214. SET_ASN_INTEGER(&(pMibIfEntry->igmpInterfaceQueryInterval),
  215. pConfig->GenQueryInterval);
  216. //
  217. // if Igmp is activated on that interface, then the state is set
  218. // to active(1), else it is set to notInService(2)
  219. //
  220. if ((pStats->State&IGMP_STATE_ACTIVATED) == IGMP_STATE_ACTIVATED) {
  221. SET_ASN_INTEGER(&(pMibIfEntry->igmpInterfaceStatus), 1);
  222. }
  223. else {
  224. SET_ASN_INTEGER(&(pMibIfEntry->igmpInterfaceStatus), 2);
  225. }
  226. // set igmpInterfaceVersion
  227. if (pConfig->IgmpProtocolType == IGMP_ROUTER_V1) {
  228. SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceVersion, 1);
  229. }
  230. else if (pConfig->IgmpProtocolType == IGMP_ROUTER_V2) {
  231. SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceVersion, 2);
  232. }
  233. // set igmpInterfaceQuerier
  234. SET_ASN_IP_ADDRESS(&pMibIfEntry->igmpInterfaceQuerier,
  235. &pMibIfEntry->igmpInterfaceQuerierBuf,
  236. pStats->QuerierIpAddr);
  237. // set igmpInterfaceQueryMaxResponseTime in seconds
  238. SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceQueryMaxResponseTime,
  239. pConfig->GenQueryMaxResponseTime);
  240. // todo: how can this value be set. This should be part of igmp host
  241. SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceVersion1QuerierTimer,
  242. pStats->V1QuerierPresentTimeLeft);
  243. SET_ASN_COUNTER(&pMibIfEntry->igmpInterfaceWrongVersionQueries,
  244. pStats->WrongVersionQueries);
  245. // number of times a group entry was added to the group table
  246. SET_ASN_COUNTER(&pMibIfEntry->igmpInterfaceJoins,
  247. pStats->GroupMembershipsAdded);
  248. SET_ASN_GAUGE(&pMibIfEntry->igmpInterfaceGroups,
  249. pStats->CurrentGroupMemberships);
  250. SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceRobustness,
  251. pConfig->RobustnessVariable);
  252. // set igmpInterfaceLastMembQueryInterval in 10ths of secs
  253. // the value is initially in ms.
  254. dwValue = pConfig->LastMemQueryInterval / 100;
  255. SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceLastMembQueryInterval,
  256. dwValue);
  257. SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceProxyIfIndex,
  258. pStats->ProxyIfIndex);
  259. // seconds since igmpInterfaceQuerier was last changed
  260. SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceQuerierUpTime,
  261. pStats->LastQuerierChangeTime);
  262. SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceQuerierExpiryTime,
  263. pStats->QuerierPresentTimeLeft);
  264. MprAdminMIBBufferFree(pResponseConfig);
  265. MprAdminMIBBufferFree(pResponseStats);
  266. TraceLeave("get_igmpInterfaceEntry");
  267. return dwErr;
  268. }
  269. DWORD
  270. ValidateInterfaceConfig(
  271. IN AsnAny *objectArray
  272. )
  273. {
  274. DWORD dwRes, IfIndex,
  275. dwValue = 0, dwGenQueryInterval, dwMaxRespTime,
  276. dwRobustness;
  277. sav_igmpInterfaceEntry *pIfConfig = (sav_igmpInterfaceEntry*) objectArray;
  278. dwRes = MIB_S_INVALID_PARAMETER;
  279. BEGIN_BREAKOUT_BLOCK {
  280. //
  281. // get the interface index and make sure that it is not 0
  282. //
  283. IfIndex = GET_ASN_INTEGER(&pIfConfig->igmpInterfaceIfIndex, 0);
  284. if (IfIndex==0) {
  285. TRACE0("Call made for invalid interface index");
  286. break;
  287. }
  288. //
  289. // verify igmpInterfaceQueryInterval. Enforce min value of 10 sec
  290. // to prevent trashing the network.
  291. //
  292. dwGenQueryInterval = GET_ASN_INTEGER(
  293. &pIfConfig->igmpInterfaceQueryInterval, 0
  294. );
  295. if (dwGenQueryInterval<10) {
  296. TRACE2("IgmpInterfaceQueryInterval:%d for interface:%d less than "
  297. "minimum value of 10 secs",
  298. dwValue, IfIndex);
  299. break;
  300. }
  301. //
  302. // Ignore interface status. Do not allow interface being enabled through snmp
  303. //
  304. //
  305. // Igmp versions 1 and 2 currently supported
  306. //
  307. dwValue = GET_ASN_INTEGER(&pIfConfig->igmpInterfaceVersion, 0);
  308. if ( (dwValue!=1) && (dwValue!=2) ) {
  309. TRACE2("Invalid Igmp version:%d for interface:%d", dwValue, IfIndex);
  310. break;
  311. }
  312. //
  313. // check InterfaceQueryMaxResponseTime
  314. // NOTE: it is in units of 10ths of a second
  315. //
  316. dwMaxRespTime = GET_ASN_INTEGER(
  317. &pIfConfig->igmpInterfaceQueryMaxResponseTime,
  318. 0);
  319. // Enforce a min of 1 sec
  320. if (dwValue<10) {
  321. TRACE2("igmpInterfaceQueryMaxResponseTime:%d for interface:%d"
  322. "should not be less than 10", dwValue, IfIndex);
  323. break;
  324. }
  325. // Absurd if value greater than GenQueryInterval*10 (conv to 10th of sec).
  326. if (dwValue>dwGenQueryInterval*10) {
  327. TRACE3("QueryMaxResponseTime:%d for interface:%d "
  328. "should not be less than GenQueryInterval:%d",
  329. dwValue, IfIndex, dwGenQueryInterval);
  330. break;
  331. }
  332. //
  333. // igmpInterfaceRobustness must not be 0. If it is 1, print trace but
  334. // do not break.
  335. //
  336. dwRobustness = GET_ASN_INTEGER(&pIfConfig->igmpInterfaceRobustness, 0);
  337. if (dwValue==0) {
  338. TRACE1("IgmpInterfaceRobustness for interface:%d cannot be set to 0",
  339. IfIndex);
  340. break;
  341. }
  342. if (dwValue!=1) {
  343. TRACE1("Warning: InterfaceRobustness for interface:%d being set to 1",
  344. IfIndex);
  345. }
  346. // no check for igmpInterfaceProxyIfIndex.
  347. // limit max LastMemQueryInterval to GroupMembershipTimeout
  348. dwValue = GET_ASN_INTEGER(&pIfConfig->igmpInterfaceLastMembQueryInterval,
  349. 0);
  350. if (dwValue>dwRobustness*dwGenQueryInterval + dwMaxRespTime) {
  351. TRACE3("LastMembQueryInterval:%d for interface:%d should not be "
  352. "higher than GroupMembershipTimeout:%d",
  353. dwValue, IfIndex,
  354. dwRobustness*dwGenQueryInterval + dwMaxRespTime
  355. );
  356. break;
  357. }
  358. // if reached here, then there is no error
  359. dwRes = NO_ERROR;
  360. } END_BREAKOUT_BLOCK;
  361. return dwRes;
  362. }
  363. DWORD
  364. SetInterfaceConfig(
  365. IN AsnAny * objectArray
  366. )
  367. {
  368. DWORD dwRes = (DWORD) -1,
  369. dwGetSize = 0,
  370. dwSetSize = 0,
  371. IfIndex, dwValue;
  372. sav_igmpInterfaceEntry *pNewIfConfig
  373. = (sav_igmpInterfaceEntry*) objectArray;
  374. PIGMP_MIB_IF_CONFIG pCurIfConfig;
  375. PIGMP_MIB_SET_INPUT_DATA pSetInputData = NULL;
  376. PIGMP_MIB_GET_OUTPUT_DATA pResponse = NULL;
  377. IGMP_MIB_GET_INPUT_DATA Query;
  378. BEGIN_BREAKOUT_BLOCK {
  379. //
  380. // retrieve existing interface config
  381. //
  382. dwRes = GetInterfaceInfo(MIB_ACTION_GET,
  383. &IfIndex, &pResponse, CONFIG_TYPE);
  384. if (dwRes != NO_ERROR) {
  385. TraceError(dwRes);
  386. break;
  387. }
  388. //
  389. // Update fields
  390. //
  391. pCurIfConfig = (PIGMP_MIB_IF_CONFIG) pResponse->Buffer;
  392. // set IfIndex
  393. pCurIfConfig->IfIndex = IfIndex;
  394. // update interface version
  395. dwValue = GET_ASN_INTEGER(&pNewIfConfig->igmpInterfaceVersion, 0);
  396. if (dwValue!=0)
  397. pCurIfConfig->IgmpProtocolType = (dwValue==1)
  398. ? IGMP_ROUTER_V1
  399. : IGMP_ROUTER_V2;
  400. // update RobustnessVariable
  401. pCurIfConfig->RobustnessVariable
  402. = GET_ASN_INTEGER(&pNewIfConfig->igmpInterfaceRobustness, 0);
  403. // calculate StartupQueryCount from RobustnessVariable
  404. pCurIfConfig->StartupQueryCount
  405. = pCurIfConfig->RobustnessVariable;
  406. // update igmpInterfaceQueryInterval
  407. pCurIfConfig->GenQueryInterval
  408. = GET_ASN_INTEGER(&pNewIfConfig->igmpInterfaceQueryInterval, 0);
  409. // calculate value of StartupQueryInterval from GenQueryInterval
  410. pCurIfConfig->StartupQueryInterval
  411. = (DWORD)(0.25*pCurIfConfig->GenQueryInterval);
  412. // update GenQueryMaxResponseTime
  413. pCurIfConfig->GenQueryMaxResponseTime
  414. = GET_ASN_INTEGER(
  415. &pNewIfConfig->igmpInterfaceQueryMaxResponseTime, 0
  416. );
  417. // update LastMemQueryInterval
  418. pCurIfConfig->LastMemQueryInterval
  419. = GET_ASN_INTEGER(
  420. &pNewIfConfig->igmpInterfaceLastMembQueryInterval, 0
  421. );
  422. // calculate LastMemQueryCount from RobustnessVariable
  423. pCurIfConfig->LastMemQueryCount = pCurIfConfig->RobustnessVariable;
  424. // LeaveEnabled is not changed
  425. //
  426. // Save interface config
  427. //
  428. dwSetSize = sizeof(IGMP_MIB_SET_INPUT_DATA) - 1 +
  429. sizeof(IGMP_MIB_IF_CONFIG);
  430. pSetInputData = (PIGMP_MIB_SET_INPUT_DATA) IGMP_MIB_ALLOC(dwSetSize);
  431. if (!pSetInputData) {
  432. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  433. TRACE0( " Not enough memory " );
  434. break;
  435. }
  436. pSetInputData->TypeId = IGMP_IF_CONFIG_ID;
  437. pSetInputData->Flags = 0;
  438. pSetInputData->BufferSize = sizeof(IGMP_MIB_IF_CONFIG);
  439. CopyMemory(
  440. pSetInputData->Buffer,
  441. pCurIfConfig,
  442. pSetInputData->BufferSize
  443. );
  444. IGMP_MIB_SET(pSetInputData, dwSetSize, dwRes);
  445. if (dwRes!=NO_ERROR) {
  446. TraceError( dwRes );
  447. break;
  448. }
  449. dwRes = MIB_S_SUCCESS;
  450. } END_BREAKOUT_BLOCK;
  451. if (pResponse)
  452. MprAdminMIBBufferFree(pResponse);
  453. if (pSetInputData)
  454. IGMP_MIB_FREE(pSetInputData);
  455. return dwRes;
  456. }
  457. UINT
  458. set_igmpInterfaceEntry(
  459. UINT ActionId,
  460. AsnAny * ObjectArray,
  461. UINT * ErrorIndex
  462. )
  463. {
  464. DWORD dwRes = NO_ERROR;
  465. TraceEnter("set_igmpInterfaceEntry");
  466. switch (ActionId)
  467. {
  468. case MIB_ACTION_VALIDATE :
  469. dwRes = ValidateInterfaceConfig(ObjectArray);
  470. break;
  471. case MIB_ACTION_SET :
  472. dwRes = SetInterfaceConfig(ObjectArray);
  473. break;
  474. case MIB_ACTION_CLEANUP :
  475. dwRes = MIB_S_SUCCESS;
  476. break;
  477. default :
  478. TRACE0("set_ifConfigEntry - wrong action");
  479. dwRes = MIB_S_INVALID_PARAMETER;
  480. break;
  481. } //end switch(ActionId)
  482. TraceLeave("set_igmpInterfaceEntry");
  483. return dwRes;
  484. }
  485. ///////////////////////////////////////////////////////////////////////////////
  486. // //
  487. // igmpCacheEntry table (1,3,6,1,3,59,1,1,2,1) //
  488. // //
  489. ///////////////////////////////////////////////////////////////////////////////
  490. UINT
  491. get_igmpCacheEntry(
  492. UINT ActionId,
  493. AsnAny * ObjectArray,
  494. UINT * ErrorIndex
  495. )
  496. {
  497. DWORD dwRes = NO_ERROR;
  498. PIGMP_MIB_GET_OUTPUT_DATA pResponse;
  499. DWORD IfIndex, Group, ReturnedGroup, dwTmpActionId;
  500. buf_igmpCacheEntry *pMibCacheEntry
  501. = (buf_igmpCacheEntry*)ObjectArray;
  502. PIGMP_MIB_GROUP_INFO pGIEntry;
  503. PIGMP_MIB_GROUP_IFS_LIST pGroupIfsList;
  504. TraceEnter("get_igmpCacheEntry");
  505. // get the interface index
  506. IfIndex = GET_ASN_INTEGER(&pMibCacheEntry->igmpCacheIfIndex, 0);
  507. // get the group address
  508. Group = GET_ASN_IP_ADDRESS(&pMibCacheEntry->igmpCacheAddress, 0);
  509. TRACE2("get_igmpCacheEntry called with IfIndex:%d, Group:%d.%d.%d.%d",
  510. IfIndex, PRINT_IPADDR(Group));
  511. dwTmpActionId = ActionId;
  512. if ( Group==0 && ActionId==MIB_ACTION_GETNEXT )
  513. {
  514. dwTmpActionId = MIB_ACTION_GETFIRST;
  515. }
  516. else if (ActionId==MIB_ACTION_GETNEXT)
  517. {
  518. dwTmpActionId = MIB_ACTION_GET;
  519. }
  520. pResponse = NULL;
  521. while (1) {
  522. if (pResponse)
  523. MprAdminMIBBufferFree(pResponse);
  524. TRACE2("GetCacheEntry() called for Group: %d.%d.%d.%d, If:%d",
  525. PRINT_IPADDR(Group), IfIndex);
  526. //
  527. // retrieve the cache entry
  528. //
  529. dwRes = GetCacheEntry(
  530. dwTmpActionId,
  531. IfIndex,
  532. Group,
  533. &ReturnedGroup,
  534. &pResponse
  535. );
  536. if (Group!=ReturnedGroup)
  537. IfIndex = 0;
  538. dwTmpActionId = MIB_ACTION_GETNEXT;
  539. // return if error
  540. if (dwRes!=NO_ERROR) {
  541. TraceError(dwRes);
  542. TraceLeave("get_igmpCacheEntry");
  543. return dwRes;
  544. }
  545. pGroupIfsList = (PIGMP_MIB_GROUP_IFS_LIST)pResponse->Buffer;
  546. // no ifs for that group
  547. if (pGroupIfsList->NumInterfaces == 0) {
  548. // for GET return error
  549. if (ActionId==MIB_ACTION_GET || ActionId==MIB_ACTION_GETFIRST)
  550. {
  551. MprAdminMIBBufferFree(pResponse);
  552. return MIB_S_ENTRY_NOT_FOUND;
  553. }
  554. // for GETNEXT continue with next group
  555. else
  556. {
  557. Group = ReturnedGroup;
  558. continue;
  559. }
  560. }
  561. pGIEntry = (PIGMP_MIB_GROUP_INFO)pGroupIfsList->Buffer;
  562. // if GET, then try to find the exact entry
  563. if (ActionId==MIB_ACTION_GET)
  564. {
  565. DWORD i;
  566. for (i=0; i<pGroupIfsList->NumInterfaces; i++,pGIEntry++)
  567. {
  568. if (pGIEntry->IfIndex==IfIndex)
  569. break;
  570. }
  571. // exact entry not found for GET
  572. if (i==pGroupIfsList->NumInterfaces)
  573. {
  574. MprAdminMIBBufferFree(pResponse);
  575. return MIB_S_ENTRY_NOT_FOUND;
  576. }
  577. }
  578. else if (ActionId==MIB_ACTION_GETNEXT)
  579. {
  580. DWORD i;
  581. PIGMP_MIB_GROUP_INFO pNextGI = pGIEntry;
  582. for (i=0; i<pGroupIfsList->NumInterfaces; i++,pGIEntry++)
  583. {
  584. if (pGIEntry->IfIndex > IfIndex &&
  585. pGIEntry->IfIndex < pNextGI->IfIndex)
  586. {
  587. pNextGI = pGIEntry;
  588. }
  589. }
  590. if (pNextGI->IfIndex <= IfIndex)
  591. {
  592. Group = ReturnedGroup;
  593. continue;
  594. }
  595. else
  596. pGIEntry = pNextGI;
  597. }
  598. break;
  599. }
  600. //
  601. // fill in the required fields and return the MibCacheEntry
  602. //
  603. Group = ReturnedGroup;
  604. IfIndex = pGIEntry->IfIndex;
  605. TRACE2("GetCacheEntry() returned for Interface: %d for group(%d.%d.%d.%d)",
  606. IfIndex, PRINT_IPADDR(Group));
  607. //
  608. // set Group/IfIndex for following getnext operation, (if any)
  609. //
  610. FORCE_SET_ASN_IP_ADDRESS(
  611. &(pMibCacheEntry->igmpCacheAddress),
  612. &(pMibCacheEntry->igmpCacheAddressBuf),
  613. Group
  614. );
  615. FORCE_SET_ASN_INTEGER(&(pMibCacheEntry->igmpCacheIfIndex),
  616. IfIndex);
  617. // find out if the group is added on the localhost interface
  618. {
  619. DWORD BufLen, Status;
  620. IPAddr *pIgmpList = NULL, *pIgmpEntry;
  621. // set all default values to false
  622. SET_ASN_INTEGER(&(pMibCacheEntry->igmpCacheSelf), 2);
  623. GetIgmpList(pGIEntry->IpAddr, NULL, &BufLen);
  624. pIgmpList = HeapAlloc(GetProcessHeap(), 0, BufLen);
  625. if (pIgmpList) {
  626. Status = GetIgmpList(pGIEntry->IpAddr, pIgmpList, &BufLen);
  627. if (Status == STATUS_SUCCESS)
  628. {
  629. ULONG Count = BufLen/sizeof(IPAddr);
  630. ULONG i;
  631. for (i=0,pIgmpEntry=pIgmpList; i<Count; i++,pIgmpEntry++)
  632. {
  633. if (*pIgmpEntry == Group) {
  634. SET_ASN_INTEGER(&(pMibCacheEntry->igmpCacheSelf), 1);
  635. break;
  636. }
  637. }
  638. }
  639. HeapFree(GetProcessHeap(), 0, pIgmpList);
  640. }
  641. }
  642. SET_ASN_IP_ADDRESS(&pMibCacheEntry->igmpCacheLastReporter,
  643. &pMibCacheEntry->igmpCacheLastReporterBuf,
  644. pGIEntry->LastReporter);
  645. // multiply GroupUpTime and GroupExpiryTime by 100 to get timeTicks
  646. SET_ASN_TIME_TICKS(&(pMibCacheEntry->igmpCacheUpTime),
  647. pGIEntry->GroupUpTime*100);
  648. SET_ASN_TIME_TICKS(&(pMibCacheEntry->igmpCacheExpiryTime),
  649. pGIEntry->GroupExpiryTime*100);
  650. // cache status is always active(1)
  651. SET_ASN_INTEGER(&(pMibCacheEntry->igmpCacheStatus), 1);
  652. SET_ASN_INTEGER(&(pMibCacheEntry->igmpCacheVersion1HostTimer),
  653. pGIEntry->V1HostPresentTimeLeft);
  654. MprAdminMIBBufferFree(pResponse);
  655. TraceLeave("get_igmpCacheEntry");
  656. return dwRes;
  657. }
  658. DWORD
  659. GetCacheEntry(
  660. DWORD ActionId,
  661. DWORD IfIndex,
  662. DWORD Group,
  663. DWORD *pNextGroup,
  664. PIGMP_MIB_GET_OUTPUT_DATA *ppResponse
  665. )
  666. /*++
  667. Routine Description:
  668. Get the Group-Interface entry from igmp.
  669. --*/
  670. {
  671. IGMP_MIB_GET_INPUT_DATA Query;
  672. DWORD dwErr = NO_ERROR, dwOutSize;
  673. *ppResponse = NULL;
  674. ZeroMemory(&Query, sizeof(Query));
  675. Query.TypeId = IGMP_GROUP_IFS_LIST_ID;
  676. Query.Flags = IGMP_ENUM_ONE_ENTRY | IGMP_ENUM_ALL_INTERFACES_GROUPS;
  677. Query.Count = 1;
  678. Query.IfIndex = IfIndex;
  679. Query.GroupAddr = Group;
  680. switch (ActionId) {
  681. //
  682. // ERROR_INVALID_PARAMETER is returned when there are no
  683. // interfaces with groups
  684. // RPC_S_SERVER_UNAVAILABLE is returned when the router
  685. // isn't running.
  686. //
  687. case MIB_ACTION_GET :
  688. {
  689. IGMP_MIB_GET(&Query, sizeof(Query), ppResponse,
  690. &dwOutSize, dwErr);
  691. if (dwErr==ERROR_INVALID_PARAMETER
  692. || dwErr==RPC_S_SERVER_UNAVAILABLE)
  693. dwErr = MIB_S_ENTRY_NOT_FOUND;
  694. break;
  695. }
  696. case MIB_ACTION_GETFIRST :
  697. {
  698. IGMP_MIB_GETFIRST(&Query, sizeof(Query), ppResponse,
  699. &dwOutSize, dwErr);
  700. if (dwErr==ERROR_INVALID_PARAMETER
  701. || dwErr==RPC_S_SERVER_UNAVAILABLE)
  702. dwErr = MIB_S_NO_MORE_ENTRIES;
  703. break;
  704. }
  705. case MIB_ACTION_GETNEXT :
  706. {
  707. IGMP_MIB_GETNEXT(&Query, sizeof(Query), ppResponse,
  708. &dwOutSize, dwErr);
  709. if (dwErr==ERROR_INVALID_PARAMETER
  710. || dwErr==RPC_S_SERVER_UNAVAILABLE)
  711. dwErr = MIB_S_NO_MORE_ENTRIES;
  712. break;
  713. }
  714. default :
  715. {
  716. dwErr = MIB_S_INVALID_PARAMETER;
  717. break;
  718. }
  719. }
  720. if (dwErr!=NO_ERROR)
  721. *ppResponse = NULL;
  722. else
  723. *pNextGroup = Query.GroupAddr;
  724. return dwErr;
  725. }
  726. UINT
  727. set_igmpCacheEntry(
  728. UINT ActionId,
  729. AsnAny * ObjectArray,
  730. UINT * ErrorIndex
  731. )
  732. {
  733. return MIB_S_NOT_SUPPORTED;
  734. }
  735. DWORD
  736. ConnectToRouter(
  737. )
  738. {
  739. DWORD dwRes = (DWORD) -1;
  740. EnterCriticalSection( &g_CS );
  741. do
  742. {
  743. MPR_SERVER_HANDLE hTmp;
  744. if ( g_hMibServer )
  745. {
  746. dwRes = NO_ERROR;
  747. break;
  748. }
  749. dwRes = MprAdminMIBServerConnect( NULL, &hTmp );
  750. if ( dwRes == NO_ERROR )
  751. {
  752. InterlockedExchangePointer(&g_hMibServer, hTmp );
  753. }
  754. else
  755. {
  756. TRACE1(
  757. "Error %d setting up DIM connection to MIB Server\n",
  758. dwRes
  759. );
  760. }
  761. } while ( FALSE );
  762. LeaveCriticalSection( &g_CS );
  763. return dwRes;
  764. }