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.

1230 lines
37 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. MprAdminMIBBufferFree( pRpcInfo );
  448. } while (actionId != MIB_ACTION_GET); // once for GET, "forever" for others
  449. *ppEntry = pEntry;
  450. *ppOif = pOif;
  451. *ppRpcInfo = pRpcInfo;
  452. return dwResult;
  453. }
  454. UINT
  455. get_ipMRouteNextHopEntry(
  456. UINT actionId,
  457. AsnAny * objectArray,
  458. UINT * errorIndex
  459. )
  460. {
  461. DWORD dwResult = ERROR_NOT_FOUND;
  462. DWORD dwNumEntries = 1;
  463. IPMCAST_MFE mfe;
  464. IPMCAST_MFE_STATS mfeStats;
  465. #ifdef SAMPLE_MFE
  466. MIB_IPMCAST_MFE_STATS sampledata;
  467. #endif
  468. PMIB_IPMCAST_MFE_STATS pEntry;
  469. PMIB_IPMCAST_OIF_STATS pOif;
  470. PMIB_MFE_STATS_TABLE pTable = NULL;
  471. DWORD dwOutBufferSize = 0;
  472. buf_ipMRouteNextHopEntry *pOutput;
  473. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  474. // fields, so we don't have to malloc
  475. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  476. DWORD dwQuerySize;
  477. DWORD oifIndex, oifAddress;
  478. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  479. TraceEnter("get_ipMRouteNextHopEntry");
  480. pOutput = (buf_ipMRouteNextHopEntry*)objectArray;
  481. pQuery->dwVarId = MCAST_MFE_STATS;
  482. //
  483. // XXX Note that the 3 lines below aren't quite right, since
  484. // 0-value instances will be missed. That is (*,G) entries
  485. // will be skipped!!
  486. //
  487. // Should call for a GET-FIRST if an incomplete length is given.
  488. // Maybe the Sfx API does this already.
  489. //
  490. // XXX hold off on changing this until Florin changes the SNMP
  491. // api to cover the out-of-range index case.
  492. //
  493. pQuery->rgdwVarIndex[0] = GetAsnIPAddress( &( pOutput->ipMRouteNextHopGroup ), 0 );
  494. pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &( pOutput->ipMRouteNextHopSource), 0 );
  495. pQuery->rgdwVarIndex[2] = GetAsnIPAddress( &( pOutput->ipMRouteNextHopSourceMask ), 0 );
  496. oifIndex = GetAsnInteger( &(pOutput->ipMRouteNextHopIfIndex), 0);
  497. oifAddress = GetAsnIPAddress( &(pOutput->ipMRouteNextHopAddress), 0);
  498. #ifndef SAMPLE_MFE
  499. {
  500. dwResult = LocateMfeOif(actionId, pQuery, oifIndex, oifAddress,
  501. &pEntry, &pOif, &pRpcInfo);
  502. if (dwResult != NO_ERROR) {
  503. TraceError(dwResult);
  504. return dwResult;
  505. }
  506. }
  507. #else
  508. {
  509. pEntry = &sampledata;
  510. pOif = &pEntry->rgmiosOutStats[0];
  511. if (pQuery->rgdwVarIndex[0] >= 0x01010101)
  512. return MIB_S_NO_MORE_ENTRIES;
  513. pEntry->dwGroup = 0x01010101;
  514. pEntry->dwSource = 0x02020202;
  515. pEntry->dwSrcMask = 0x03030303;
  516. pEntry->ulNumOutIf = 1;
  517. pOif->dwOutIfIndex = 11;
  518. pOif->dwNextHopAddr = 0x04040404;
  519. pOif->ulOutPackets = 22;
  520. // don't care what the other values are for this test
  521. }
  522. #endif
  523. // Save index terms
  524. ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopGroup),
  525. &(pOutput->dwIpMRouteNextHopGroupInfo),
  526. pEntry->dwGroup);
  527. ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopSource),
  528. &(pOutput->dwIpMRouteNextHopSourceInfo),
  529. pEntry->dwSource);
  530. ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopSourceMask),
  531. &(pOutput->dwIpMRouteNextHopSourceMaskInfo),
  532. pEntry->dwSrcMask);
  533. ForceSetAsnInteger (&(pOutput->ipMRouteNextHopIfIndex),
  534. pOif->dwOutIfIndex);
  535. ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopAddress),
  536. &(pOutput->dwIpMRouteNextHopAddressInfo),
  537. pOif->dwNextHopAddr);
  538. // Save other terms
  539. SetAsnInteger(&(pOutput->ipMRouteNextHopState), 2); // "forwarding"
  540. SetAsnTimeTicks(&(pOutput->ipMRouteNextHopUpTime), pEntry->ulUpTime); // XXX
  541. SetAsnTimeTicks(&(pOutput->ipMRouteNextHopExpiryTime), pEntry->ulExpiryTime); // XXX
  542. #ifdef CLOSEST_MEMBER_HOPS
  543. SetAsnInteger(&(pOutput->ipMRouteNextHopClosestMemberHops), 1);
  544. #endif
  545. SetAsnCounter(&(pOutput->ipMRouteNextHopPkts), pOif->ulOutPackets);
  546. // For protocol, we'll just report the protocol owning the interface
  547. SetAsnInteger(&(pOutput->ipMRouteNextHopProtocol),
  548. GetInterfaceProtocol(pOif->dwOutIfIndex));
  549. if ( pRpcInfo ) { MprAdminMIBBufferFree( pRpcInfo ); }
  550. TraceLeave("get_ipMRouteNextHopEntry");
  551. return MIB_S_SUCCESS;
  552. }
  553. DWORD
  554. SetMibInfo(
  555. IN UINT actionId, // SET, CLEANUP
  556. IN PMIB_OPAQUE_INFO pInfo, // value info
  557. IN DWORD dwInfoSize // size of above
  558. )
  559. {
  560. DWORD dwRes = NO_ERROR;
  561. switch ( actionId )
  562. {
  563. #ifdef THREE_PHASE
  564. case MIB_ACTION_VALIDATE :
  565. MULTICAST_MIB_VALIDATE(
  566. pInfo,
  567. dwInfoSize,
  568. dwRes
  569. );
  570. // ERROR_INVALID_PARAMETER is returned when there is
  571. // no interface for the specified index.
  572. //
  573. if ( dwRes == ERROR_INVALID_PARAMETER )
  574. {
  575. dwRes = MIB_S_INVALID_PARAMETER;
  576. }
  577. break;
  578. #endif
  579. case MIB_ACTION_SET :
  580. #if 1
  581. dwRes = ( g_hMIBServer ) ? NO_ERROR
  582. : ConnectToRouter();
  583. if ( dwRes == NO_ERROR )
  584. {
  585. dwRes = MprAdminMIBEntrySet( g_hMIBServer,
  586. PID_IP,
  587. IPRTRMGR_PID,
  588. (LPVOID) (pInfo),
  589. (dwInfoSize)
  590. );
  591. }
  592. #else
  593. MULTICAST_MIB_COMMIT(
  594. pInfo,
  595. dwInfoSize,
  596. dwRes
  597. );
  598. #endif
  599. // ERROR_INVALID_PARAMETER is returned when there is
  600. // no interface for the specified index.
  601. //
  602. if ( dwRes == ERROR_INVALID_PARAMETER
  603. || dwRes == ERROR_INVALID_INDEX )
  604. {
  605. dwRes = MIB_S_INVALID_PARAMETER;
  606. }
  607. break;
  608. #ifdef THREE_PHASE
  609. case MIB_ACTION_CLEANUP :
  610. MULTICAST_MIB_CLEANUP(
  611. pInfo,
  612. dwInfoSize,
  613. dwRes
  614. );
  615. // ERROR_INVALID_PARAMETER is returned when there is
  616. // no interface for the specified index.
  617. //
  618. if ( dwRes == ERROR_INVALID_PARAMETER )
  619. {
  620. dwRes = MIB_S_INVALID_PARAMETER;
  621. }
  622. break;
  623. #endif
  624. default :
  625. dwRes = MIB_S_INVALID_PARAMETER;
  626. break;
  627. }
  628. return dwRes;
  629. }
  630. DWORD
  631. GetMibInfo(
  632. IN UINT actionId, // GET, GET-NEXT, SET
  633. IN PMIB_OPAQUE_QUERY pQuery, // instance info
  634. IN DWORD dwQuerySize, // size of above
  635. OUT PMIB_OPAQUE_INFO *ppimgod, // value info
  636. OUT PDWORD pdwOutSize // size of above
  637. )
  638. {
  639. DWORD dwRes = (DWORD) -1;
  640. PMIB_OPAQUE_INFO pimgodOutData = NULL;
  641. *ppimgod = NULL;
  642. switch ( actionId )
  643. {
  644. case MIB_ACTION_GET :
  645. MULTICAST_MIB_GET(
  646. pQuery,
  647. dwQuerySize,
  648. &pimgodOutData,
  649. pdwOutSize,
  650. dwRes
  651. );
  652. //
  653. // ERROR_INVALID_PARAMETER is returned when there is
  654. // no interface for the specified index.
  655. // RPC_S_SERVER_UNAVAILABLE is returned when the router
  656. // isn't running.
  657. //
  658. if ( dwRes == ERROR_INVALID_PARAMETER
  659. || dwRes == RPC_S_SERVER_UNAVAILABLE
  660. || dwRes == RPC_S_UNKNOWN_IF )
  661. {
  662. dwRes = MIB_S_ENTRY_NOT_FOUND;
  663. }
  664. break;
  665. case MIB_ACTION_GETFIRST :
  666. MULTICAST_MIB_GETFIRST(
  667. pQuery,
  668. dwQuerySize,
  669. &pimgodOutData,
  670. pdwOutSize,
  671. dwRes
  672. );
  673. //
  674. // ERROR_INVALID_PARAMETER is returned when there is
  675. // no interface for the specified index.
  676. // RPC_S_SERVER_UNAVAILABLE is returned when the router
  677. // isn't running.
  678. //
  679. if ( dwRes == ERROR_INVALID_PARAMETER
  680. || dwRes == RPC_S_SERVER_UNAVAILABLE
  681. || dwRes == RPC_S_UNKNOWN_IF )
  682. {
  683. dwRes = MIB_S_NO_MORE_ENTRIES;
  684. }
  685. break;
  686. case MIB_ACTION_GETNEXT :
  687. MULTICAST_MIB_GETNEXT(
  688. pQuery,
  689. dwQuerySize,
  690. &pimgodOutData,
  691. pdwOutSize,
  692. dwRes
  693. );
  694. //
  695. // ERROR_INVALID_PARAMETER is returned when there is
  696. // no interface for the specified index.
  697. // RPC_S_SERVER_UNAVAILABLE is returned when the router
  698. // isn't running.
  699. //
  700. if ( dwRes == ERROR_INVALID_PARAMETER
  701. || dwRes == ERROR_NO_MORE_ITEMS
  702. || dwRes == RPC_S_SERVER_UNAVAILABLE
  703. || dwRes == RPC_S_UNKNOWN_IF )
  704. {
  705. dwRes = MIB_S_NO_MORE_ENTRIES;
  706. break;
  707. }
  708. //
  709. // Get Next wraps to the next table at the end of the
  710. // entries in the current table. To flag the end of a table,
  711. // check the end of the table.
  712. //
  713. if ( pQuery->dwVarId != pQuery->dwVarId )
  714. {
  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. else if ( pimgodOutData )
  727. {
  728. MprAdminMIBBufferFree( pimgodOutData );
  729. }
  730. return dwRes;
  731. }
  732. UINT
  733. set_ipMRouteScopeEntry(
  734. UINT actionId,
  735. AsnAny * objectArray,
  736. UINT * errorIndex
  737. )
  738. {
  739. DWORD dwRes = MIB_S_SUCCESS;
  740. DWORD dwNumEntries = 1;
  741. PMIB_IPMCAST_SCOPE pEntry;
  742. sav_ipMRouteScopeEntry *pOutput;
  743. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  744. DWORD dwOutBufferSize = 0;
  745. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  746. // fields, so we don't have to malloc
  747. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  748. DWORD dwQuerySize;
  749. DWORD dwIfIndex;
  750. DWORD dwAddr;
  751. DWORD dwMask;
  752. TraceEnter("set_ipMRouteScopeEntry");
  753. pOutput = (sav_ipMRouteScopeEntry*)objectArray;
  754. dwAddr = GetAsnIPAddress( &pOutput->ipMRouteScopeAddress, 0 );
  755. dwMask = GetAsnIPAddress( &pOutput->ipMRouteScopeAddressMask, 0 );
  756. switch(actionId) {
  757. case MIB_ACTION_VALIDATE:
  758. //
  759. // Verify that the specified ifIndex, address, and mask are valid.
  760. //
  761. if ((dwAddr & dwMask) != dwAddr) {
  762. TRACE0( "set_ipMRouteScopeEntry: address/mask mismatch" );
  763. dwRes = MIB_S_INVALID_PARAMETER;
  764. } else if (!IN_MULTICAST(ntohl(dwAddr))) {
  765. TRACE0( "set_ipMRouteScopeEntry: non-multicast address" );
  766. dwRes = MIB_S_INVALID_PARAMETER;
  767. }
  768. break;
  769. case MIB_ACTION_SET: {
  770. BYTE pScopeName[MAX_SCOPE_NAME_LEN+1];
  771. DWORD dwInfoSize;
  772. MIB_IPMCAST_SCOPE pScopeBuff[2]; // big enough to hold 1 + mib hdr
  773. // so we don't have to malloc
  774. MIB_OPAQUE_INFO *pInfo = (PMIB_OPAQUE_INFO)&pScopeBuff[0];
  775. PMIB_IPMCAST_SCOPE pScope = (MIB_IPMCAST_SCOPE *)(pInfo->rgbyData);
  776. pInfo->dwId = MCAST_SCOPE;
  777. pScope->dwGroupAddress = dwAddr;
  778. pScope->dwGroupMask = dwMask;
  779. //
  780. // Copy the scope name.
  781. //
  782. pScopeName[0] = '\0';
  783. GetAsnOctetString( pScopeName, &pOutput->ipMRouteScopeName );
  784. MultiByteToWideChar( CP_UTF8,
  785. 0,
  786. pScopeName,
  787. strlen(pScopeName),
  788. pScope->snNameBuffer,
  789. MAX_SCOPE_NAME_LEN+1 );
  790. pScope->dwStatus = GetAsnInteger(
  791. &pOutput->ipMRouteScopeStatus, 0 );
  792. dwInfoSize = MIB_INFO_SIZE(MIB_IPMCAST_SCOPE);
  793. //
  794. // Passing a name of "" or a status of 0 tells the router
  795. // not to change the existing value.
  796. //
  797. dwRes = SetMibInfo(actionId, pInfo, dwInfoSize);
  798. break;
  799. }
  800. case MIB_ACTION_CLEANUP:
  801. dwRes = MIB_S_SUCCESS;
  802. break;
  803. default:
  804. dwRes = MIB_S_INVALID_PARAMETER;
  805. TRACE0(" set_ipMRouteScopeEntry - Wrong Action ");
  806. break;
  807. }
  808. TraceLeave("set_ipMRouteScopeEntry");
  809. return dwRes;
  810. }
  811. UINT
  812. set_ipMRouteBoundaryEntry(
  813. UINT actionId,
  814. AsnAny * objectArray,
  815. UINT * errorIndex
  816. )
  817. {
  818. DWORD dwRes = MIB_S_SUCCESS;
  819. DWORD dwNumEntries = 1;
  820. PMIB_IPMCAST_BOUNDARY pEntry;
  821. sav_ipMRouteBoundaryEntry *pOutput;
  822. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  823. DWORD dwOutBufferSize = 0;
  824. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  825. // fields, so we don't have to malloc
  826. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  827. DWORD dwQuerySize;
  828. DWORD dwIfIndex;
  829. DWORD dwAddr;
  830. DWORD dwMask;
  831. TraceEnter("set_ipMRouteBoundaryEntry");
  832. pOutput = (sav_ipMRouteBoundaryEntry*)objectArray;
  833. dwIfIndex = GetAsnInteger( &( pOutput->ipMRouteBoundaryIfIndex ), 0 );
  834. dwAddr = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddress, 0 );
  835. dwMask = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddressMask, 0 );
  836. switch(actionId) {
  837. case MIB_ACTION_VALIDATE:
  838. //
  839. // Verify that the specified ifIndex, address, and mask are valid.
  840. //
  841. if ((dwAddr & dwMask) != dwAddr) {
  842. TRACE0( "set_ipMRouteBoundaryEntry: address/mask mismatch" );
  843. dwRes = MIB_S_INVALID_PARAMETER;
  844. } else if (!IN_MULTICAST(ntohl(dwAddr))) {
  845. TRACE0( "set_ipMRouteBoundaryEntry: non-multicast address" );
  846. dwRes = MIB_S_INVALID_PARAMETER;
  847. }
  848. break;
  849. case MIB_ACTION_SET: {
  850. DWORD dwInfoSize;
  851. MIB_OPAQUE_INFO pInfoBuff[2]; // big enough to hold 1 + extra index
  852. // fields, so we don't have to malloc
  853. MIB_OPAQUE_INFO *pInfo = &pInfoBuff[0];
  854. PMIB_IPMCAST_BOUNDARY pBound = (MIB_IPMCAST_BOUNDARY *)(pInfo->rgbyData);
  855. pInfo->dwId = MCAST_BOUNDARY;
  856. pBound->dwIfIndex = dwIfIndex;
  857. pBound->dwGroupAddress = dwAddr;
  858. pBound->dwGroupMask = dwMask;
  859. pBound->dwStatus = GetAsnInteger(
  860. &pOutput->ipMRouteBoundaryStatus, 0 );
  861. dwInfoSize = sizeof(MIB_OPAQUE_INFO) + 3*sizeof(DWORD);
  862. dwRes = SetMibInfo(actionId, pInfo, dwInfoSize);
  863. break;
  864. }
  865. case MIB_ACTION_CLEANUP:
  866. dwRes = MIB_S_SUCCESS;
  867. break;
  868. default:
  869. dwRes = MIB_S_INVALID_PARAMETER;
  870. TRACE0(" set_ipMRouteBoundaryEntry - Wrong Action ");
  871. break;
  872. }
  873. TraceLeave("set_ipMRouteBoundaryEntry");
  874. return dwRes;
  875. }
  876. UINT
  877. get_ipMRouteScopeEntry(
  878. UINT actionId,
  879. AsnAny * objectArray,
  880. UINT * errorIndex
  881. )
  882. {
  883. DWORD dwErr = ERROR_NOT_FOUND;
  884. DWORD dwNumEntries = 1;
  885. PMIB_IPMCAST_SCOPE pEntry;
  886. buf_ipMRouteScopeEntry *pOutput;
  887. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  888. DWORD dwOutBufferSize = 0;
  889. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  890. // fields, so we don't have to malloc
  891. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  892. DWORD dwQuerySize;
  893. BYTE pScopeName[MAX_SCOPE_NAME_LEN+1];
  894. TraceEnter("get_ipMRouteScopeEntry");
  895. pOutput = (buf_ipMRouteScopeEntry*)objectArray;
  896. pQuery->dwVarId = MCAST_SCOPE;
  897. pQuery->rgdwVarIndex[0] = GetAsnIPAddress( &pOutput->ipMRouteScopeAddress, 0 );
  898. pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &pOutput->ipMRouteScopeAddressMask, 0 );
  899. dwQuerySize = sizeof(MIB_OPAQUE_QUERY) + sizeof(DWORD);
  900. dwErr = GetMibInfo(actionId, pQuery, dwQuerySize,
  901. &pRpcInfo, &dwOutBufferSize);
  902. if (dwErr != NO_ERROR) {
  903. TraceError(dwErr);
  904. TraceLeave("get_ipMRouteScopeEntry");
  905. if (dwErr == ERROR_NOT_FOUND)
  906. return MIB_S_ENTRY_NOT_FOUND;
  907. return dwErr;
  908. }
  909. pEntry = (PMIB_IPMCAST_SCOPE) pRpcInfo->rgbyData;
  910. // Set index values
  911. ForceSetAsnIPAddress(&(pOutput->ipMRouteScopeAddress),
  912. &(pOutput->dwIpMRouteScopeAddressInfo),
  913. pEntry->dwGroupAddress);
  914. ForceSetAsnIPAddress(&(pOutput->ipMRouteScopeAddressMask),
  915. &(pOutput->dwIpMRouteScopeAddressMaskInfo),
  916. pEntry->dwGroupMask);
  917. // Set other values.
  918. WideCharToMultiByte( CP_UTF8,
  919. 0,
  920. pEntry->snNameBuffer,
  921. wcslen(pEntry->snNameBuffer)+1,
  922. pScopeName,
  923. MAX_SCOPE_NAME_LEN+1,
  924. NULL,
  925. NULL );
  926. SetAsnOctetString(&( pOutput->ipMRouteScopeName),
  927. pOutput->rgbyScopeNameInfo,
  928. pScopeName,
  929. min(strlen(pScopeName),MAX_SCOPE_NAME_LEN));
  930. SetAsnInteger(&(pOutput->ipMRouteScopeStatus), ROWSTATUS_ACTIVE);
  931. if (pRpcInfo)
  932. MprAdminMIBBufferFree(pRpcInfo);
  933. TraceLeave("get_ipMRouteScopeEntry");
  934. return MIB_S_SUCCESS;
  935. }
  936. UINT
  937. get_ipMRouteBoundaryEntry(
  938. UINT actionId,
  939. AsnAny * objectArray,
  940. UINT * errorIndex
  941. )
  942. {
  943. DWORD dwErr = ERROR_NOT_FOUND;
  944. DWORD dwNumEntries = 1;
  945. PMIB_IPMCAST_BOUNDARY pEntry;
  946. buf_ipMRouteBoundaryEntry *pOutput;
  947. PMIB_OPAQUE_INFO pRpcInfo = NULL;
  948. DWORD dwOutBufferSize = 0;
  949. MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index
  950. // fields, so we don't have to malloc
  951. MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0];
  952. DWORD dwQuerySize;
  953. TraceEnter("get_ipMRouteBoundaryEntry");
  954. pOutput = (buf_ipMRouteBoundaryEntry*)objectArray;
  955. pQuery->dwVarId = MCAST_BOUNDARY;
  956. pQuery->rgdwVarIndex[0] = GetAsnInteger( &( pOutput->ipMRouteBoundaryIfIndex ), 0 );
  957. pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddress, 0 );
  958. pQuery->rgdwVarIndex[2] = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddressMask, 0 );
  959. dwQuerySize = sizeof(MIB_OPAQUE_QUERY) + 2*sizeof(DWORD);
  960. dwErr = GetMibInfo(actionId, pQuery, dwQuerySize,
  961. &pRpcInfo, &dwOutBufferSize);
  962. if (dwErr != NO_ERROR) {
  963. TraceError(dwErr);
  964. TraceLeave("get_ipMRouteBoundaryEntry");
  965. if (dwErr == ERROR_NOT_FOUND)
  966. return MIB_S_ENTRY_NOT_FOUND;
  967. return dwErr;
  968. }
  969. pEntry = (PMIB_IPMCAST_BOUNDARY) pRpcInfo->rgbyData;
  970. // Set index values
  971. ForceSetAsnInteger(&(pOutput->ipMRouteBoundaryIfIndex), pEntry->dwIfIndex);
  972. ForceSetAsnIPAddress(&(pOutput->ipMRouteBoundaryAddress),
  973. &(pOutput->dwIpMRouteBoundaryAddressInfo),
  974. pEntry->dwGroupAddress);
  975. ForceSetAsnIPAddress(&(pOutput->ipMRouteBoundaryAddressMask),
  976. &(pOutput->dwIpMRouteBoundaryAddressMaskInfo),
  977. pEntry->dwGroupMask);
  978. // Set other values
  979. SetAsnInteger(&(pOutput->ipMRouteBoundaryStatus), ROWSTATUS_ACTIVE);
  980. if (pRpcInfo)
  981. MprAdminMIBBufferFree(pRpcInfo);
  982. TraceLeave("get_ipMRouteBoundaryEntry");
  983. return MIB_S_SUCCESS;
  984. }
  985. DWORD
  986. ConnectToRouter()
  987. {
  988. DWORD dwRes = (DWORD) -1;
  989. TraceEnter("ConnectToRouter");
  990. EnterCriticalSection( &g_CS );
  991. do
  992. {
  993. MPR_SERVER_HANDLE hTmp;
  994. if ( g_hMIBServer )
  995. {
  996. dwRes = NO_ERROR;
  997. break;
  998. }
  999. dwRes = MprAdminMIBServerConnect( NULL, &hTmp );
  1000. if ( dwRes == NO_ERROR )
  1001. {
  1002. InterlockedExchangePointer(&g_hMIBServer, hTmp );
  1003. }
  1004. else
  1005. {
  1006. TRACE1(
  1007. "Error %d setting up DIM connection to MIB Server\n",
  1008. dwRes
  1009. );
  1010. }
  1011. } while ( FALSE );
  1012. LeaveCriticalSection( &g_CS );
  1013. TraceLeave("ConnectToRouter");
  1014. return dwRes;
  1015. }