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.

2178 lines
60 KiB

  1. /*++
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name:
  4. apitest.c
  5. Abstract:
  6. Contains routines for testing the RTMv2 API.
  7. Author:
  8. Chaitanya Kodeboyina (chaitk) 26-Jun-1998
  9. Revision History:
  10. --*/
  11. #include "apitest.h"
  12. MY_ENTITY_EXPORT_METHODS
  13. Rip2Methods =
  14. {
  15. 5,
  16. {
  17. EntityExportMethod,
  18. EntityExportMethod,
  19. NULL,
  20. EntityExportMethod,
  21. EntityExportMethod
  22. }
  23. };
  24. MY_ENTITY_EXPORT_METHODS
  25. OspfMethods =
  26. {
  27. 6,
  28. {
  29. EntityExportMethod,
  30. EntityExportMethod,
  31. EntityExportMethod,
  32. EntityExportMethod,
  33. EntityExportMethod,
  34. EntityExportMethod
  35. }
  36. };
  37. MY_ENTITY_EXPORT_METHODS
  38. Bgp4Methods =
  39. {
  40. 4,
  41. {
  42. EntityExportMethod,
  43. EntityExportMethod,
  44. EntityExportMethod,
  45. EntityExportMethod
  46. }
  47. };
  48. ENTITY_CHARS
  49. GlobalEntityChars [] =
  50. {
  51. //
  52. // {
  53. // Rtmv2Registration,
  54. // { RtmInstanceId, AddressFamily, { EntityProtocolId, EntityInstanceId } },
  55. // EntityEventCallback, ExportMethods,
  56. // RoutesFileName,
  57. // }
  58. //
  59. /*
  60. {
  61. FALSE,
  62. { 0, RTM_PROTOCOL_FAMILY_IP, { PROTO_IP_RIP, 1 } },
  63. EntityEventCallback, &Rip2Methods,
  64. "test.out"
  65. },
  66. */
  67. {
  68. TRUE,
  69. { 1, AF_INET, { PROTO_IP_RIP, 1 } },
  70. EntityEventCallback, &Rip2Methods,
  71. "test.out"
  72. },
  73. {
  74. TRUE,
  75. { 1, AF_INET, { PROTO_IP_OSPF, 1 } },
  76. EntityEventCallback, &OspfMethods,
  77. "test.out"
  78. },
  79. {
  80. TRUE,
  81. { 1, AF_INET, { PROTO_IP_BGP, 1 } },
  82. EntityEventCallback, &Bgp4Methods,
  83. "test.out"
  84. },
  85. {
  86. TRUE,
  87. { 0, 0, { 0, 0 } },
  88. NULL, NULL,
  89. ""
  90. }
  91. };
  92. const RTM_VIEW_SET VIEW_MASK_ARR[]
  93. = {
  94. 0,
  95. RTM_VIEW_MASK_UCAST,
  96. RTM_VIEW_MASK_MCAST,
  97. RTM_VIEW_MASK_UCAST | RTM_VIEW_MASK_MCAST
  98. };
  99. // Disable warnings for unreferenced params and local variables
  100. #pragma warning(disable: 4100)
  101. #pragma warning(disable: 4101)
  102. //
  103. // Main
  104. //
  105. #if !LOOKUP_TESTING
  106. int
  107. __cdecl
  108. main (void)
  109. {
  110. PENTITY_CHARS Entity;
  111. DWORD Status;
  112. LPTHREAD_START_ROUTINE EntityThreadProc;
  113. #if MT
  114. UINT NumThreads;
  115. HANDLE Threads[64];
  116. #endif
  117. Entity = &GlobalEntityChars[0];
  118. #if MT
  119. NumThreads = 0;
  120. #endif
  121. while (Entity->EntityInformation.EntityId.EntityId != 0)
  122. {
  123. if (Entity->Rtmv2Registration)
  124. {
  125. EntityThreadProc = Rtmv2EntityThreadProc;
  126. }
  127. else
  128. {
  129. EntityThreadProc = Rtmv1EntityThreadProc;
  130. }
  131. #if MT
  132. Threads[NumThreads] = CreateThread(NULL,
  133. 0,
  134. EntityThreadProc,
  135. Entity++,
  136. 0,
  137. NULL);
  138. Print("Thread ID %d: %p\n", NumThreads, Threads[NumThreads]);
  139. NumThreads++;
  140. #else
  141. Status = EntityThreadProc(Entity++);
  142. #endif
  143. }
  144. #if MT
  145. WaitForMultipleObjects(NumThreads, Threads, TRUE, INFINITE);
  146. #endif
  147. return 0;
  148. }
  149. #endif
  150. //
  151. // A general state machine for a protocol thread (RTMv1)
  152. //
  153. DWORD Rtmv1EntityThreadProc (LPVOID ThreadParameters)
  154. {
  155. RTM_PROTOCOL_FAMILY_CONFIG FamilyConfig;
  156. PENTITY_CHARS EntityChars;
  157. PRTM_ENTITY_INFO EntityInfo;
  158. HANDLE Event;
  159. HANDLE V1RegnHandle;
  160. DWORD ProtocolId;
  161. UINT i;
  162. FILE *FilePtr;
  163. IP_NETWORK Network;
  164. UINT NumDests;
  165. UINT NumRoutes;
  166. Route ThisRoute;
  167. Route Routes[MAXROUTES];
  168. RTM_IP_ROUTE V1Route;
  169. RTM_IP_ROUTE V1Route2;
  170. HANDLE V1EnumHandle;
  171. BOOL Exists;
  172. DWORD Flags;
  173. DWORD Status;
  174. //
  175. // Get all characteristics of this entity
  176. //
  177. EntityChars = (PENTITY_CHARS) ThreadParameters;
  178. EntityInfo = &EntityChars->EntityInformation;
  179. Assert(EntityInfo->AddressFamily == RTM_PROTOCOL_FAMILY_IP);
  180. Print("\n--------------------------------------------------------\n");
  181. #if WRAPPER
  182. FamilyConfig.RPFC_Validate = ValidateRouteCallback;
  183. FamilyConfig.RPFC_Change = RouteChangeCallback;
  184. Status = RtmCreateRouteTable(EntityInfo->AddressFamily, &FamilyConfig);
  185. if (Status != ERROR_ALREADY_EXISTS)
  186. {
  187. Check(Status, 50);
  188. }
  189. else
  190. {
  191. Print("Protocol Family's Route Table already created\n");
  192. }
  193. Event = CreateEvent(NULL, TRUE, FALSE, NULL);
  194. Assert(Event != NULL);
  195. ProtocolId = EntityInfo->EntityId.EntityProtocolId,
  196. V1RegnHandle = RtmRegisterClient(EntityInfo->AddressFamily,
  197. ProtocolId,
  198. NULL,
  199. NULL); // RTM_PROTOCOL_SINGLE_ROUTE);
  200. if (V1RegnHandle == NULL)
  201. {
  202. Status = GetLastError();
  203. Check(Status, 52);
  204. }
  205. if ((FilePtr = fopen(EntityChars->RoutesFileName, "r")) == NULL)
  206. {
  207. Fatal("Failed open route database with status = %p\n",
  208. ERROR_OPENING_DATABASE);
  209. }
  210. NumRoutes = ReadRoutesFromFile(FilePtr, MAX_ROUTES, Routes);
  211. fclose(FilePtr);
  212. //
  213. // How many destinations do we have in table ?
  214. //
  215. NumDests = RtmGetNetworkCount(EntityInfo->AddressFamily);
  216. if (NumDests == 0)
  217. {
  218. Check(Status, 63);
  219. }
  220. Print("Number of destinations = %lu\n\n", NumDests);
  221. //
  222. // Add a bunch of routes from the input file
  223. //
  224. for (i = 0; i < NumRoutes; i++)
  225. {
  226. // Print("Add Route: Addr = %08x, Mask = %08x\n",
  227. // Routes[i].addr,
  228. // Routes[i].mask);
  229. ConvertRouteToV1Route(&Routes[i], &V1Route);
  230. V1Route.RR_ProtocolSpecificData.PSD_Data[0] =
  231. V1Route.RR_ProtocolSpecificData.PSD_Data[1] =
  232. V1Route.RR_ProtocolSpecificData.PSD_Data[2] =
  233. V1Route.RR_ProtocolSpecificData.PSD_Data[3] = i;
  234. V1Route.RR_FamilySpecificData.FSD_Priority = ProtocolId;
  235. V1Route.RR_FamilySpecificData.FSD_Flags = (ULONG) ~0;
  236. Status = RtmAddRoute(V1RegnHandle,
  237. &V1Route,
  238. INFINITE,
  239. &Flags,
  240. NULL,
  241. NULL);
  242. Check(Status, 54);
  243. }
  244. //
  245. // Check if routes exist to the destination
  246. //
  247. for (i = 0; i < NumRoutes; i++)
  248. {
  249. Network.N_NetNumber = Routes[i].addr;
  250. Network.N_NetMask = Routes[i].mask;
  251. Exists = RtmIsRoute(EntityInfo->AddressFamily,
  252. &Network,
  253. &V1Route);
  254. if (!Exists)
  255. {
  256. Check(Status, 64);
  257. continue;
  258. }
  259. // ConvertV1RouteToRoute(&V1Route, &ThisRoute);
  260. // PrintRoute(&ThisRoute);
  261. Exists = RtmLookupIPDestination(Routes[i].addr,
  262. &V1Route2);
  263. if (Exists)
  264. {
  265. if (!RtlEqualMemory(&V1Route, &V1Route2, sizeof(RTM_IP_ROUTE)))
  266. {
  267. Print("Routes different: \n");
  268. ConvertV1RouteToRoute(&V1Route, &ThisRoute);
  269. // PrintRoute(&ThisRoute);
  270. ConvertV1RouteToRoute(&V1Route2, &ThisRoute);
  271. // PrintRoute(&ThisRoute);
  272. Print("\n");
  273. }
  274. }
  275. else
  276. {
  277. Status = GetLastError();
  278. PrintIPAddr(&Routes[i].addr); Print("\n");
  279. Check(Status, 65);
  280. }
  281. }
  282. //
  283. // How many destinations do we have in table ?
  284. //
  285. NumDests = RtmGetNetworkCount(EntityInfo->AddressFamily);
  286. if (NumDests == 0)
  287. {
  288. Check(Status, 63);
  289. }
  290. Print("Number of destinations = %lu\n\n", NumDests);
  291. // Try using RtmGetFirstRoute and RtmGetNextRoute
  292. NumRoutes = 0;
  293. Status = RtmGetFirstRoute(EntityInfo->AddressFamily,
  294. NULL,
  295. &V1Route);
  296. // Check(Status, 59);
  297. while (SUCCESS(Status))
  298. {
  299. NumRoutes++;
  300. // Print the V1 Route that is next in the enum
  301. // ConvertV1RouteToRoute(&V1Route, &ThisRoute);
  302. // PrintRoute(&ThisRoute);
  303. Status = RtmGetNextRoute(EntityInfo->AddressFamily,
  304. NULL,
  305. &V1Route);
  306. // Check(Status, 60);
  307. }
  308. // Print("Num of routes in table : %lu\n", NumRoutes);
  309. //
  310. // Disable and reenable all routes that match criteria
  311. //
  312. V1Route.RR_InterfaceID = 3;
  313. Status = RtmBlockSetRouteEnable(V1RegnHandle,
  314. RTM_ONLY_THIS_INTERFACE,
  315. &V1Route,
  316. FALSE);
  317. Check(Status, 66);
  318. /*
  319. V1Route.RR_InterfaceID = 3;
  320. Status = RtmBlockSetRouteEnable(V1RegnHandle,
  321. RTM_ONLY_THIS_INTERFACE,
  322. &V1Route,
  323. TRUE);
  324. Check(Status, 66);
  325. //
  326. // Convert all routes that match criteria to static
  327. //
  328. V1Route.RR_InterfaceID = 3;
  329. Status = RtmBlockConvertRoutesToStatic(V1RegnHandle,
  330. RTM_ONLY_THIS_INTERFACE,
  331. &V1Route);
  332. Check(Status, 62);
  333. */
  334. //
  335. // Delete all routes that match the criteria
  336. //
  337. ZeroMemory(&V1Route, sizeof(RTM_IP_ROUTE));
  338. V1Route.RR_InterfaceID = 2;
  339. Status= RtmBlockDeleteRoutes(V1RegnHandle,
  340. RTM_ONLY_THIS_INTERFACE|RTM_ONLY_THIS_NETWORK,
  341. &V1Route);
  342. Check(Status, 61);
  343. //
  344. // Enum and del this regn's routes in the table
  345. //
  346. V1Route.RR_RoutingProtocol = ProtocolId;
  347. V1EnumHandle = RtmCreateEnumerationHandle(EntityInfo->AddressFamily,
  348. RTM_ONLY_THIS_PROTOCOL,
  349. &V1Route);
  350. if (V1EnumHandle == NULL)
  351. {
  352. Status = GetLastError();
  353. Check(Status, 56);
  354. }
  355. NumRoutes = 0;
  356. do
  357. {
  358. Status = RtmEnumerateGetNextRoute(V1EnumHandle,
  359. &V1Route);
  360. // Check(Status, 58);
  361. if (!SUCCESS(Status))
  362. {
  363. break;
  364. }
  365. NumRoutes++;
  366. // Print the V1 Route that is next in the enum
  367. // ConvertV1RouteToRoute(&V1Route, &ThisRoute);
  368. // PrintRoute(&ThisRoute);
  369. // Delete this route from the table forever
  370. Status = RtmDeleteRoute(V1RegnHandle,
  371. &V1Route,
  372. &Flags,
  373. NULL);
  374. Check(Status, 55);
  375. }
  376. while (TRUE);
  377. Print("Num of routes in table : %lu\n", NumRoutes);
  378. Status = RtmCloseEnumerationHandle(V1EnumHandle);
  379. Check(Status, 57);
  380. //
  381. // Enumerate all routes in table once again
  382. //
  383. V1EnumHandle = RtmCreateEnumerationHandle(EntityInfo->AddressFamily,
  384. RTM_INCLUDE_DISABLED_ROUTES,
  385. NULL);
  386. if (V1EnumHandle == NULL)
  387. {
  388. Status = GetLastError();
  389. Check(Status, 56);
  390. }
  391. NumRoutes = 0;
  392. do
  393. {
  394. Status = RtmEnumerateGetNextRoute(V1EnumHandle,
  395. &V1Route);
  396. // Check(Status, 58);
  397. if (!SUCCESS(Status))
  398. {
  399. break;
  400. }
  401. NumRoutes++;
  402. // Print the V1 Route that is next in the enum
  403. ConvertV1RouteToRoute(&V1Route, &ThisRoute);
  404. // PrintRoute(&ThisRoute);
  405. UNREFERENCED_PARAMETER(Flags);
  406. Status = RtmDeleteRoute(V1RegnHandle,
  407. &V1Route,
  408. &Flags,
  409. NULL);
  410. Check(Status, 55);
  411. }
  412. while (TRUE);
  413. Print("Num of routes in table : %lu\n", NumRoutes);
  414. Status = RtmCloseEnumerationHandle(V1EnumHandle);
  415. Check(Status, 57);
  416. //
  417. // Deregister the entity and clean up now
  418. //
  419. Status = RtmDeregisterClient(V1RegnHandle);
  420. Check(Status, 53);
  421. if (Event)
  422. {
  423. CloseHandle(Event);
  424. }
  425. Status = RtmDeleteRouteTable(EntityInfo->AddressFamily);
  426. Check(Status, 51);
  427. #endif
  428. Print("\n--------------------------------------------------------\n");
  429. return 0;
  430. }
  431. VOID
  432. ConvertRouteToV1Route(Route *ThisRoute, RTM_IP_ROUTE *V1Route)
  433. {
  434. ZeroMemory(V1Route, sizeof(RTM_IP_ROUTE));
  435. V1Route->RR_Network.N_NetNumber = ThisRoute->addr;
  436. V1Route->RR_Network.N_NetMask = ThisRoute->mask;
  437. V1Route->RR_InterfaceID = PtrToUlong(ThisRoute->interface);
  438. V1Route->RR_NextHopAddress.N_NetNumber = ThisRoute->nexthop;
  439. V1Route->RR_NextHopAddress.N_NetMask = 0xFFFFFFFF;
  440. V1Route->RR_FamilySpecificData.FSD_Metric = ThisRoute->metric;
  441. return;
  442. }
  443. VOID
  444. ConvertV1RouteToRoute(RTM_IP_ROUTE *V1Route, Route *ThisRoute)
  445. {
  446. DWORD Mask;
  447. ZeroMemory(ThisRoute, sizeof(Route));
  448. ThisRoute->addr = V1Route->RR_Network.N_NetNumber;
  449. ThisRoute->mask = V1Route->RR_Network.N_NetMask;
  450. ThisRoute->len = 0;
  451. // No checking for contiguous masks
  452. Mask = ThisRoute->mask;
  453. while (Mask)
  454. {
  455. if (Mask & 1)
  456. {
  457. ThisRoute->len++;
  458. }
  459. Mask >>= 1;
  460. }
  461. ThisRoute->interface = ULongToPtr(V1Route->RR_InterfaceID);
  462. ThisRoute->nexthop = V1Route->RR_NextHopAddress.N_NetNumber;
  463. Assert(V1Route->RR_NextHopAddress.N_NetMask == 0xFFFFFFFF);
  464. ThisRoute->metric = V1Route->RR_FamilySpecificData.FSD_Metric;
  465. Print("Owner = %08x, ", V1Route->RR_RoutingProtocol);
  466. PrintRoute(ThisRoute);
  467. return;
  468. }
  469. DWORD
  470. ValidateRouteCallback(
  471. IN PVOID Route
  472. )
  473. {
  474. UNREFERENCED_PARAMETER(Route);
  475. return NO_ERROR;
  476. }
  477. VOID
  478. RouteChangeCallback(
  479. IN DWORD Flags,
  480. IN PVOID CurrBestRoute,
  481. IN PVOID PrevBestRoute
  482. )
  483. {
  484. Route ThisRoute;
  485. Print("Route Change Notification:\n");
  486. Print("Flags = %08x\n", Flags);
  487. Print("Prev Route = ");
  488. if (Flags & RTM_PREVIOUS_BEST_ROUTE)
  489. {
  490. ConvertV1RouteToRoute((RTM_IP_ROUTE *) PrevBestRoute, &ThisRoute);
  491. // PrintRoute(ThisRoute);
  492. }
  493. else
  494. {
  495. Print("NULL Route\n");
  496. }
  497. // Print("Curr Route = ");
  498. if (Flags & RTM_CURRENT_BEST_ROUTE)
  499. {
  500. ConvertV1RouteToRoute((RTM_IP_ROUTE *) CurrBestRoute, &ThisRoute);
  501. // PrintRoute(ThisRoute);
  502. }
  503. else
  504. {
  505. Print("NULL Route\n");
  506. }
  507. return;
  508. }
  509. //
  510. // A general state machine for a protocol thread (RTMv2)
  511. //
  512. DWORD Rtmv2EntityThreadProc (LPVOID ThreadParameters)
  513. {
  514. PENTITY_CHARS EntityChars;
  515. PRTM_ENTITY_INFO EntityInfo;
  516. RTM_INSTANCE_CONFIG InstanceConfig;
  517. RTM_ADDRESS_FAMILY_CONFIG AddrFamConfig;
  518. RTM_ADDRESS_FAMILY_INFO AddrFamilyInfo;
  519. RTM_ENTITY_HANDLE RtmRegHandle;
  520. RTM_VIEW_SET ViewSet;
  521. UINT NumViews;
  522. UINT NumInstances;
  523. RTM_INSTANCE_INFO Instances[MAX_INSTANCES];
  524. RTM_ADDRESS_FAMILY_INFO AddrFams[MAX_ADDR_FAMS];
  525. UINT NumEntities;
  526. RTM_ENTITY_HANDLE EntityHandles[MAX_ENTITIES];
  527. RTM_ENTITY_INFO EntityInfos[MAX_ENTITIES];
  528. UINT NumMethods;
  529. RTM_ENTITY_EXPORT_METHOD ExportMethods[MAX_METHODS];
  530. RTM_ENTITY_METHOD_INPUT Input;
  531. UINT OutputHdrSize;
  532. UINT OutputSize;
  533. RTM_ENTITY_METHOD_OUTPUT Output[MAX_METHODS];
  534. UINT i, j, k, l, m;
  535. UCHAR *p;
  536. FILE *FilePtr;
  537. UINT NumRoutes;
  538. Route Routes[MAXROUTES];
  539. RTM_NEXTHOP_INFO NextHopInfo;
  540. RTM_NEXTHOP_HANDLE NextHopHandle;
  541. PRTM_NEXTHOP_INFO NextHopPointer;
  542. DWORD ChangeFlags;
  543. RTM_ENUM_HANDLE EnumHandle;
  544. RTM_ENUM_HANDLE EnumHandle1;
  545. RTM_ENUM_HANDLE EnumHandle2;
  546. UINT TotalHandles;
  547. UINT NumHandles;
  548. HANDLE Handles[MAX_HANDLES];
  549. RTM_NET_ADDRESS NetAddress;
  550. UINT DestInfoSize;
  551. PRTM_DEST_INFO DestInfo1;
  552. PRTM_DEST_INFO DestInfo2;
  553. UINT NumInfos;
  554. PRTM_DEST_INFO DestInfos;
  555. RTM_ROUTE_INFO RouteInfo;
  556. RTM_ROUTE_HANDLE RouteHandle;
  557. PRTM_ROUTE_INFO RoutePointer;
  558. RTM_PREF_INFO PrefInfo;
  559. RTM_ROUTE_LIST_HANDLE RouteListHandle1;
  560. RTM_ROUTE_LIST_HANDLE RouteListHandle2;
  561. RTM_NOTIFY_HANDLE NotifyHandle;
  562. BOOL Marked;
  563. DWORD Status;
  564. DWORD Status1;
  565. DWORD Status2;
  566. //
  567. // Test the mask to len conversion macros in rtmv2.h
  568. //
  569. for (i = 0; i < 33; i++)
  570. {
  571. j = RTM_IPV4_MASK_FROM_LEN(i);
  572. p = (PUCHAR) &j;
  573. RTM_IPV4_LEN_FROM_MASK(k, j);
  574. Assert(i == k);
  575. printf("Len %2d: %08x: %02x.%02x.%02x.%02x: %2d\n",
  576. i, j, p[0], p[1], p[2], p[3], k);
  577. }
  578. //
  579. // Get all characteristics of this entity
  580. //
  581. EntityChars = (PENTITY_CHARS) ThreadParameters;
  582. EntityInfo = &EntityChars->EntityInformation;
  583. Print("\n--------------------------------------------------------\n");
  584. //
  585. // -00- Is this addr family config in registry
  586. //
  587. Status = RtmReadAddressFamilyConfig(EntityInfo->RtmInstanceId,
  588. EntityInfo->AddressFamily,
  589. &AddrFamConfig);
  590. DBG_UNREFERENCED_LOCAL_VARIABLE(InstanceConfig);
  591. if (!SUCCESS(Status))
  592. {
  593. // Fill in the instance config
  594. Status = RtmWriteInstanceConfig(EntityInfo->RtmInstanceId,
  595. &InstanceConfig);
  596. Check(Status, 0);
  597. // Fill in the address family config
  598. AddrFamConfig.AddressSize = sizeof(DWORD);
  599. AddrFamConfig.MaxChangeNotifyRegns = 10;
  600. AddrFamConfig.MaxOpaqueInfoPtrs = 10;
  601. AddrFamConfig.MaxNextHopsInRoute = 5;
  602. AddrFamConfig.MaxHandlesInEnum = 100;
  603. AddrFamConfig.ViewsSupported = RTM_VIEW_MASK_UCAST|RTM_VIEW_MASK_MCAST;
  604. Status = RtmWriteAddressFamilyConfig(EntityInfo->RtmInstanceId,
  605. EntityInfo->AddressFamily,
  606. &AddrFamConfig);
  607. Check(Status, 0);
  608. }
  609. //
  610. // -01- Register with an AF on an RTM instance
  611. //
  612. Status = RtmRegisterEntity(EntityInfo,
  613. (PRTM_ENTITY_EXPORT_METHODS)
  614. EntityChars->ExportMethods,
  615. EntityChars->EventCallback,
  616. TRUE,
  617. &EntityChars->RegnProfile,
  618. &RtmRegHandle);
  619. Check(Status, 1);
  620. //
  621. // Count the number of views for later use
  622. //
  623. NumViews = EntityChars->RegnProfile.NumberOfViews;
  624. //
  625. // Test all the management APIs before others
  626. //
  627. NumInstances = MAX_INSTANCES;
  628. Status = RtmGetInstances(&NumInstances,
  629. &Instances[0]);
  630. Check(Status, 100);
  631. for (i = 0; i < NumInstances; i++)
  632. {
  633. Status = RtmGetInstanceInfo(Instances[i].RtmInstanceId,
  634. &Instances[i],
  635. &Instances[i].NumAddressFamilies,
  636. AddrFams);
  637. Check(Status, 101);
  638. }
  639. //
  640. // Query the appropriate table to check regn
  641. //
  642. NumEntities = MAX_ENTITIES;
  643. Status = RtmGetAddressFamilyInfo(EntityInfo->RtmInstanceId,
  644. EntityInfo->AddressFamily,
  645. &AddrFamilyInfo,
  646. &NumEntities,
  647. EntityInfos);
  648. Check(Status, 102);
  649. //
  650. // -03- Get all currently registered entities
  651. //
  652. NumEntities = MAX_ENTITIES;
  653. Status = RtmGetRegisteredEntities(RtmRegHandle,
  654. &NumEntities,
  655. EntityHandles,
  656. EntityInfos);
  657. Print("\n");
  658. for (i = 0; i < NumEntities; i++)
  659. {
  660. Print("%02d: Handle: %p\n", i, EntityHandles[i]);
  661. }
  662. Print("\n");
  663. Check(Status, 3);
  664. //
  665. // -04- Get all exports methods of each entity
  666. //
  667. for (i = 0; i < NumEntities; i++)
  668. {
  669. NumMethods = 0;
  670. Status = RtmGetEntityMethods(RtmRegHandle,
  671. EntityHandles[i],
  672. &NumMethods,
  673. NULL);
  674. Check(Status, 4);
  675. Print("\n");
  676. Print("Number of methods for %p = %2d\n",
  677. EntityHandles[i],
  678. NumMethods);
  679. Print("\n");
  680. Status = RtmGetEntityMethods(RtmRegHandle,
  681. EntityHandles[i],
  682. &NumMethods,
  683. ExportMethods);
  684. Check(Status, 4);
  685. /*
  686. //
  687. // -06- Try blocking methods & then calling invoke
  688. // Wont block as thread owns Critical Section
  689. //
  690. Status = RtmBlockMethods(RtmRegHandle,
  691. NULL,
  692. 0,
  693. RTM_BLOCK_METHODS);
  694. Check(Status, 6);
  695. */
  696. // for (j = 0; j < NumMethods; j++)
  697. {
  698. //
  699. // -05- Invoke all exports methods of an entity
  700. //
  701. Input.MethodType = METHOD_TYPE_ALL_METHODS; // 1 << j;
  702. Input.InputSize = 0;
  703. OutputHdrSize = FIELD_OFFSET(RTM_ENTITY_METHOD_OUTPUT, OutputData);
  704. OutputSize = OutputHdrSize * MAX_METHODS;
  705. Status = RtmInvokeMethod(RtmRegHandle,
  706. EntityHandles[i],
  707. &Input,
  708. &OutputSize,
  709. Output);
  710. Print("\n");
  711. Print("Num Methods Called = %d\n", OutputSize / OutputHdrSize);
  712. Print("\n");
  713. Check(Status, 5);
  714. }
  715. }
  716. //
  717. // -44- Release handles we have on the entities
  718. //
  719. Status = RtmReleaseEntities(RtmRegHandle,
  720. NumEntities,
  721. EntityHandles);
  722. Check(Status, 44);
  723. //
  724. // -07- Add next hops to the table (from the info file)
  725. //
  726. if ((FilePtr = fopen(EntityChars->RoutesFileName, "r")) == NULL)
  727. {
  728. Fatal("Failed open route database with status = %x\n",
  729. ERROR_OPENING_DATABASE);
  730. }
  731. NumRoutes = ReadRoutesFromFile(FilePtr,
  732. MAX_ROUTES,
  733. Routes);
  734. fclose(FilePtr);
  735. // For each route, add its next-hop to the next-hop table
  736. for (i = 0; i < NumRoutes; i++)
  737. {
  738. RTM_IPV4_MAKE_NET_ADDRESS(&NextHopInfo.NextHopAddress,
  739. Routes[i].nexthop,
  740. ADDRSIZE);
  741. NextHopInfo.RemoteNextHop = NULL;
  742. NextHopInfo.Flags = 0;
  743. NextHopInfo.EntitySpecificInfo = UIntToPtr(i);
  744. NextHopInfo.InterfaceIndex = PtrToUlong(Routes[i].interface);
  745. NextHopHandle = NULL;
  746. Status = RtmAddNextHop(RtmRegHandle,
  747. &NextHopInfo,
  748. &NextHopHandle,
  749. &ChangeFlags);
  750. Check(Status, 7);
  751. // Print("Add Next Hop %lu: %p\n", i, NextHopHandle);
  752. if (!(ChangeFlags & RTM_NEXTHOP_CHANGE_NEW))
  753. {
  754. Status = RtmReleaseNextHops(RtmRegHandle,
  755. 1,
  756. &NextHopHandle);
  757. Check(Status, 15);
  758. }
  759. #if _DBG_
  760. else
  761. {
  762. Status = RtmDeleteNextHop(RtmRegHandle,
  763. NextHopHandle,
  764. NULL);
  765. Check(Status, 14);
  766. }
  767. #endif
  768. }
  769. //
  770. // 08 - Find the next-hops added using RtmFindNextHop
  771. //
  772. for (i = 0; i < NumRoutes; i++)
  773. {
  774. RTM_IPV4_MAKE_NET_ADDRESS(&NextHopInfo.NextHopAddress,
  775. Routes[i].nexthop,
  776. ADDRSIZE);
  777. NextHopInfo.NextHopOwner = RtmRegHandle;
  778. NextHopInfo.InterfaceIndex = PtrToUlong(Routes[i].interface);
  779. NextHopHandle = NULL;
  780. Status = RtmFindNextHop(RtmRegHandle,
  781. &NextHopInfo,
  782. &NextHopHandle,
  783. &NextHopPointer);
  784. // Print("NextHop: Handle: %p,\n\t Addr: ", NextHopHandle);
  785. // Print("%3d.", (UINT) NextHopPointer->NextHopAddress.AddrBits[0]);
  786. // Print("%3d.", (UINT) NextHopPointer->NextHopAddress.AddrBits[1]);
  787. // Print("%3d.", (UINT) NextHopPointer->NextHopAddress.AddrBits[2]);
  788. // Print("%3d ", (UINT) NextHopPointer->NextHopAddress.AddrBits[3]);
  789. // Print("\n\tInterface = %lu\n", NextHopPointer->InterfaceIndex);
  790. Check(Status, 8);
  791. Status = RtmReleaseNextHops(RtmRegHandle,
  792. 1,
  793. &NextHopHandle);
  794. Check(Status, 15);
  795. }
  796. //
  797. // -40- Register with RTM for getting change notifications
  798. //
  799. Status = RtmRegisterForChangeNotification(RtmRegHandle,
  800. RTM_VIEW_MASK_MCAST,
  801. RTM_CHANGE_TYPE_BEST,
  802. // RTM_NOTIFY_ONLY_MARKED_DESTS,
  803. EntityChars,
  804. &NotifyHandle);
  805. Check(Status, 40);
  806. Print("Change Notification Registration Successful\n\n");
  807. //
  808. // -35- Create an entity specific list to add routes to
  809. //
  810. Status = RtmCreateRouteList(RtmRegHandle,
  811. &RouteListHandle1);
  812. Check(Status, 35);
  813. //
  814. // -17- Add routes to RIB with approprate next-hops
  815. //
  816. for (i = 0; i < NumRoutes; i++)
  817. {
  818. // Get the next hop handle using next hop address
  819. RTM_IPV4_MAKE_NET_ADDRESS(&NextHopInfo.NextHopAddress,
  820. Routes[i].nexthop,
  821. ADDRSIZE);
  822. NextHopInfo.NextHopOwner = RtmRegHandle;
  823. NextHopInfo.InterfaceIndex = PtrToUlong(Routes[i].interface);
  824. NextHopHandle = NULL;
  825. Status = RtmFindNextHop(RtmRegHandle,
  826. &NextHopInfo,
  827. &NextHopHandle,
  828. NULL);
  829. Check(Status, 8);
  830. // Now do the route add with the right information
  831. RouteHandle = NULL;
  832. RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress,
  833. Routes[i].addr,
  834. Routes[i].len);
  835. // Print("Add Route: Len : %08x, Addr = %3d.%3d.%3d.%3d\n",
  836. // NetAddress.NumBits,
  837. // NetAddress.AddrBits[0],
  838. // NetAddress.AddrBits[1],
  839. // NetAddress.AddrBits[2],
  840. // NetAddress.AddrBits[3]);
  841. ZeroMemory(&RouteInfo, sizeof(RTM_ROUTE_INFO));
  842. // Assume 'neighbour learnt from' is the 1st nexthop
  843. RouteInfo.Neighbour = NextHopHandle;
  844. RouteInfo.PrefInfo.Preference = EntityInfo->EntityId.EntityProtocolId;
  845. RouteInfo.PrefInfo.Metric = Routes[i].metric;
  846. RouteInfo.BelongsToViews = VIEW_MASK_ARR[1 + (i % 3)];
  847. RouteInfo.EntitySpecificInfo = UIntToPtr(i);
  848. RouteInfo.NextHopsList.NumNextHops = 1;
  849. RouteInfo.NextHopsList.NextHops[0] = NextHopHandle;
  850. ChangeFlags = RTM_ROUTE_CHANGE_NEW;
  851. Status = RtmAddRouteToDest(RtmRegHandle,
  852. &RouteHandle,
  853. &NetAddress,
  854. &RouteInfo,
  855. INFINITE,
  856. RouteListHandle1,
  857. 0,
  858. NULL,
  859. &ChangeFlags);
  860. Check(Status, 17);
  861. // Update the same route using the handle
  862. ChangeFlags = 0;
  863. RouteInfo.Flags = RTM_ROUTE_FLAGS_DISCARD;
  864. Status = RtmAddRouteToDest(RtmRegHandle,
  865. &RouteHandle,
  866. &NetAddress,
  867. &RouteInfo,
  868. INFINITE,
  869. RouteListHandle1,
  870. 0,
  871. NULL,
  872. &ChangeFlags);
  873. Check(Status, 17);
  874. // Print("Add Route %lu: %p\n", i, RouteHandle);
  875. Status = RtmLockRoute(RtmRegHandle,
  876. RouteHandle,
  877. TRUE,
  878. TRUE,
  879. &RoutePointer);
  880. Check(Status, 46);
  881. // Update route parameters in place
  882. RoutePointer->PrefInfo.Metric = 1000 - RoutePointer->PrefInfo.Metric;
  883. RoutePointer->BelongsToViews = VIEW_MASK_ARR[i % 3];
  884. RoutePointer->EntitySpecificInfo = UIntToPtr(1000 - i);
  885. Status = RtmUpdateAndUnlockRoute(RtmRegHandle,
  886. RouteHandle,
  887. 10, // INFINITE,
  888. NULL,
  889. 0,
  890. NULL,
  891. &ChangeFlags);
  892. Check(Status, 47);
  893. // Print("Update Route %lu: %p\n", i, RouteHandle);
  894. if (!SUCCESS(Status))
  895. {
  896. Status = RtmLockRoute(RtmRegHandle,
  897. RouteHandle,
  898. TRUE,
  899. FALSE,
  900. NULL);
  901. Check(Status, 46);
  902. }
  903. // Try doing a add specifying the route handle
  904. RouteInfo.PrefInfo.Metric = Routes[i].metric;
  905. RouteInfo.BelongsToViews = VIEW_MASK_ARR[1 + (i % 3)];
  906. RouteInfo.EntitySpecificInfo = UIntToPtr(i);
  907. ChangeFlags = 0;
  908. Status = RtmAddRouteToDest(RtmRegHandle,
  909. &RouteHandle,
  910. &NetAddress,
  911. &RouteInfo,
  912. INFINITE,
  913. RouteListHandle1,
  914. 0,
  915. NULL,
  916. &ChangeFlags);
  917. Check(Status, 17);
  918. Status = RtmReleaseNextHops(RtmRegHandle,
  919. 1,
  920. &NextHopHandle);
  921. // Check(Status, 15);
  922. if (!SUCCESS(Status))
  923. {
  924. // Print("%p %p\n", RtmRegHandle,NextHopHandle);
  925. Status = RtmReleaseNextHops(RtmRegHandle,
  926. 1,
  927. &NextHopHandle);
  928. Check(Status, 15);
  929. }
  930. }
  931. Status = RtmCreateRouteList(RtmRegHandle,
  932. &RouteListHandle2);
  933. Check(Status, 35);
  934. //
  935. // -38- Create an enumeration on the route list
  936. //
  937. Status = RtmCreateRouteListEnum(RtmRegHandle,
  938. RouteListHandle1,
  939. &EnumHandle);
  940. Check(Status, 38);
  941. TotalHandles = 0;
  942. do
  943. {
  944. //
  945. // -39- Get next set of routes on the enum
  946. //
  947. NumHandles = MAX_HANDLES;
  948. Status = RtmGetListEnumRoutes(RtmRegHandle,
  949. EnumHandle,
  950. &NumHandles,
  951. Handles);
  952. Check(Status, 39);
  953. TotalHandles += NumHandles;
  954. for (i = 0; i < NumHandles; i++)
  955. {
  956. ; // Print("Route Handle %5lu: %p\n", i, Handles[i]);
  957. }
  958. //
  959. // -37- Move all routes in one route list to another
  960. //
  961. Status = RtmInsertInRouteList(RtmRegHandle,
  962. RouteListHandle2,
  963. NumHandles,
  964. Handles);
  965. Check(Status, 37);
  966. //
  967. // Release the routes that have been enum'ed
  968. //
  969. Status = RtmReleaseRoutes(RtmRegHandle, NumHandles, Handles);
  970. Check(Status, 27);
  971. }
  972. while (NumHandles == MAX_HANDLES);
  973. Print("\nTotal Num of handles in list: %lu\n", TotalHandles);
  974. //
  975. // -36- Destroy all the entity specific lists
  976. //
  977. Status = RtmDeleteRouteList(RtmRegHandle, RouteListHandle1);
  978. Check(Status, 36);
  979. Status = RtmDeleteRouteList(RtmRegHandle, RouteListHandle2);
  980. Check(Status, 36);
  981. DestInfoSize = RTM_SIZE_OF_DEST_INFO(NumViews);
  982. DestInfo1 = ALLOC_RTM_DEST_INFO(NumViews, 1);
  983. DestInfo2 = ALLOC_RTM_DEST_INFO(NumViews, 1);
  984. //
  985. // -18- Get dests from the table using exact match
  986. //
  987. for (i = 0; i < NumRoutes; i++)
  988. {
  989. // Query for the route with the right information
  990. RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress, Routes[i].addr, Routes[i].len);
  991. Status = RtmGetExactMatchDestination(RtmRegHandle,
  992. &NetAddress,
  993. RTM_BEST_PROTOCOL,
  994. 0,
  995. DestInfo1);
  996. Check(Status, 18);
  997. //
  998. // For each destination in table, mark the dest
  999. //
  1000. Status = RtmMarkDestForChangeNotification(RtmRegHandle,
  1001. NotifyHandle,
  1002. DestInfo1->DestHandle,
  1003. TRUE);
  1004. Check(Status, 48);
  1005. Status = RtmIsMarkedForChangeNotification(RtmRegHandle,
  1006. NotifyHandle,
  1007. DestInfo1->DestHandle,
  1008. &Marked);
  1009. Check(Status, 49);
  1010. Assert(Marked == TRUE);
  1011. Status = RtmReleaseDestInfo(RtmRegHandle, DestInfo1);
  1012. Check(Status, 22);
  1013. }
  1014. DestInfo1 = ALLOC_RTM_DEST_INFO(NumViews, 1);
  1015. DestInfo2 = ALLOC_RTM_DEST_INFO(NumViews, 1);
  1016. //
  1017. // -29- Get routes from the table using exact match
  1018. //
  1019. for (i = 0; i < NumRoutes; i++)
  1020. {
  1021. // Get the next hop handle using next hop address
  1022. RTM_IPV4_MAKE_NET_ADDRESS(&NextHopInfo.NextHopAddress,
  1023. Routes[i].nexthop,
  1024. ADDRSIZE);
  1025. NextHopInfo.NextHopOwner = RtmRegHandle;
  1026. NextHopInfo.InterfaceIndex = PtrToUlong(Routes[i].interface);
  1027. NextHopHandle = NULL;
  1028. Status = RtmFindNextHop(RtmRegHandle,
  1029. &NextHopInfo,
  1030. &NextHopHandle,
  1031. NULL);
  1032. Check(Status, 8);
  1033. RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress,
  1034. Routes[i].addr,
  1035. Routes[i].len);
  1036. // Query for the route with the right information
  1037. RouteInfo.Neighbour = NextHopHandle;
  1038. RouteInfo.RouteOwner = RtmRegHandle;
  1039. RouteInfo.PrefInfo.Preference = EntityInfo->EntityId.EntityProtocolId;
  1040. RouteInfo.PrefInfo.Metric = Routes[i].metric;
  1041. RouteInfo.NextHopsList.NumNextHops = 1;
  1042. RouteInfo.NextHopsList.NextHops[0] = NextHopHandle;
  1043. Status = RtmGetExactMatchRoute(RtmRegHandle,
  1044. &NetAddress,
  1045. RTM_MATCH_FULL,
  1046. &RouteInfo,
  1047. PtrToUlong(Routes[i].interface),
  1048. 0,
  1049. &RouteHandle);
  1050. Check(Status, 29);
  1051. Status = RtmReleaseNextHops(RtmRegHandle,
  1052. 1,
  1053. &NextHopHandle);
  1054. Check(Status, 15);
  1055. Status = RtmReleaseRoutes(RtmRegHandle, 1, &RouteHandle);
  1056. Check(Status, 27);
  1057. Status = RtmReleaseRouteInfo(RtmRegHandle, &RouteInfo);
  1058. Check(Status, 31);
  1059. }
  1060. //
  1061. // -19- Get dests from the table using prefix match
  1062. //
  1063. // -20- Do a prefix walk up the tree for each dest
  1064. //
  1065. for (i = j = 0; i < NumRoutes; i++)
  1066. {
  1067. // Query for the route with the right information
  1068. RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress,
  1069. Routes[i].addr,
  1070. Routes[i].len);
  1071. Status = RtmGetMostSpecificDestination(RtmRegHandle,
  1072. &NetAddress,
  1073. RTM_BEST_PROTOCOL,
  1074. RTM_VIEW_MASK_UCAST,
  1075. DestInfo1);
  1076. // Check(Status, 19);
  1077. if (DestInfo1->DestAddress.NumBits != NetAddress.NumBits)
  1078. {
  1079. ; // Print("No Exact Match : %5lu\n", j++);
  1080. }
  1081. while (SUCCESS(Status))
  1082. {
  1083. Status = RtmGetLessSpecificDestination(RtmRegHandle,
  1084. DestInfo1->DestHandle,
  1085. RTM_BEST_PROTOCOL,
  1086. RTM_VIEW_MASK_UCAST,
  1087. DestInfo2);
  1088. // Check(Status, 20);
  1089. Check(RtmReleaseDestInfo(RtmRegHandle, DestInfo1), 22);
  1090. if (!SUCCESS(Status)) break;
  1091. // Print("NumBits: %d\n", DestInfo2->DestAddress.NumBits);
  1092. Status = RtmGetLessSpecificDestination(RtmRegHandle,
  1093. DestInfo2->DestHandle,
  1094. RTM_BEST_PROTOCOL,
  1095. RTM_VIEW_MASK_UCAST,
  1096. DestInfo1);
  1097. // Check(Status, 20);
  1098. Check(RtmReleaseDestInfo(RtmRegHandle, DestInfo2), 20);
  1099. if (!SUCCESS(Status)) break;
  1100. // Print("NumBits: %d\n", DestInfo1->DestAddress.NumBits);
  1101. }
  1102. }
  1103. #if DBG
  1104. for (i = 0; i < 100000000; i++) { ; }
  1105. #endif
  1106. //
  1107. // Just do a "route enum" over the whole table
  1108. //
  1109. Status2 = RtmCreateRouteEnum(RtmRegHandle,
  1110. NULL,
  1111. 0, // RTM_VIEW_MASK_UCAST|RTM_VIEW_MASK_MCAST,
  1112. RTM_ENUM_OWN_ROUTES,
  1113. NULL,
  1114. 0,
  1115. NULL,
  1116. 0,
  1117. &EnumHandle2);
  1118. Check(Status2, 25);
  1119. l = 0;
  1120. do
  1121. {
  1122. NumHandles = MAX_HANDLES;
  1123. Status2 = RtmGetEnumRoutes(RtmRegHandle,
  1124. EnumHandle2,
  1125. &NumHandles,
  1126. Handles);
  1127. // Check(Status2, 26);
  1128. for (k = 0; k < NumHandles; k++)
  1129. {
  1130. ; // Print("Route %d: %p\n", l++, Handles[k]);
  1131. }
  1132. Check(RtmReleaseRoutes(RtmRegHandle,
  1133. NumHandles,
  1134. Handles), 27);
  1135. }
  1136. while (SUCCESS(Status2));
  1137. //
  1138. // Just try a enum query after ERROR_NO_MORE_ITEMS is retd
  1139. //
  1140. NumHandles = MAX_HANDLES;
  1141. Status2 = RtmGetEnumRoutes(RtmRegHandle,
  1142. EnumHandle2,
  1143. &NumHandles,
  1144. Handles);
  1145. Assert((NumHandles == 0) && (Status2 == ERROR_NO_MORE_ITEMS));
  1146. Status2 = RtmDeleteEnumHandle(RtmRegHandle,
  1147. EnumHandle2);
  1148. Check(Status2, 16);
  1149. //
  1150. // Get dests from the table using an enumeration
  1151. // -23- Open a new dest enumeration
  1152. // -24- Get dests in enum
  1153. // -16- Close destination enum.
  1154. //
  1155. DestInfos = ALLOC_RTM_DEST_INFO(NumViews, MAX_HANDLES);
  1156. #if MCAST_ENUM
  1157. RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress,
  1158. 0x000000E0,
  1159. 4);
  1160. #else
  1161. RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress,
  1162. 0x00000000,
  1163. 0);
  1164. #endif
  1165. Status = RtmCreateDestEnum(RtmRegHandle,
  1166. RTM_VIEW_MASK_UCAST | RTM_VIEW_MASK_MCAST,
  1167. RTM_ENUM_RANGE | RTM_ENUM_OWN_DESTS,
  1168. &NetAddress,
  1169. RTM_THIS_PROTOCOL,
  1170. &EnumHandle1);
  1171. Check(Status, 23);
  1172. m = j = 0;
  1173. do
  1174. {
  1175. NumInfos = MAX_HANDLES;
  1176. Status1 = RtmGetEnumDests(RtmRegHandle,
  1177. EnumHandle1,
  1178. &NumInfos,
  1179. DestInfos);
  1180. // Check(Status1, 24);
  1181. for (i = 0; i < NumInfos; i++)
  1182. {
  1183. DestInfo1 = (PRTM_DEST_INFO) ((PUCHAR)DestInfos+(i*DestInfoSize));
  1184. // Print("Dest %d: %p\n", j++, DestInfo1->DestHandle);
  1185. // PrintDestInfo(DestInfo1);
  1186. Status2 = RtmCreateRouteEnum(RtmRegHandle,
  1187. DestInfo1->DestHandle,
  1188. RTM_VIEW_MASK_UCAST |
  1189. RTM_VIEW_MASK_MCAST,
  1190. RTM_ENUM_OWN_ROUTES,
  1191. NULL,
  1192. 0, // RTM_MATCH_INTERFACE,
  1193. NULL,
  1194. 0,
  1195. &EnumHandle2);
  1196. Check(Status2, 25);
  1197. /*
  1198. Check(RtmHoldDestination(RtmRegHandle,
  1199. DestInfo1->DestHandle,
  1200. RTM_VIEW_MASK_UCAST,
  1201. 100), 33);
  1202. */
  1203. l = 0;
  1204. PrefInfo.Preference = (ULONG) ~0;
  1205. PrefInfo.Metric = (ULONG) 0;
  1206. do
  1207. {
  1208. NumHandles = MAX_HANDLES;
  1209. Status2 = RtmGetEnumRoutes(RtmRegHandle,
  1210. EnumHandle2,
  1211. &NumHandles,
  1212. Handles);
  1213. // Check(Status2, 26);
  1214. for (k = 0; k < NumHandles; k++)
  1215. {
  1216. // Print("\tRoute %d: %p\t", l++, Handles[k]);
  1217. // PrintRouteInfo(Handles[k]);
  1218. Status = RtmIsBestRoute(RtmRegHandle,
  1219. Handles[k],
  1220. &ViewSet);
  1221. Check(Status, 28);
  1222. // Print("Best In Views: %08x\n", ViewSet);
  1223. Status = RtmGetRouteInfo(RtmRegHandle,
  1224. Handles[k],
  1225. &RouteInfo,
  1226. &NetAddress);
  1227. Check(Status, 30);
  1228. Print("RouteDest: Len : %08x," \
  1229. " Addr = %3d.%3d.%3d.%3d," \
  1230. " Pref = %08x, %08x\n",
  1231. NetAddress.NumBits,
  1232. NetAddress.AddrBits[0],
  1233. NetAddress.AddrBits[1],
  1234. NetAddress.AddrBits[2],
  1235. NetAddress.AddrBits[3],
  1236. RouteInfo.PrefInfo.Preference,
  1237. RouteInfo.PrefInfo.Metric);
  1238. //
  1239. // Make sure that list is ordered by PrefInfo
  1240. //
  1241. if ((PrefInfo.Preference < RouteInfo.PrefInfo.Preference)||
  1242. ((PrefInfo.Preference == RouteInfo.PrefInfo.Preference)
  1243. && (PrefInfo.Metric > RouteInfo.PrefInfo.Metric)))
  1244. {
  1245. Check(ERROR_INVALID_DATA, 150);
  1246. }
  1247. Status = RtmReleaseRouteInfo(RtmRegHandle,
  1248. &RouteInfo);
  1249. Check(Status, 31);
  1250. // Print("Del Route %lu: %p\n", m++, Handles[k]);
  1251. Status = RtmDeleteRouteToDest(RtmRegHandle,
  1252. Handles[k],
  1253. &ChangeFlags);
  1254. Check(Status, 32);
  1255. }
  1256. Check(RtmReleaseRoutes(RtmRegHandle,
  1257. NumHandles,
  1258. Handles), 27);
  1259. }
  1260. while (SUCCESS(Status2));
  1261. //
  1262. // Just try a enum query after ERROR_NO_MORE_ITEMS is retd
  1263. //
  1264. NumHandles = MAX_HANDLES;
  1265. Status2 = RtmGetEnumRoutes(RtmRegHandle,
  1266. EnumHandle2,
  1267. &NumHandles,
  1268. Handles);
  1269. Assert((NumHandles == 0) && (Status2 == ERROR_NO_MORE_ITEMS));
  1270. /*
  1271. Check(RtmHoldDestination(RtmRegHandle,
  1272. DestInfo1->DestHandle,
  1273. RTM_VIEW_MASK_MCAST,
  1274. 100), 33);
  1275. */
  1276. Status2 = RtmDeleteEnumHandle(RtmRegHandle,
  1277. EnumHandle2);
  1278. Check(Status2, 16);
  1279. // Check(RtmReleaseDestInfo(RtmRegHandle,
  1280. // DestInfo1), 22);
  1281. }
  1282. Check(RtmReleaseDests(RtmRegHandle,
  1283. NumInfos,
  1284. DestInfos), 34);
  1285. }
  1286. while (SUCCESS(Status1));
  1287. //
  1288. // Just try a enum query after ERROR_NO_MORE_ITEMS is retd
  1289. //
  1290. NumInfos = MAX_HANDLES;
  1291. Status1 = RtmGetEnumDests(RtmRegHandle,
  1292. EnumHandle1,
  1293. &NumInfos,
  1294. DestInfos);
  1295. Assert((NumInfos == 0) && (Status1 == ERROR_NO_MORE_ITEMS));
  1296. Status1 = RtmDeleteEnumHandle(RtmRegHandle,
  1297. EnumHandle1);
  1298. Check(Status1, 16);
  1299. //
  1300. // -10- Enumerate all the next-hops in table,
  1301. //
  1302. // -11- For each next-hop in table
  1303. // -12- Get the next hop info,
  1304. // -14- Delete the next-hop,
  1305. // -13- Release next hop info.
  1306. //
  1307. // -15- Release all the next-hops in table,
  1308. //
  1309. // -16- Close the next hop enumeration handle.
  1310. //
  1311. Status = RtmCreateNextHopEnum(RtmRegHandle,
  1312. 0,
  1313. NULL,
  1314. &EnumHandle);
  1315. Check(Status, 10);
  1316. j = 0;
  1317. do
  1318. {
  1319. NumHandles = 5; // MAX_HANDLES;
  1320. Status = RtmGetEnumNextHops(RtmRegHandle,
  1321. EnumHandle,
  1322. &NumHandles,
  1323. Handles);
  1324. // Check(Status, 11);
  1325. for (i = 0; i < NumHandles; i++)
  1326. {
  1327. Check(RtmGetNextHopInfo(RtmRegHandle,
  1328. Handles[i],
  1329. &NextHopInfo), 12);
  1330. // Print("Deleting NextHop %lu: %p\n", j++, Handles[i]);
  1331. // Print("State: %04x, Interface: %d\n",
  1332. // NextHopInfo.State,
  1333. // NextHopInfo.InterfaceIndex);
  1334. Check(RtmDeleteNextHop(RtmRegHandle,
  1335. Handles[i],
  1336. NULL), 14);
  1337. Check(RtmReleaseNextHopInfo(RtmRegHandle,
  1338. &NextHopInfo), 13);
  1339. }
  1340. Check(RtmReleaseNextHops(RtmRegHandle,
  1341. NumHandles,
  1342. Handles), 15);
  1343. }
  1344. while (SUCCESS(Status));
  1345. //
  1346. // Just try a enum query after ERROR_NO_MORE_ITEMS is retd
  1347. //
  1348. NumHandles = MAX_HANDLES;
  1349. Status = RtmGetEnumNextHops(RtmRegHandle,
  1350. EnumHandle,
  1351. &NumHandles,
  1352. Handles);
  1353. Assert((NumHandles == 0) && (Status == ERROR_NO_MORE_ITEMS));
  1354. Status = RtmDeleteEnumHandle(RtmRegHandle,
  1355. EnumHandle);
  1356. Check(Status, 16);
  1357. //
  1358. // Make sure that the next hop table is empty now
  1359. //
  1360. Status = RtmCreateNextHopEnum(RtmRegHandle,
  1361. 0,
  1362. NULL,
  1363. &EnumHandle);
  1364. NumHandles = MAX_HANDLES;
  1365. Status = RtmGetEnumNextHops(RtmRegHandle,
  1366. EnumHandle,
  1367. &NumHandles,
  1368. Handles);
  1369. if ((Status != ERROR_NO_MORE_ITEMS) || (NumHandles != 0))
  1370. {
  1371. Check(Status, 11);
  1372. }
  1373. Status = RtmDeleteEnumHandle(RtmRegHandle,
  1374. EnumHandle);
  1375. Check(Status, 16);
  1376. Sleep(1000);
  1377. //
  1378. // -41- Deregister all existing change notif registrations
  1379. //
  1380. Status = RtmDeregisterFromChangeNotification(RtmRegHandle,
  1381. NotifyHandle);
  1382. Check(Status, 41);
  1383. Print("Change Notification Deregistration Successful\n\n");
  1384. //
  1385. // -02- De-register with the RTM before exiting
  1386. //
  1387. Status = RtmDeregisterEntity(RtmRegHandle);
  1388. Check(Status, 2);
  1389. #if _DBG_
  1390. Status = RtmDeregisterEntity(RtmRegHandle);
  1391. Check(Status, 2);
  1392. #endif
  1393. Print("\n--------------------------------------------------------\n");
  1394. return NO_ERROR;
  1395. }
  1396. DWORD
  1397. EntityEventCallback (
  1398. IN RTM_ENTITY_HANDLE RtmRegHandle,
  1399. IN RTM_EVENT_TYPE EventType,
  1400. IN PVOID Context1,
  1401. IN PVOID Context2
  1402. )
  1403. {
  1404. RTM_ENTITY_HANDLE EntityHandle;
  1405. PENTITY_CHARS EntityChars;
  1406. PRTM_ENTITY_INFO EntityInfo;
  1407. RTM_NOTIFY_HANDLE NotifyHandle;
  1408. PRTM_DEST_INFO DestInfos;
  1409. UINT NumDests;
  1410. UINT NumViews;
  1411. RTM_ROUTE_HANDLE RouteHandle;
  1412. PRTM_ROUTE_INFO RoutePointer;
  1413. DWORD ChangeFlags;
  1414. DWORD Status;
  1415. Print("\nEvent callback called for %p :", RtmRegHandle);
  1416. Status = NO_ERROR;
  1417. Print("\n\tEntity Event = ");
  1418. switch (EventType)
  1419. {
  1420. case RTM_ENTITY_REGISTERED:
  1421. EntityHandle = (RTM_ENTITY_HANDLE) Context1;
  1422. EntityInfo = (PRTM_ENTITY_INFO) Context2;
  1423. Print("Registration\n\tEntity Handle = %p\n\tEntity IdInst = %p\n\n",
  1424. EntityHandle,
  1425. EntityInfo->EntityId);
  1426. /*
  1427. //
  1428. // -45- Make a copy of the handle of new entity
  1429. //
  1430. Status = RtmReferenceHandles(RtmRegHandle,
  1431. 1,
  1432. &EntityHandle);
  1433. Check(Status, 45);
  1434. */
  1435. break;
  1436. case RTM_ENTITY_DEREGISTERED:
  1437. EntityHandle = (RTM_ENTITY_HANDLE) Context1;
  1438. EntityInfo = (PRTM_ENTITY_INFO) Context2;
  1439. Print("Deregistration\n\tEntity Handle = %p\n\tEntity IdInst = %p\n\n",
  1440. EntityHandle,
  1441. EntityInfo->EntityId);
  1442. /*
  1443. //
  1444. // -44- Release the handle we have on the entity
  1445. //
  1446. Status = RtmReleaseEntities(RtmRegHandle,
  1447. 1,
  1448. &EntityHandle);
  1449. Check(Status, 44);
  1450. */
  1451. break;
  1452. case RTM_CHANGE_NOTIFICATION:
  1453. NotifyHandle = (RTM_NOTIFY_HANDLE) Context1;
  1454. EntityChars = (PENTITY_CHARS) Context2;
  1455. Print("Changes Available\n\tNotify Handle = %p\n\tEntity Ch = %p\n\n",
  1456. NotifyHandle,
  1457. EntityChars);
  1458. //
  1459. // Count the number of view for later use
  1460. //
  1461. NumViews = EntityChars->RegnProfile.NumberOfViews;
  1462. //
  1463. // -43- Get all changes to destinations
  1464. //
  1465. DestInfos = ALLOC_RTM_DEST_INFO(NumViews, MAX_HANDLES);
  1466. do
  1467. {
  1468. NumDests = MAX_HANDLES;
  1469. Status = RtmGetChangedDests(RtmRegHandle,
  1470. NotifyHandle,
  1471. &NumDests,
  1472. DestInfos);
  1473. // Check(Status, 42);
  1474. printf("Status = %lu\n", Status);
  1475. Print("Num Changed Dests = %d\n", NumDests);
  1476. EntityChars->TotalChangedDests += NumDests;
  1477. Status = RtmReleaseChangedDests(RtmRegHandle,
  1478. NotifyHandle,
  1479. NumDests,
  1480. DestInfos);
  1481. Check(Status, 43);
  1482. }
  1483. while (NumDests > 0);
  1484. Print("Total Changed Dests = %d\n", EntityChars->TotalChangedDests);
  1485. break;
  1486. case RTM_ROUTE_EXPIRED:
  1487. RouteHandle = (RTM_ROUTE_HANDLE) Context1;
  1488. RoutePointer = (PRTM_ROUTE_INFO) Context2;
  1489. Print("Route Aged Out\n\tRoute Handle = %p\n\tRoute Pointer = %p\n\n",
  1490. RouteHandle,
  1491. RoutePointer);
  1492. // Refresh the route by doing dummy update in place
  1493. Status = RtmLockRoute(RtmRegHandle,
  1494. RouteHandle,
  1495. TRUE,
  1496. TRUE,
  1497. NULL);
  1498. // Check(Status, 46);
  1499. if (Status == NO_ERROR)
  1500. {
  1501. Status = RtmUpdateAndUnlockRoute(RtmRegHandle,
  1502. RouteHandle,
  1503. INFINITE,
  1504. NULL,
  1505. 0,
  1506. NULL,
  1507. &ChangeFlags);
  1508. Check(Status, 47);
  1509. if (!SUCCESS(Status))
  1510. {
  1511. Status = RtmLockRoute(RtmRegHandle,
  1512. RouteHandle,
  1513. TRUE,
  1514. FALSE,
  1515. NULL);
  1516. Check(Status, 46);
  1517. }
  1518. }
  1519. Check(RtmReleaseRoutes(RtmRegHandle,
  1520. 1,
  1521. &RouteHandle), 27);
  1522. break;
  1523. default:
  1524. Status = ERROR_NOT_SUPPORTED;
  1525. }
  1526. return Status;
  1527. }
  1528. VOID
  1529. EntityExportMethod (
  1530. IN RTM_ENTITY_HANDLE CallerHandle,
  1531. IN RTM_ENTITY_HANDLE CalleeHandle,
  1532. IN RTM_ENTITY_METHOD_INPUT *Input,
  1533. OUT RTM_ENTITY_METHOD_OUTPUT *Output
  1534. )
  1535. {
  1536. Print("Export Function %2d called on %p: Caller = %p\n\n",
  1537. Input->MethodType,
  1538. CalleeHandle,
  1539. CallerHandle);
  1540. Output->MethodStatus = NO_ERROR;
  1541. return;
  1542. }
  1543. // Default warnings for unreferenced params and local variables
  1544. #pragma warning(default: 4100)
  1545. #pragma warning(default: 4101)
  1546. #if _DBG_
  1547. 00 RtmReadAddrFamilyConfig
  1548. 00 RtmWriteAddrFamilyConfig
  1549. 00 RtmWriteInstanceConfig
  1550. 01 RtmRegisterEntity
  1551. 02 RtmDeregisterEntity
  1552. 03 RtmGetRegdEntities
  1553. 04 RtmGetEntityMethods
  1554. 05 RtmInvokeMethod
  1555. 06 RtmBlockMethods
  1556. 07 RtmAddNextHop
  1557. 08 RtmFindNextHop
  1558. 09 RtmLockNextHop
  1559. 10 RtmCreateNextHopEnum
  1560. 11 RtmGetEnumNextHops
  1561. 12 RtmGetNextHopInfo
  1562. 13 RtmReleaseNextHopInfo
  1563. 14 RtmDelNextHop
  1564. 15 RtmReleaseNextHops
  1565. 16 RtmDeleteEnumHandle
  1566. 17 RtmAddRouteToDest
  1567. 18 RtmGetExactMatchDestination
  1568. 19 RtmGetMostSpecificDestination
  1569. 20 RtmGetLessSpecificDestination
  1570. 21 RtmGetDestInfo
  1571. 22 RtmReleaseDestInfo
  1572. 23 RtmCreateDestEnum
  1573. 24 RtmGetEnumDests
  1574. 25 RtmCreateRouteEnum
  1575. 26 RtmGetEnumRoutes
  1576. 27 RtmReleaseRoutes
  1577. 28 RtmIsBestRoute
  1578. 29 RtmGetExactMatchRoute
  1579. 30 RtmGetRouteInfo
  1580. 31 RtmReleaseRouteInfo
  1581. 32 RtmDelRoute
  1582. 33 RtmHoldDestination
  1583. 34 RtmReleaseDests
  1584. 35 RtmCreateRouteList
  1585. 36 RtmDeleteRouteList
  1586. 37 RtmInsertInRouteList
  1587. 38 RtmCreateRouteListEnum
  1588. 39 RtmGetListEnumRoutes
  1589. 40 RtmRegisterForChangeNotification
  1590. 41 RtmDeregisterFromChangeNotification
  1591. 42 RtmGetChangedDests
  1592. 43 RtmReleaseChangedDests
  1593. 44 RtmReleaseEntities
  1594. 45 RtmReferenceHandles
  1595. 46 RtmLockRoute
  1596. 47 RtmUpdateAndUnlockRoute
  1597. 48 RtmMarkDestForChangeNotification
  1598. 49 RtmIsMarkedForChangeNotification
  1599. 50 RtmCreateRouteTable
  1600. 51 RtmDeleteRouteTable
  1601. 52 RtmRegisterClient
  1602. 53 RtmDeregisterClient
  1603. 54 RtmAddRoute
  1604. 55 RtmDeleteRoute
  1605. 56 RtmCreateEnumerationHandle
  1606. 57 RtmCloseEnumerationHandle
  1607. 58 RtmEnumerateGetNextRoute
  1608. 59 RtmGetFirstRoute
  1609. 60 RtmGetNextRoute
  1610. 61 RtmBlockDeleteRoutes
  1611. 62 RtmBlockConvertRoutesToStatic
  1612. 63 RtmGetNetworkCount
  1613. 64 RtmIsRoute
  1614. 65 RtmLookupIPDestination
  1615. 66 RtmBlockSetRouteEnable
  1616. #endif