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.

1227 lines
36 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. routing\ip\mcastmib\mibfuncs.c
  5. Abstract:
  6. IP Multicast MIB instrumentation callbacks
  7. Revision history:
  8. Dave Thaler 4/17/98 Created
  9. --*/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. //
  13. // Define this to report a dummy MFE
  14. //
  15. #undef SAMPLE_MFE
  16. #define ROWSTATUS_ACTIVE 1
  17. DWORD
  18. ConnectToRouter();
  19. DWORD
  20. SetGlobalInfo(
  21. IN AsnAny * objectArray
  22. );
  23. DWORD
  24. GetMibInfo(
  25. IN UINT actionId,
  26. IN PMIB_OPAQUE_QUERY pQuery,
  27. IN DWORD dwQuerySize,
  28. OUT PMIB_OPAQUE_INFO * ppimgod,
  29. OUT PDWORD pdwOutSize
  30. );
  31. //
  32. // IP Multicast MIB scalar objects
  33. //
  34. UINT
  35. get_global(
  36. UINT actionId,
  37. AsnAny *objectArray,
  38. UINT *errorIndex
  39. )
  40. {
  41. DWORD dwErr = ERROR_NOT_FOUND;
  42. DWORD dwNumEntries = 1;
  43. PMIB_IPMCAST_GLOBAL pEntry;
  44. buf_global *pOutput;
  45. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  46. DWORD dwOutBufferSize = 0;
  47. MIB_OPAQUE_QUERY pQueryBuff, *pQuery = &pQueryBuff;
  48. DWORD dwQuerySize;
  49. TraceEnter("get_global");
  50. pOutput = (buf_global*)objectArray;
  51. pQuery->dwVarId = MCAST_GLOBAL;
  52. dwQuerySize = sizeof(MIB_OPAQUE_QUERY) - sizeof(DWORD);
  53. dwErr = GetMibInfo(actionId, pQuery, dwQuerySize,
  54. &pRpcInfo, &dwOutBufferSize);
  55. if (dwErr != NO_ERROR) {
  56. TraceError(dwErr);
  57. return dwErr;
  58. }
  59. pEntry = (PMIB_IPMCAST_GLOBAL) pRpcInfo->rgbyData;
  60. SetAsnInteger(&(pOutput->ipMRouteEnable), pEntry->dwEnable);
  61. if (pRpcInfo)
  62. MprAdminMIBBufferFree(pRpcInfo);
  63. TraceLeave("get_global");
  64. return MIB_S_SUCCESS;
  65. }
  66. //
  67. // IP Multicast Interface Table support
  68. //
  69. // We cache the fields which are static config info (such as protocol)
  70. // so that queries that access only these rows can consult the cache
  71. // rather than forcing a call to the router manager, kernel diving, etc.
  72. //
  73. typedef struct {
  74. DWORD dwIfIndex; // interface to which this info applies
  75. DWORD dwProtocol; // multicast protocol owning that interface
  76. DWORD dwTimestamp; // time at which above info was obtained
  77. } MCAST_IF_CONFIG;
  78. #define CACHE_SIZE 100 // number of interfaces to cache
  79. MCAST_IF_CONFIG *cacheArray[CACHE_SIZE];
  80. static int
  81. GetCacheIdx(dwIfIndex)
  82. DWORD dwIfIndex;
  83. {
  84. register int i;
  85. for (i=0; i<CACHE_SIZE; i++)
  86. if (cacheArray[i] && cacheArray[i]->dwIfIndex==dwIfIndex)
  87. return i;
  88. return -1;
  89. }
  90. static void
  91. UpdateCacheInterfaceConfig(dwCacheIdx, newIfConfig)
  92. DWORD dwCacheIdx;
  93. MCAST_IF_CONFIG *newIfConfig;
  94. {
  95. // Free the old one
  96. if (cacheArray[dwCacheIdx])
  97. MULTICAST_MIB_FREE( cacheArray[dwCacheIdx] );
  98. // Store the new one
  99. cacheArray[dwCacheIdx] = newIfConfig;
  100. }
  101. static void
  102. AddCacheInterfaceConfig(pIfConfig)
  103. MCAST_IF_CONFIG *pIfConfig;
  104. {
  105. register int i, best = -1;
  106. // Find empty or oldest spot
  107. for (i=0; i<CACHE_SIZE; i++) {
  108. if (!cacheArray[i]) {
  109. best=i;
  110. break;
  111. }
  112. if (best<0 || cacheArray[i]->dwTimestamp < cacheArray[best]->dwTimestamp)
  113. best=i;
  114. }
  115. UpdateCacheInterfaceConfig(best, pIfConfig);
  116. }
  117. static MCAST_IF_CONFIG *
  118. SaveInterfaceConfig(pEntry)
  119. PMIB_IPMCAST_IF_ENTRY pEntry;
  120. {
  121. MCAST_IF_CONFIG *pIfConfig;
  122. int iCacheIdx;
  123. TRACE1("SaveInterfaceConfig %d\n", pEntry->dwIfIndex);
  124. pIfConfig= MULTICAST_MIB_ALLOC(sizeof(MCAST_IF_CONFIG));
  125. if (!pIfConfig) {
  126. return NULL;
  127. }
  128. pIfConfig->dwIfIndex = pEntry->dwIfIndex;
  129. pIfConfig->dwProtocol = pEntry->dwProtocol;
  130. pIfConfig->dwTimestamp = GetCurrentTime();
  131. iCacheIdx = GetCacheIdx(pEntry->dwIfIndex);
  132. if (iCacheIdx >= 0)
  133. UpdateCacheInterfaceConfig((DWORD)iCacheIdx, pIfConfig);
  134. else
  135. AddCacheInterfaceConfig(pIfConfig);
  136. return pIfConfig;
  137. }
  138. MCAST_IF_CONFIG *
  139. GetInterfaceConfig(dwIfIndex)
  140. DWORD dwIfIndex;
  141. {
  142. MCAST_IF_CONFIG *outIfConfig = NULL;
  143. MCAST_IF_CONFIG *pIfConfig;
  144. DWORD dwQuerySize;
  145. MIB_OPAQUE_QUERY pQueryBuff, *pQuery = &pQueryBuff;
  146. DWORD dwErr = ERROR_NOT_FOUND;
  147. DWORD dwNumEntries = 1;
  148. PMIB_IPMCAST_IF_ENTRY pEntry;
  149. buf_ipMRouteInterfaceEntry *pOutput;
  150. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  151. DWORD dwOutBufferSize = 0;
  152. TRACE1("GetInterfaceConfig %d\n", dwIfIndex);
  153. // Do a MIB lookup
  154. pQuery->dwVarId = MCAST_IF_ENTRY;
  155. pQuery->rgdwVarIndex[0] = dwIfIndex;
  156. dwQuerySize = sizeof(MIB_OPAQUE_QUERY);
  157. dwErr = GetMibInfo(MIB_ACTION_GET, pQuery, dwQuerySize,
  158. &pRpcInfo, &dwOutBufferSize);
  159. // Save each entry returned
  160. if (dwErr == NO_ERROR) {
  161. pEntry = (PMIB_IPMCAST_IF_ENTRY) pRpcInfo->rgbyData;
  162. pIfConfig = SaveInterfaceConfig(pEntry);
  163. if (pEntry->dwIfIndex == dwIfIndex)
  164. outIfConfig = pIfConfig;
  165. }
  166. // Return the saved entry which was asked for
  167. if (pRpcInfo)
  168. MprAdminMIBBufferFree(pRpcInfo);
  169. return outIfConfig;
  170. }
  171. MCAST_IF_CONFIG *
  172. ForceGetCacheInterfaceConfig(dwIfIndex)
  173. DWORD dwIfIndex;
  174. {
  175. MCAST_IF_CONFIG *tmpIfConfig;
  176. int iCacheIdx = GetCacheIdx(dwIfIndex);
  177. TRACE2("ForceGetCacheInterfaceConfig ifIndex=%d ci=%d\n", dwIfIndex,
  178. iCacheIdx);
  179. if (iCacheIdx >= 0
  180. && GetCurrentTime() - cacheArray[iCacheIdx]->dwTimestamp
  181. < IPMULTI_IF_CACHE_TIMEOUT)
  182. return cacheArray[iCacheIdx];
  183. // Service a cache miss
  184. tmpIfConfig = GetInterfaceConfig(dwIfIndex);
  185. return tmpIfConfig;
  186. }
  187. static DWORD
  188. GetInterfaceProtocol(dwIfIndex)
  189. DWORD dwIfIndex;
  190. {
  191. // Look up interface config in interface config cache
  192. MCAST_IF_CONFIG *pIfConfig = ForceGetCacheInterfaceConfig(dwIfIndex);
  193. return (pIfConfig)? pIfConfig->dwProtocol : 0;
  194. }
  195. UINT
  196. get_ipMRouteInterfaceEntry(
  197. UINT actionId,
  198. AsnAny * objectArray,
  199. UINT * errorIndex
  200. )
  201. /*++
  202. Routine Description:
  203. Get the InterfaceEntry for IP Multicast. Have to get the InterfaceConfig
  204. and InterfaceStats for the interface from the router.
  205. --*/
  206. {
  207. DWORD dwErr = ERROR_NOT_FOUND;
  208. DWORD dwNumEntries = 1;
  209. PMIB_IPMCAST_IF_ENTRY pEntry;
  210. buf_ipMRouteInterfaceEntry *pOutput;
  211. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  212. DWORD dwOutBufferSize = 0;
  213. MIB_OPAQUE_QUERY pQueryBuff,
  214. *pQuery = &pQueryBuff;
  215. DWORD dwQuerySize;
  216. TraceEnter("get_ipMRouteInterfaceEntry");
  217. pOutput = (buf_ipMRouteInterfaceEntry*)objectArray;
  218. pQuery->dwVarId = MCAST_IF_ENTRY;
  219. pQuery->rgdwVarIndex[0] = GetAsnInteger( &( pOutput->ipMRouteInterfaceIfIndex ), 0 );
  220. dwQuerySize = sizeof(MIB_OPAQUE_QUERY);
  221. dwErr = GetMibInfo(actionId, pQuery, dwQuerySize,
  222. &pRpcInfo, &dwOutBufferSize);
  223. if (dwErr != NO_ERROR) {
  224. TraceError(dwErr);
  225. return ERROR_NO_MORE_ITEMS;
  226. }
  227. pEntry = (PMIB_IPMCAST_IF_ENTRY) pRpcInfo->rgbyData;
  228. SaveInterfaceConfig(pEntry);
  229. // Set index values
  230. ForceSetAsnInteger(&(pOutput->ipMRouteInterfaceIfIndex), pEntry->dwIfIndex);
  231. // Set other values
  232. SetAsnInteger(&(pOutput->ipMRouteInterfaceTtl), pEntry->dwTtl);
  233. SetAsnInteger(&(pOutput->ipMRouteInterfaceProtocol), pEntry->dwProtocol);
  234. SetAsnInteger(&(pOutput->ipMRouteInterfaceRateLimit), pEntry->dwRateLimit);
  235. SetAsnCounter(&(pOutput->ipMRouteInterfaceInMcastOctets),
  236. pEntry->ulInMcastOctets);
  237. SetAsnCounter(&(pOutput->ipMRouteInterfaceOutMcastOctets),
  238. pEntry->ulOutMcastOctets);
  239. if (pRpcInfo)
  240. MprAdminMIBBufferFree(pRpcInfo);
  241. TraceLeave("get_ipMRouteInterfaceEntry");
  242. return MIB_S_SUCCESS;
  243. }
  244. //
  245. // Multicast Forwarding Table (ipMRouteTable) support
  246. //
  247. UINT
  248. get_ipMRouteEntry(
  249. UINT actionId,
  250. AsnAny * objectArray,
  251. UINT * errorIndex
  252. )
  253. /*++
  254. Routine Description:
  255. Get the MFE information based on the input criteria.
  256. --*/
  257. {
  258. DWORD dwResult = ERROR_NOT_FOUND;
  259. DWORD dwNumEntries = 1;
  260. IPMCAST_MFE mfe;
  261. IPMCAST_MFE_STATS mfeStats;
  262. #ifdef SAMPLE_MFE
  263. MIB_IPMCAST_MFE_STATS sampledata;
  264. #endif
  265. PMIB_IPMCAST_MFE_STATS pEntry;
  266. PMIB_MFE_STATS_TABLE pTable = NULL;
  267. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  268. DWORD dwOutBufferSize = 0;
  269. buf_ipMRouteEntry *pOutput;
  270. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  271. // fields, so we don't have to malloc
  272. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  273. DWORD dwQuerySize;
  274. BOOL bPart;
  275. TraceEnter("get_ipMRouteEntry");
  276. pOutput = (buf_ipMRouteEntry*)objectArray;
  277. pQuery->dwVarId = MCAST_MFE_STATS;
  278. // Extract the instance info
  279. pQuery->rgdwVarIndex[0] = GetAsnIPAddress( &pOutput->ipMRouteGroup, 0 );
  280. pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &pOutput->ipMRouteSource,
  281. 0xFFFFFFFF );
  282. pQuery->rgdwVarIndex[2] = GetAsnIPAddress( &pOutput->ipMRouteSourceMask,
  283. 0xFFFFFFFF);
  284. //
  285. // Fix up query if instance was partially-specified.
  286. // This section can go away if the SNMP API does this for us.
  287. //
  288. if (!pOutput->ipMRouteGroup.asnType
  289. || !pOutput->ipMRouteGroup.asnValue.string.length) {
  290. actionId = MIB_ACTION_GETFIRST;
  291. } else {
  292. if (!pOutput->ipMRouteSource.asnType
  293. || !pOutput->ipMRouteSource.asnValue.string.length) {
  294. if (pQuery->rgdwVarIndex[0]) {
  295. pQuery->rgdwVarIndex[0]--;
  296. } else {
  297. actionId = MIB_ACTION_GETFIRST;
  298. }
  299. } else {
  300. if (!pOutput->ipMRouteSourceMask.asnType
  301. || !pOutput->ipMRouteSourceMask.asnValue.string.length) {
  302. if (pQuery->rgdwVarIndex[1]) {
  303. pQuery->rgdwVarIndex[1]--;
  304. } else {
  305. if (pQuery->rgdwVarIndex[0]) {
  306. pQuery->rgdwVarIndex[0]--;
  307. pQuery->rgdwVarIndex[1] = 0xFFFFFFFF;
  308. } else {
  309. actionId = MIB_ACTION_GETFIRST;
  310. }
  311. }
  312. }
  313. }
  314. }
  315. dwQuerySize = sizeof(MIB_OPAQUE_QUERY) + 2*sizeof(DWORD);
  316. #ifndef SAMPLE_MFE
  317. dwResult = GetMibInfo(actionId, pQuery, dwQuerySize,
  318. &pRpcInfo, &dwOutBufferSize);
  319. if (dwResult != NO_ERROR) {
  320. TraceError(dwResult);
  321. return dwResult;
  322. }
  323. pTable = (PMIB_MFE_STATS_TABLE)( pRpcInfo->rgbyData);
  324. if (pTable->dwNumEntries == 0)
  325. {
  326. MprAdminMIBBufferFree( pRpcInfo );
  327. return MIB_S_NO_MORE_ENTRIES;
  328. }
  329. pEntry = pTable->table; // use first entry returned
  330. #else
  331. pEntry = &sampledata;
  332. if (pQuery->rgdwVarIndex[0] >= 0x01010101)
  333. return MIB_S_NO_MORE_ENTRIES;
  334. sampledata.dwGroup = 0x01010101; /* (*,G) Entry */
  335. sampledata.dwSource = 0x00000000;
  336. sampledata.dwSrcMask = 0x00000000;
  337. // don't care what the other values are for this test
  338. #endif
  339. // Save index terms
  340. ForceSetAsnIPAddress(&(pOutput->ipMRouteGroup),
  341. &(pOutput->dwIpMRouteGroupInfo),
  342. pEntry->dwGroup);
  343. ForceSetAsnIPAddress(&(pOutput->ipMRouteSource),
  344. &(pOutput->dwIpMRouteSourceInfo),
  345. pEntry->dwSource);
  346. ForceSetAsnIPAddress(&(pOutput->ipMRouteSourceMask),
  347. &(pOutput->dwIpMRouteSourceMaskInfo),
  348. pEntry->dwSrcMask);
  349. // Save other terms
  350. SetAsnIPAddress(&pOutput->ipMRouteUpstreamNeighbor,
  351. &pOutput->dwIpMRouteUpstreamNeighborInfo,
  352. pEntry->dwUpStrmNgbr);
  353. SetAsnInteger(&(pOutput->ipMRouteInIfIndex), pEntry->dwInIfIndex);
  354. SetAsnTimeTicks(&(pOutput->ipMRouteUpTime), pEntry->ulUpTime);
  355. SetAsnTimeTicks(&(pOutput->ipMRouteExpiryTime), pEntry->ulExpiryTime);
  356. SetAsnCounter(&(pOutput->ipMRoutePkts), pEntry->ulInPkts);
  357. SetAsnCounter(&(pOutput->ipMRouteDifferentInIfPackets),
  358. pEntry->ulPktsDifferentIf);
  359. SetAsnCounter(&(pOutput->ipMRouteOctets), pEntry->ulInOctets);
  360. // For protocol, we'll just report the protocol owning the iif
  361. SetAsnInteger(&(pOutput->ipMRouteProtocol),
  362. GetInterfaceProtocol(pEntry->dwInIfIndex));
  363. SetAsnInteger(&pOutput->ipMRouteRtProto, pEntry->dwRouteProtocol);
  364. SetAsnIPAddress(&pOutput->ipMRouteRtAddress,
  365. &pOutput->dwIpMRouteRtAddressInfo,
  366. pEntry->dwRouteNetwork);
  367. SetAsnIPAddress(&pOutput->ipMRouteRtMask,
  368. &pOutput->dwIpMRouteRtMaskInfo,
  369. pEntry->dwRouteMask);
  370. if ( pRpcInfo ) { MprAdminMIBBufferFree( pRpcInfo ); }
  371. TraceLeave("get_ipMRouteEntry");
  372. return MIB_S_SUCCESS;
  373. }
  374. //
  375. // Multicast Forwarding Next Hop table (ipMRouteNextHopTable) support
  376. //
  377. static DWORD
  378. LocateMfeOif(actionId, pQuery, oifIndex, oifAddress, ppEntry, ppOif,
  379. ppRpcInfo)
  380. UINT actionId;
  381. MIB_OPAQUE_QUERY *pQuery;
  382. DWORD oifIndex;
  383. DWORD oifAddress;
  384. PMIB_IPMCAST_MFE_STATS *ppEntry;
  385. PMIB_IPMCAST_OIF_STATS *ppOif;
  386. PMIB_OPAQUE_INFO *ppRpcInfo;
  387. /*++
  388. Routine Description:
  389. Get the exact/next/first oif entry based on the input criteria.
  390. --*/
  391. {
  392. DWORD dwResult = MIB_S_SUCCESS;
  393. DWORD dwQuerySize = sizeof(MIB_OPAQUE_QUERY) + 2*sizeof(DWORD);
  394. DWORD dwOutBufferSize = 0;
  395. PMIB_MFE_STATS_TABLE pTable = NULL;
  396. PMIB_IPMCAST_MFE_STATS pEntry = NULL;
  397. PMIB_IPMCAST_OIF_STATS pOif = NULL;
  398. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  399. BOOL oifIndexAny = FALSE;
  400. BOOL oifAddressAny = FALSE;
  401. DWORD idx;
  402. BOOL bFound;
  403. do {
  404. // Get the first MFE which applies (if any)
  405. dwResult = GetMibInfo(actionId, pQuery, dwQuerySize,
  406. &pRpcInfo, &dwOutBufferSize);
  407. if (dwResult != NO_ERROR) {
  408. TraceError(dwResult);
  409. return dwResult;
  410. }
  411. pTable = (PMIB_MFE_STATS_TABLE)( pRpcInfo->rgbyData);
  412. if (pTable->dwNumEntries == 0) {
  413. MprAdminMIBBufferFree( pRpcInfo );
  414. return MIB_S_NO_MORE_ENTRIES;
  415. }
  416. pEntry = pTable->table; // use first entry returned
  417. // Get the first OIF which applies (if any)
  418. bFound=FALSE;
  419. for (idx=0; !bFound && idx < pEntry->ulNumOutIf; idx++) {
  420. pOif = &pEntry->rgmiosOutStats[idx];
  421. // Do processing for GET
  422. if (actionId==MIB_ACTION_GET) {
  423. if (oifIndex == pOif->dwOutIfIndex
  424. && oifAddress == pOif->dwNextHopAddr) {
  425. bFound=TRUE;
  426. break;
  427. } else
  428. continue;
  429. }
  430. // Do processing for GET-NEXT
  431. if ( oifIndexAny == TRUE
  432. || oifIndex < pOif->dwOutIfIndex
  433. || (oifIndex == pOif->dwOutIfIndex
  434. && (oifAddressAny == TRUE
  435. || oifAddress < pOif->dwNextHopAddr))) {
  436. bFound=TRUE;
  437. break;
  438. }
  439. }
  440. if (bFound)
  441. break;
  442. // else continue and get a new entry
  443. pQuery->rgdwVarIndex[0] = pEntry->dwGroup;
  444. pQuery->rgdwVarIndex[1] = pEntry->dwSource;
  445. pQuery->rgdwVarIndex[2] = pEntry->dwSrcMask;
  446. oifAddressAny = oifIndexAny = TRUE;
  447. } while (actionId != MIB_ACTION_GET); // once for GET, "forever" for others
  448. *ppEntry = pEntry;
  449. *ppOif = pOif;
  450. *ppRpcInfo = pRpcInfo;
  451. return dwResult;
  452. }
  453. UINT
  454. get_ipMRouteNextHopEntry(
  455. UINT actionId,
  456. AsnAny * objectArray,
  457. UINT * errorIndex
  458. )
  459. {
  460. DWORD dwResult = ERROR_NOT_FOUND;
  461. DWORD dwNumEntries = 1;
  462. IPMCAST_MFE mfe;
  463. IPMCAST_MFE_STATS mfeStats;
  464. #ifdef SAMPLE_MFE
  465. MIB_IPMCAST_MFE_STATS sampledata;
  466. #endif
  467. PMIB_IPMCAST_MFE_STATS pEntry;
  468. PMIB_IPMCAST_OIF_STATS pOif;
  469. PMIB_MFE_STATS_TABLE pTable = NULL;
  470. DWORD dwOutBufferSize = 0;
  471. buf_ipMRouteNextHopEntry *pOutput;
  472. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  473. // fields, so we don't have to malloc
  474. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  475. DWORD dwQuerySize;
  476. DWORD oifIndex, oifAddress;
  477. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  478. TraceEnter("get_ipMRouteNextHopEntry");
  479. pOutput = (buf_ipMRouteNextHopEntry*)objectArray;
  480. pQuery->dwVarId = MCAST_MFE_STATS;
  481. //
  482. // XXX Note that the 3 lines below aren't quite right, since
  483. // 0-value instances will be missed. That is (*,G) entries
  484. // will be skipped!!
  485. //
  486. // Should call for a GET-FIRST if an incomplete length is given.
  487. // Maybe the Sfx API does this already.
  488. //
  489. // XXX hold off on changing this until Florin changes the SNMP
  490. // api to cover the out-of-range index case.
  491. //
  492. pQuery->rgdwVarIndex[0] = GetAsnIPAddress( &( pOutput->ipMRouteNextHopGroup ), 0 );
  493. pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &( pOutput->ipMRouteNextHopSource), 0 );
  494. pQuery->rgdwVarIndex[2] = GetAsnIPAddress( &( pOutput->ipMRouteNextHopSourceMask ), 0 );
  495. oifIndex = GetAsnInteger( &(pOutput->ipMRouteNextHopIfIndex), 0);
  496. oifAddress = GetAsnIPAddress( &(pOutput->ipMRouteNextHopAddress), 0);
  497. #ifndef SAMPLE_MFE
  498. {
  499. dwResult = LocateMfeOif(actionId, pQuery, oifIndex, oifAddress,
  500. &pEntry, &pOif, &pRpcInfo);
  501. if (dwResult != NO_ERROR) {
  502. TraceError(dwResult);
  503. return dwResult;
  504. }
  505. }
  506. #else
  507. {
  508. pEntry = &sampledata;
  509. pOif = &pEntry->rgmiosOutStats[0];
  510. if (pQuery->rgdwVarIndex[0] >= 0x01010101)
  511. return MIB_S_NO_MORE_ENTRIES;
  512. pEntry->dwGroup = 0x01010101;
  513. pEntry->dwSource = 0x02020202;
  514. pEntry->dwSrcMask = 0x03030303;
  515. pEntry->ulNumOutIf = 1;
  516. pOif->dwOutIfIndex = 11;
  517. pOif->dwNextHopAddr = 0x04040404;
  518. pOif->ulOutPackets = 22;
  519. // don't care what the other values are for this test
  520. }
  521. #endif
  522. // Save index terms
  523. ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopGroup),
  524. &(pOutput->dwIpMRouteNextHopGroupInfo),
  525. pEntry->dwGroup);
  526. ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopSource),
  527. &(pOutput->dwIpMRouteNextHopSourceInfo),
  528. pEntry->dwSource);
  529. ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopSourceMask),
  530. &(pOutput->dwIpMRouteNextHopSourceMaskInfo),
  531. pEntry->dwSrcMask);
  532. ForceSetAsnInteger (&(pOutput->ipMRouteNextHopIfIndex),
  533. pOif->dwOutIfIndex);
  534. ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopAddress),
  535. &(pOutput->dwIpMRouteNextHopAddressInfo),
  536. pOif->dwNextHopAddr);
  537. // Save other terms
  538. SetAsnInteger(&(pOutput->ipMRouteNextHopState), 2); // "forwarding"
  539. SetAsnTimeTicks(&(pOutput->ipMRouteNextHopUpTime), pEntry->ulUpTime); // XXX
  540. SetAsnTimeTicks(&(pOutput->ipMRouteNextHopExpiryTime), pEntry->ulExpiryTime); // XXX
  541. #ifdef CLOSEST_MEMBER_HOPS
  542. SetAsnInteger(&(pOutput->ipMRouteNextHopClosestMemberHops), 1);
  543. #endif
  544. SetAsnCounter(&(pOutput->ipMRouteNextHopPkts), pOif->ulOutPackets);
  545. // For protocol, we'll just report the protocol owning the interface
  546. SetAsnInteger(&(pOutput->ipMRouteNextHopProtocol),
  547. GetInterfaceProtocol(pOif->dwOutIfIndex));
  548. if ( pRpcInfo ) { MprAdminMIBBufferFree( pRpcInfo ); }
  549. TraceLeave("get_ipMRouteNextHopEntry");
  550. return MIB_S_SUCCESS;
  551. }
  552. DWORD
  553. SetMibInfo(
  554. IN UINT actionId, // SET, CLEANUP
  555. IN PMIB_OPAQUE_INFO pInfo, // value info
  556. IN DWORD dwInfoSize // size of above
  557. )
  558. {
  559. DWORD dwRes = NO_ERROR;
  560. switch ( actionId )
  561. {
  562. #ifdef THREE_PHASE
  563. case MIB_ACTION_VALIDATE :
  564. MULTICAST_MIB_VALIDATE(
  565. pInfo,
  566. dwInfoSize,
  567. dwRes
  568. );
  569. // ERROR_INVALID_PARAMETER is returned when there is
  570. // no interface for the specified index.
  571. //
  572. if ( dwRes == ERROR_INVALID_PARAMETER )
  573. {
  574. dwRes = MIB_S_INVALID_PARAMETER;
  575. }
  576. break;
  577. #endif
  578. case MIB_ACTION_SET :
  579. #if 1
  580. dwRes = ( g_hMIBServer ) ? NO_ERROR
  581. : ConnectToRouter();
  582. if ( dwRes == NO_ERROR )
  583. {
  584. dwRes = MprAdminMIBEntrySet( g_hMIBServer,
  585. PID_IP,
  586. IPRTRMGR_PID,
  587. (LPVOID) (pInfo),
  588. (dwInfoSize)
  589. );
  590. }
  591. #else
  592. MULTICAST_MIB_COMMIT(
  593. pInfo,
  594. dwInfoSize,
  595. dwRes
  596. );
  597. #endif
  598. // ERROR_INVALID_PARAMETER is returned when there is
  599. // no interface for the specified index.
  600. //
  601. if ( dwRes == ERROR_INVALID_PARAMETER
  602. || dwRes == ERROR_INVALID_INDEX )
  603. {
  604. dwRes = MIB_S_INVALID_PARAMETER;
  605. }
  606. break;
  607. #ifdef THREE_PHASE
  608. case MIB_ACTION_CLEANUP :
  609. MULTICAST_MIB_CLEANUP(
  610. pInfo,
  611. dwInfoSize,
  612. dwRes
  613. );
  614. // ERROR_INVALID_PARAMETER is returned when there is
  615. // no interface for the specified index.
  616. //
  617. if ( dwRes == ERROR_INVALID_PARAMETER )
  618. {
  619. dwRes = MIB_S_INVALID_PARAMETER;
  620. }
  621. break;
  622. #endif
  623. default :
  624. dwRes = MIB_S_INVALID_PARAMETER;
  625. break;
  626. }
  627. return dwRes;
  628. }
  629. DWORD
  630. GetMibInfo(
  631. IN UINT actionId, // GET, GET-NEXT, SET
  632. IN PMIB_OPAQUE_QUERY pQuery, // instance info
  633. IN DWORD dwQuerySize, // size of above
  634. OUT PMIB_OPAQUE_INFO *ppimgod, // value info
  635. OUT PDWORD pdwOutSize // size of above
  636. )
  637. {
  638. DWORD dwRes = (DWORD) -1;
  639. PMIB_OPAQUE_INFO pimgodOutData = NULL;
  640. *ppimgod = NULL;
  641. switch ( actionId )
  642. {
  643. case MIB_ACTION_GET :
  644. MULTICAST_MIB_GET(
  645. pQuery,
  646. dwQuerySize,
  647. &pimgodOutData,
  648. pdwOutSize,
  649. dwRes
  650. );
  651. //
  652. // ERROR_INVALID_PARAMETER is returned when there is
  653. // no interface for the specified index.
  654. // RPC_S_SERVER_UNAVAILABLE is returned when the router
  655. // isn't running.
  656. //
  657. if ( dwRes == ERROR_INVALID_PARAMETER
  658. || dwRes == RPC_S_SERVER_UNAVAILABLE
  659. || dwRes == RPC_S_UNKNOWN_IF )
  660. {
  661. dwRes = MIB_S_ENTRY_NOT_FOUND;
  662. }
  663. break;
  664. case MIB_ACTION_GETFIRST :
  665. MULTICAST_MIB_GETFIRST(
  666. pQuery,
  667. dwQuerySize,
  668. &pimgodOutData,
  669. pdwOutSize,
  670. dwRes
  671. );
  672. //
  673. // ERROR_INVALID_PARAMETER is returned when there is
  674. // no interface for the specified index.
  675. // RPC_S_SERVER_UNAVAILABLE is returned when the router
  676. // isn't running.
  677. //
  678. if ( dwRes == ERROR_INVALID_PARAMETER
  679. || dwRes == RPC_S_SERVER_UNAVAILABLE
  680. || dwRes == RPC_S_UNKNOWN_IF )
  681. {
  682. dwRes = MIB_S_NO_MORE_ENTRIES;
  683. }
  684. break;
  685. case MIB_ACTION_GETNEXT :
  686. MULTICAST_MIB_GETNEXT(
  687. pQuery,
  688. dwQuerySize,
  689. &pimgodOutData,
  690. pdwOutSize,
  691. dwRes
  692. );
  693. //
  694. // ERROR_INVALID_PARAMETER is returned when there is
  695. // no interface for the specified index.
  696. // RPC_S_SERVER_UNAVAILABLE is returned when the router
  697. // isn't running.
  698. //
  699. if ( dwRes == ERROR_INVALID_PARAMETER
  700. || dwRes == ERROR_NO_MORE_ITEMS
  701. || dwRes == RPC_S_SERVER_UNAVAILABLE
  702. || dwRes == RPC_S_UNKNOWN_IF )
  703. {
  704. dwRes = MIB_S_NO_MORE_ENTRIES;
  705. break;
  706. }
  707. //
  708. // Get Next wraps to the next table at the end of the
  709. // entries in the current table. To flag the end of a table,
  710. // check the end of the table.
  711. //
  712. if ( pQuery->dwVarId != pQuery->dwVarId )
  713. {
  714. MprAdminMIBBufferFree( pimgodOutData );
  715. dwRes = MIB_S_NO_MORE_ENTRIES;
  716. }
  717. break;
  718. default :
  719. dwRes = MIB_S_INVALID_PARAMETER;
  720. break;
  721. }
  722. if ( dwRes == NO_ERROR )
  723. {
  724. *ppimgod = pimgodOutData;
  725. }
  726. return dwRes;
  727. }
  728. UINT
  729. set_ipMRouteScopeEntry(
  730. UINT actionId,
  731. AsnAny * objectArray,
  732. UINT * errorIndex
  733. )
  734. {
  735. DWORD dwRes = MIB_S_SUCCESS;
  736. DWORD dwNumEntries = 1;
  737. PMIB_IPMCAST_SCOPE pEntry;
  738. sav_ipMRouteScopeEntry *pOutput;
  739. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  740. DWORD dwOutBufferSize = 0;
  741. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  742. // fields, so we don't have to malloc
  743. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  744. DWORD dwQuerySize;
  745. DWORD dwIfIndex;
  746. DWORD dwAddr;
  747. DWORD dwMask;
  748. TraceEnter("set_ipMRouteScopeEntry");
  749. pOutput = (sav_ipMRouteScopeEntry*)objectArray;
  750. dwAddr = GetAsnIPAddress( &pOutput->ipMRouteScopeAddress, 0 );
  751. dwMask = GetAsnIPAddress( &pOutput->ipMRouteScopeAddressMask, 0 );
  752. switch(actionId) {
  753. case MIB_ACTION_VALIDATE:
  754. //
  755. // Verify that the specified ifIndex, address, and mask are valid.
  756. //
  757. if ((dwAddr & dwMask) != dwAddr) {
  758. TRACE0( "set_ipMRouteScopeEntry: address/mask mismatch" );
  759. dwRes = MIB_S_INVALID_PARAMETER;
  760. } else if (!IN_MULTICAST(ntohl(dwAddr))) {
  761. TRACE0( "set_ipMRouteScopeEntry: non-multicast address" );
  762. dwRes = MIB_S_INVALID_PARAMETER;
  763. }
  764. break;
  765. case MIB_ACTION_SET: {
  766. BYTE pScopeName[MAX_SCOPE_NAME_LEN+1];
  767. DWORD dwInfoSize;
  768. MIB_IPMCAST_SCOPE pScopeBuff[2]; // big enough to hold 1 + mib hdr
  769. // so we don't have to malloc
  770. MIB_OPAQUE_INFO *pInfo = (PMIB_OPAQUE_INFO)&pScopeBuff[0];
  771. PMIB_IPMCAST_SCOPE pScope = (MIB_IPMCAST_SCOPE *)(pInfo->rgbyData);
  772. pInfo->dwId = MCAST_SCOPE;
  773. pScope->dwGroupAddress = dwAddr;
  774. pScope->dwGroupMask = dwMask;
  775. //
  776. // Copy the scope name.
  777. //
  778. pScopeName[0] = '\0';
  779. GetAsnOctetString( pScopeName, &pOutput->ipMRouteScopeName );
  780. MultiByteToWideChar( CP_UTF8,
  781. 0,
  782. pScopeName,
  783. strlen(pScopeName),
  784. pScope->snNameBuffer,
  785. MAX_SCOPE_NAME_LEN+1 );
  786. pScope->dwStatus = GetAsnInteger(
  787. &pOutput->ipMRouteScopeStatus, 0 );
  788. dwInfoSize = MIB_INFO_SIZE(MIB_IPMCAST_SCOPE);
  789. //
  790. // Passing a name of "" or a status of 0 tells the router
  791. // not to change the existing value.
  792. //
  793. dwRes = SetMibInfo(actionId, pInfo, dwInfoSize);
  794. break;
  795. }
  796. case MIB_ACTION_CLEANUP:
  797. dwRes = MIB_S_SUCCESS;
  798. break;
  799. default:
  800. dwRes = MIB_S_INVALID_PARAMETER;
  801. TRACE0(" set_ipMRouteScopeEntry - Wrong Action ");
  802. break;
  803. }
  804. TraceLeave("set_ipMRouteScopeEntry");
  805. return dwRes;
  806. }
  807. UINT
  808. set_ipMRouteBoundaryEntry(
  809. UINT actionId,
  810. AsnAny * objectArray,
  811. UINT * errorIndex
  812. )
  813. {
  814. DWORD dwRes = MIB_S_SUCCESS;
  815. DWORD dwNumEntries = 1;
  816. PMIB_IPMCAST_BOUNDARY pEntry;
  817. sav_ipMRouteBoundaryEntry *pOutput;
  818. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  819. DWORD dwOutBufferSize = 0;
  820. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  821. // fields, so we don't have to malloc
  822. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  823. DWORD dwQuerySize;
  824. DWORD dwIfIndex;
  825. DWORD dwAddr;
  826. DWORD dwMask;
  827. TraceEnter("set_ipMRouteBoundaryEntry");
  828. pOutput = (sav_ipMRouteBoundaryEntry*)objectArray;
  829. dwIfIndex = GetAsnInteger( &( pOutput->ipMRouteBoundaryIfIndex ), 0 );
  830. dwAddr = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddress, 0 );
  831. dwMask = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddressMask, 0 );
  832. switch(actionId) {
  833. case MIB_ACTION_VALIDATE:
  834. //
  835. // Verify that the specified ifIndex, address, and mask are valid.
  836. //
  837. if ((dwAddr & dwMask) != dwAddr) {
  838. TRACE0( "set_ipMRouteBoundaryEntry: address/mask mismatch" );
  839. dwRes = MIB_S_INVALID_PARAMETER;
  840. } else if (!IN_MULTICAST(ntohl(dwAddr))) {
  841. TRACE0( "set_ipMRouteBoundaryEntry: non-multicast address" );
  842. dwRes = MIB_S_INVALID_PARAMETER;
  843. }
  844. break;
  845. case MIB_ACTION_SET: {
  846. DWORD dwInfoSize;
  847. MIB_OPAQUE_INFO pInfoBuff[2]; // big enough to hold 1 + extra index
  848. // fields, so we don't have to malloc
  849. MIB_OPAQUE_INFO *pInfo = &pInfoBuff[0];
  850. PMIB_IPMCAST_BOUNDARY pBound = (MIB_IPMCAST_BOUNDARY *)(pInfo->rgbyData);
  851. pInfo->dwId = MCAST_BOUNDARY;
  852. pBound->dwIfIndex = dwIfIndex;
  853. pBound->dwGroupAddress = dwAddr;
  854. pBound->dwGroupMask = dwMask;
  855. pBound->dwStatus = GetAsnInteger(
  856. &pOutput->ipMRouteBoundaryStatus, 0 );
  857. dwInfoSize = sizeof(MIB_OPAQUE_INFO) + 3*sizeof(DWORD);
  858. dwRes = SetMibInfo(actionId, pInfo, dwInfoSize);
  859. break;
  860. }
  861. case MIB_ACTION_CLEANUP:
  862. dwRes = MIB_S_SUCCESS;
  863. break;
  864. default:
  865. dwRes = MIB_S_INVALID_PARAMETER;
  866. TRACE0(" set_ipMRouteBoundaryEntry - Wrong Action ");
  867. break;
  868. }
  869. TraceLeave("set_ipMRouteBoundaryEntry");
  870. return dwRes;
  871. }
  872. UINT
  873. get_ipMRouteScopeEntry(
  874. UINT actionId,
  875. AsnAny * objectArray,
  876. UINT * errorIndex
  877. )
  878. {
  879. DWORD dwErr = ERROR_NOT_FOUND;
  880. DWORD dwNumEntries = 1;
  881. PMIB_IPMCAST_SCOPE pEntry;
  882. buf_ipMRouteScopeEntry *pOutput;
  883. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  884. DWORD dwOutBufferSize = 0;
  885. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  886. // fields, so we don't have to malloc
  887. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  888. DWORD dwQuerySize;
  889. BYTE pScopeName[MAX_SCOPE_NAME_LEN+1];
  890. TraceEnter("get_ipMRouteScopeEntry");
  891. pOutput = (buf_ipMRouteScopeEntry*)objectArray;
  892. pQuery->dwVarId = MCAST_SCOPE;
  893. pQuery->rgdwVarIndex[0] = GetAsnIPAddress( &pOutput->ipMRouteScopeAddress, 0 );
  894. pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &pOutput->ipMRouteScopeAddressMask, 0 );
  895. dwQuerySize = sizeof(MIB_OPAQUE_QUERY) + sizeof(DWORD);
  896. dwErr = GetMibInfo(actionId, pQuery, dwQuerySize,
  897. &pRpcInfo, &dwOutBufferSize);
  898. if (dwErr != NO_ERROR) {
  899. TraceError(dwErr);
  900. TraceLeave("get_ipMRouteScopeEntry");
  901. if (dwErr == ERROR_NOT_FOUND)
  902. return MIB_S_ENTRY_NOT_FOUND;
  903. return dwErr;
  904. }
  905. pEntry = (PMIB_IPMCAST_SCOPE) pRpcInfo->rgbyData;
  906. // Set index values
  907. ForceSetAsnIPAddress(&(pOutput->ipMRouteScopeAddress),
  908. &(pOutput->dwIpMRouteScopeAddressInfo),
  909. pEntry->dwGroupAddress);
  910. ForceSetAsnIPAddress(&(pOutput->ipMRouteScopeAddressMask),
  911. &(pOutput->dwIpMRouteScopeAddressMaskInfo),
  912. pEntry->dwGroupMask);
  913. // Set other values.
  914. WideCharToMultiByte( CP_UTF8,
  915. 0,
  916. pEntry->snNameBuffer,
  917. wcslen(pEntry->snNameBuffer)+1,
  918. pScopeName,
  919. MAX_SCOPE_NAME_LEN+1,
  920. NULL,
  921. NULL );
  922. SetAsnOctetString(&( pOutput->ipMRouteScopeName),
  923. pOutput->rgbyScopeNameInfo,
  924. pScopeName,
  925. min(strlen(pScopeName),MAX_SCOPE_NAME_LEN));
  926. SetAsnInteger(&(pOutput->ipMRouteScopeStatus), ROWSTATUS_ACTIVE);
  927. if (pRpcInfo)
  928. MprAdminMIBBufferFree(pRpcInfo);
  929. TraceLeave("get_ipMRouteScopeEntry");
  930. return MIB_S_SUCCESS;
  931. }
  932. UINT
  933. get_ipMRouteBoundaryEntry(
  934. UINT actionId,
  935. AsnAny * objectArray,
  936. UINT * errorIndex
  937. )
  938. {
  939. DWORD dwErr = ERROR_NOT_FOUND;
  940. DWORD dwNumEntries = 1;
  941. PMIB_IPMCAST_BOUNDARY pEntry;
  942. buf_ipMRouteBoundaryEntry *pOutput;
  943. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  944. DWORD dwOutBufferSize = 0;
  945. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  946. // fields, so we don't have to malloc
  947. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  948. DWORD dwQuerySize;
  949. TraceEnter("get_ipMRouteBoundaryEntry");
  950. pOutput = (buf_ipMRouteBoundaryEntry*)objectArray;
  951. pQuery->dwVarId = MCAST_BOUNDARY;
  952. pQuery->rgdwVarIndex[0] = GetAsnInteger( &( pOutput->ipMRouteBoundaryIfIndex ), 0 );
  953. pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddress, 0 );
  954. pQuery->rgdwVarIndex[2] = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddressMask, 0 );
  955. dwQuerySize = sizeof(MIB_OPAQUE_QUERY) + 2*sizeof(DWORD);
  956. dwErr = GetMibInfo(actionId, pQuery, dwQuerySize,
  957. &pRpcInfo, &dwOutBufferSize);
  958. if (dwErr != NO_ERROR) {
  959. TraceError(dwErr);
  960. TraceLeave("get_ipMRouteBoundaryEntry");
  961. if (dwErr == ERROR_NOT_FOUND)
  962. return MIB_S_ENTRY_NOT_FOUND;
  963. return dwErr;
  964. }
  965. pEntry = (PMIB_IPMCAST_BOUNDARY) pRpcInfo->rgbyData;
  966. // Set index values
  967. ForceSetAsnInteger(&(pOutput->ipMRouteBoundaryIfIndex), pEntry->dwIfIndex);
  968. ForceSetAsnIPAddress(&(pOutput->ipMRouteBoundaryAddress),
  969. &(pOutput->dwIpMRouteBoundaryAddressInfo),
  970. pEntry->dwGroupAddress);
  971. ForceSetAsnIPAddress(&(pOutput->ipMRouteBoundaryAddressMask),
  972. &(pOutput->dwIpMRouteBoundaryAddressMaskInfo),
  973. pEntry->dwGroupMask);
  974. // Set other values
  975. SetAsnInteger(&(pOutput->ipMRouteBoundaryStatus), ROWSTATUS_ACTIVE);
  976. if (pRpcInfo)
  977. MprAdminMIBBufferFree(pRpcInfo);
  978. TraceLeave("get_ipMRouteBoundaryEntry");
  979. return MIB_S_SUCCESS;
  980. }
  981. DWORD
  982. ConnectToRouter()
  983. {
  984. DWORD dwRes = (DWORD) -1;
  985. TraceEnter("ConnectToRouter");
  986. EnterCriticalSection( &g_CS );
  987. do
  988. {
  989. MPR_SERVER_HANDLE hTmp;
  990. if ( g_hMIBServer )
  991. {
  992. dwRes = NO_ERROR;
  993. break;
  994. }
  995. dwRes = MprAdminMIBServerConnect( NULL, &hTmp );
  996. if ( dwRes == NO_ERROR )
  997. {
  998. InterlockedExchangePointer(&g_hMIBServer, hTmp );
  999. }
  1000. else
  1001. {
  1002. TRACE1(
  1003. "Error %d setting up DIM connection to MIB Server\n",
  1004. dwRes
  1005. );
  1006. }
  1007. } while ( FALSE );
  1008. LeaveCriticalSection( &g_CS );
  1009. TraceLeave("ConnectToRouter");
  1010. return dwRes;
  1011. }