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.

1854 lines
42 KiB

  1. /*++
  2. Copyright (c) 1997 - 98, Microsoft Corporation
  3. Module Name:
  4. rtmenum.c
  5. Abstract:
  6. Contains routines for managing any enumerations
  7. over destinations, routes and next hops in RTM.
  8. Author:
  9. Chaitanya Kodeboyina (chaitk) 23-Aug-1998
  10. Revision History:
  11. --*/
  12. #include "pchrtm.h"
  13. #pragma hdrstop
  14. DWORD
  15. WINAPI
  16. RtmCreateDestEnum (
  17. IN RTM_ENTITY_HANDLE RtmRegHandle,
  18. IN RTM_VIEW_SET TargetViews,
  19. IN RTM_ENUM_FLAGS EnumFlags,
  20. IN PRTM_NET_ADDRESS NetAddress,
  21. IN ULONG ProtocolId,
  22. OUT PRTM_ENUM_HANDLE RtmEnumHandle
  23. )
  24. /*++
  25. Routine Description:
  26. Creates a enumeration over the destinations in the route table.
  27. Arguments:
  28. RtmRegHandle - RTM registration handle for calling entity,
  29. TargetViews - Set of views in which the enumeration is done,
  30. EnumFlags - Flags that control the dests returned in enum,
  31. NetAddress - Start and/or stop address of the enumeration,
  32. [ See a description of RTM_ENUM_FLAGS ...]
  33. Protocol Id - Protocol Id that determines the best route
  34. information returned in 'GetEnumDests' call,
  35. RtmEnumHandle - Handle to this enumeration, which is used
  36. in subsequent calls to get dests, and so on.
  37. Return Value:
  38. Status of the operation
  39. --*/
  40. {
  41. PADDRFAM_INFO AddrFamInfo;
  42. PENTITY_INFO Entity;
  43. PDEST_ENUM Enum;
  44. PUCHAR AddrBits;
  45. UINT AddrSize;
  46. UINT i, j;
  47. DWORD Status;
  48. //
  49. // Do some validation checks on the input params
  50. //
  51. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  52. if ((EnumFlags & RTM_ENUM_NEXT) && (EnumFlags & RTM_ENUM_RANGE))
  53. {
  54. return ERROR_INVALID_PARAMETER;
  55. }
  56. if (EnumFlags & (RTM_ENUM_NEXT | RTM_ENUM_RANGE))
  57. {
  58. if (!NetAddress)
  59. {
  60. return ERROR_INVALID_PARAMETER;
  61. }
  62. }
  63. AddrFamInfo = Entity->OwningAddrFamily;
  64. //
  65. // Is he interested in any non-supported views ?
  66. //
  67. if (TargetViews & ~AddrFamInfo->ViewsSupported)
  68. {
  69. return ERROR_NOT_SUPPORTED;
  70. }
  71. //
  72. // Create and initialize an dest enumeration block
  73. //
  74. Enum = (PDEST_ENUM) AllocNZeroObject(sizeof(DEST_ENUM));
  75. if (Enum == NULL)
  76. {
  77. return ERROR_NOT_ENOUGH_MEMORY;
  78. }
  79. do
  80. {
  81. #if DBG_HDL
  82. Enum->EnumHeader.ObjectHeader.TypeSign = DEST_ENUM_ALLOC;
  83. #endif
  84. Enum->EnumHeader.HandleType = DEST_ENUM_TYPE;
  85. Enum->TargetViews = TargetViews;
  86. Enum->NumberOfViews = NUMBER_OF_BITS(TargetViews);
  87. Enum->ProtocolId = ProtocolId;
  88. Enum->EnumFlags = EnumFlags;
  89. #if DBG
  90. // Initialize the first address in the enum
  91. if (Enum->EnumFlags & (RTM_ENUM_NEXT | RTM_ENUM_RANGE))
  92. {
  93. CopyMemory(&Enum->StartAddress,
  94. NetAddress,
  95. sizeof(RTM_NET_ADDRESS));
  96. }
  97. #endif
  98. AddrSize = AddrFamInfo->AddressSize;
  99. //
  100. // Initialize the last address in the enum
  101. //
  102. if (Enum->EnumFlags & RTM_ENUM_RANGE)
  103. {
  104. //
  105. // Convert the NetAddress a.b/n -> a.b.FF.FF/N where N = ADDRSIZE
  106. //
  107. Enum->StopAddress.AddressFamily = NetAddress->AddressFamily;
  108. Enum->StopAddress.NumBits = (USHORT) (AddrSize * BITS_IN_BYTE);
  109. AddrBits = Enum->StopAddress.AddrBits;
  110. for (i = 0; i < (NetAddress->NumBits / BITS_IN_BYTE); i++)
  111. {
  112. AddrBits[i] = NetAddress->AddrBits[i];
  113. }
  114. j = i;
  115. for (; i < AddrSize; i++)
  116. {
  117. AddrBits[i] = 0xFF;
  118. }
  119. if (j < AddrSize)
  120. {
  121. AddrBits[j] >>= (NetAddress->NumBits % BITS_IN_BYTE);
  122. AddrBits[j] |= NetAddress->AddrBits[j];
  123. }
  124. }
  125. try
  126. {
  127. InitializeCriticalSection(&Enum->EnumLock);
  128. }
  129. except(EXCEPTION_EXECUTE_HANDLER)
  130. {
  131. Status = GetLastError();
  132. break;
  133. }
  134. // Initialize the next destination context
  135. if (EnumFlags & (RTM_ENUM_NEXT | RTM_ENUM_RANGE))
  136. {
  137. CopyMemory(&Enum->NextDest,
  138. NetAddress,
  139. sizeof(RTM_NET_ADDRESS));
  140. }
  141. #if DBG_HDL
  142. //
  143. // Insert into list of handles opened by entity
  144. //
  145. ACQUIRE_OPEN_HANDLES_LOCK(Entity);
  146. InsertTailList(&Entity->OpenHandles, &Enum->EnumHeader.HandlesLE);
  147. RELEASE_OPEN_HANDLES_LOCK(Entity);
  148. #endif
  149. REFERENCE_ENTITY(Entity, ENUM_REF);
  150. //
  151. // Make a handle to the enum block and return
  152. //
  153. *RtmEnumHandle = MAKE_HANDLE_FROM_POINTER(Enum);
  154. return NO_ERROR;
  155. }
  156. while (FALSE);
  157. //
  158. // Something failed - undo work done and return status
  159. //
  160. #if DBG_HDL
  161. Enum->EnumHeader.ObjectHeader.TypeSign = DEST_ENUM_FREED;
  162. #endif
  163. FreeObject(Enum);
  164. *RtmEnumHandle = NULL;
  165. return Status;
  166. }
  167. DWORD
  168. WINAPI
  169. RtmGetEnumDests (
  170. IN RTM_ENTITY_HANDLE RtmRegHandle,
  171. IN RTM_ENUM_HANDLE EnumHandle,
  172. IN OUT PUINT NumDests,
  173. OUT PRTM_DEST_INFO DestInfos
  174. )
  175. /*++
  176. Routine Description:
  177. Gets the next set of destinations in the given enumeration
  178. on the route table.
  179. Arguments:
  180. RtmRegHandle - RTM registration handle for calling entity,
  181. EnumHandle - Handle to the destination enumeration,
  182. NumDests - Num. of DestInfo's in output is passed in,
  183. Num. of DestInfo's copied out is returned.
  184. DestInfos - Output buffer where destination info is retd.
  185. Return Value:
  186. Status of the operation
  187. --*/
  188. {
  189. PADDRFAM_INFO AddrFamInfo;
  190. PENTITY_INFO Entity;
  191. PDEST_ENUM Enum;
  192. LOOKUP_CONTEXT Context;
  193. PUCHAR EndofBuffer;
  194. UINT DestInfoSize;
  195. UINT DestsInput;
  196. UINT DestsCopied;
  197. UINT DestsLeft;
  198. PDEST_INFO Dest;
  199. PLOOKUP_LINKAGE*DestData;
  200. PROUTE_INFO Route;
  201. USHORT StopNumBits;
  202. PUCHAR StopKeyBits;
  203. UINT i, j;
  204. DWORD Status;
  205. //
  206. // Init the output params in case we fail validation
  207. //
  208. DestsInput = *NumDests;
  209. *NumDests = 0;
  210. //
  211. // Do some validation checks on the input params
  212. //
  213. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  214. VALIDATE_DEST_ENUM_HANDLE(EnumHandle, &Enum);
  215. AddrFamInfo = Entity->OwningAddrFamily;
  216. if ((DestsInput > AddrFamInfo->MaxHandlesInEnum) ||
  217. (DestsInput < 1))
  218. {
  219. return ERROR_INVALID_PARAMETER;
  220. }
  221. // Acquire lock to block other RtmGetEnumDests
  222. ACQUIRE_DEST_ENUM_LOCK(Enum);
  223. // Make sure enum is active at this point
  224. if (Enum->EnumDone)
  225. {
  226. RELEASE_DEST_ENUM_LOCK(Enum);
  227. return ERROR_NO_MORE_ITEMS;
  228. }
  229. //
  230. // Get the next set of destinations from table
  231. //
  232. // Initialize the lookup context before Enum
  233. ZeroMemory(&Context, sizeof(LOOKUP_CONTEXT));
  234. DestInfoSize = RTM_SIZE_OF_DEST_INFO(Enum->NumberOfViews);
  235. EndofBuffer = (PUCHAR) DestInfos + DestsInput * DestInfoSize;
  236. DestsLeft = DestsInput;
  237. DestsCopied = 0;
  238. ACQUIRE_ROUTE_TABLE_READ_LOCK(AddrFamInfo);
  239. do
  240. {
  241. // Use the end of the caller's buffer as temp space
  242. DestData = (PLOOKUP_LINKAGE *) (EndofBuffer -
  243. DestsLeft * sizeof(PLOOKUP_LINKAGE));
  244. if (Enum->EnumFlags & RTM_ENUM_RANGE)
  245. {
  246. StopNumBits = Enum->StopAddress.NumBits;
  247. StopKeyBits = Enum->StopAddress.AddrBits;
  248. }
  249. else
  250. {
  251. StopNumBits = 0;
  252. StopKeyBits = NULL;
  253. }
  254. Status = EnumOverTable(AddrFamInfo->RouteTable,
  255. &Enum->NextDest.NumBits,
  256. Enum->NextDest.AddrBits,
  257. &Context,
  258. StopNumBits,
  259. StopKeyBits,
  260. &DestsLeft,
  261. DestData);
  262. for (i = 0; i < DestsLeft; i++)
  263. {
  264. Dest = CONTAINING_RECORD(DestData[i], DEST_INFO, LookupLinkage);
  265. if ((Enum->TargetViews == RTM_VIEW_MASK_ANY) ||
  266. (Dest->BelongsToViews & Enum->TargetViews))
  267. {
  268. if (Enum->EnumFlags & RTM_ENUM_OWN_DESTS)
  269. {
  270. // Check if this dest is owned in any view by caller
  271. for (j = 0; j < AddrFamInfo->NumberOfViews; j++)
  272. {
  273. Route = Dest->ViewInfo[j].BestRoute;
  274. if (Route)
  275. {
  276. if (Route->RouteInfo.RouteOwner == RtmRegHandle)
  277. {
  278. break;
  279. }
  280. }
  281. }
  282. if (j == AddrFamInfo->NumberOfViews)
  283. {
  284. continue;
  285. }
  286. }
  287. //
  288. // Get the destination info from the dest
  289. //
  290. GetDestInfo(Entity,
  291. Dest,
  292. Enum->ProtocolId,
  293. Enum->TargetViews,
  294. DestInfos);
  295. DestsCopied++;
  296. DestInfos = (PRTM_DEST_INFO)(DestInfoSize + (PUCHAR)DestInfos);
  297. }
  298. }
  299. DestsLeft = DestsInput - DestsCopied;
  300. }
  301. while (SUCCESS(Status) && (DestsLeft > 0));
  302. //
  303. // We have no more dests, or we have filled output
  304. //
  305. ASSERT(!SUCCESS(Status) || ((PUCHAR) DestInfos == (PUCHAR) EndofBuffer));
  306. RELEASE_ROUTE_TABLE_READ_LOCK(AddrFamInfo);
  307. // If we are at end of the enum, make enum as done
  308. if (Status == ERROR_NO_MORE_ITEMS)
  309. {
  310. Enum->EnumDone = TRUE;
  311. }
  312. RELEASE_DEST_ENUM_LOCK(Enum);
  313. *NumDests = DestsCopied;
  314. return *NumDests ? NO_ERROR : ERROR_NO_MORE_ITEMS;
  315. }
  316. DWORD
  317. WINAPI
  318. RtmReleaseDests (
  319. IN RTM_ENTITY_HANDLE RtmRegHandle,
  320. IN UINT NumDests,
  321. IN PRTM_DEST_INFO DestInfos
  322. )
  323. /*++
  324. Routine Description:
  325. Release destination information obtained in other calls -
  326. like dest enumerations.
  327. Arguments:
  328. RtmRegHandle - RTM registration handle for calling entity,
  329. NumDests - Number of dest infos that are being released,
  330. DestInfos - Array of dest infos that are being released.
  331. Return Value:
  332. Status of the operation
  333. --*/
  334. {
  335. PENTITY_INFO Entity;
  336. UINT NumViews;
  337. UINT DestInfoSize;
  338. UINT i;
  339. DBG_VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  340. //
  341. // Get the size of each info in dest info array
  342. //
  343. NumViews = ((PRTM_DEST_INFO) DestInfos)->NumberOfViews;
  344. DestInfoSize = RTM_SIZE_OF_DEST_INFO(NumViews);
  345. //
  346. // Dereference each dest info in array
  347. //
  348. for (i = 0; i < NumDests; i++)
  349. {
  350. RtmReleaseDestInfo(RtmRegHandle, DestInfos);
  351. DestInfos = (PRTM_DEST_INFO)(DestInfoSize + (PUCHAR)DestInfos);
  352. }
  353. return NO_ERROR;
  354. }
  355. DWORD
  356. WINAPI
  357. RtmCreateRouteEnum (
  358. IN RTM_ENTITY_HANDLE RtmRegHandle,
  359. IN RTM_DEST_HANDLE DestHandle OPTIONAL,
  360. IN RTM_VIEW_SET TargetViews,
  361. IN RTM_ENUM_FLAGS EnumFlags,
  362. IN PRTM_NET_ADDRESS StartDest OPTIONAL,
  363. IN RTM_MATCH_FLAGS MatchingFlags,
  364. IN PRTM_ROUTE_INFO CriteriaRoute OPTIONAL,
  365. IN ULONG CriteriaInterface OPTIONAL,
  366. OUT PRTM_ENUM_HANDLE RtmEnumHandle
  367. )
  368. /*++
  369. Routine Description:
  370. Creates a enumeration over the routes on a particular dest
  371. in the route table. If the dest is NULL, an enumeration is
  372. created over the whole route table.
  373. If matching flags are specified, only routes that match the
  374. criteria are returned.
  375. Arguments:
  376. RtmRegHandle - RTM registration handle for calling entity,
  377. DestHandle - The destination whose routes we are enum'ing,
  378. Or NULL if we are enum'ing over all dests.
  379. TargetViews - Set of views in which the enumeration is done,
  380. EnumFlags - Flags that control the routes retd in enum,
  381. MatchingFlags - Indicates the elements of the route to match,
  382. CriteriaRoute - Values to match each route in the enum,
  383. CritInterface - Interface on which routes should fall on,
  384. RtmEnumHandle - Handle to this enumeration, which is used
  385. in subsequent calls to get routes, and so on.
  386. Return Value:
  387. Status of the operation
  388. --*/
  389. {
  390. PADDRFAM_INFO AddrFamInfo;
  391. PENTITY_INFO Entity;
  392. PROUTE_ENUM Enum;
  393. PDEST_INFO Dest;
  394. BOOL LockInited;
  395. ULONG NumBytes;
  396. DWORD Status;
  397. //
  398. // Do some validation checks on the input params
  399. //
  400. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  401. AddrFamInfo = Entity->OwningAddrFamily;
  402. #if WRN
  403. Dest = NULL;
  404. #endif
  405. if (ARGUMENT_PRESENT(DestHandle))
  406. {
  407. // StartDest doesnt apply if enum'ing a dest
  408. if (ARGUMENT_PRESENT(StartDest))
  409. {
  410. return ERROR_INVALID_PARAMETER;
  411. }
  412. VALIDATE_DEST_HANDLE(DestHandle, &Dest);
  413. }
  414. // If we have matching flags, we need corr. route
  415. if (MatchingFlags & ~RTM_MATCH_INTERFACE)
  416. {
  417. if (!ARGUMENT_PRESENT(CriteriaRoute))
  418. {
  419. return ERROR_INVALID_PARAMETER;
  420. }
  421. }
  422. //
  423. // Is he interested in any non-supported views ?
  424. //
  425. if (TargetViews & ~AddrFamInfo->ViewsSupported)
  426. {
  427. return ERROR_NOT_SUPPORTED;
  428. }
  429. //
  430. // Create and initialize a route enumeration block
  431. //
  432. Enum = (PROUTE_ENUM) AllocNZeroObject(sizeof(ROUTE_ENUM));
  433. if (Enum == NULL)
  434. {
  435. return ERROR_NOT_ENOUGH_MEMORY;
  436. }
  437. LockInited = FALSE;
  438. #if WRN
  439. Status = ERROR_GEN_FAILURE;
  440. #endif
  441. do
  442. {
  443. #if DBG_HDL
  444. Enum->EnumHeader.ObjectHeader.TypeSign = ROUTE_ENUM_ALLOC;
  445. #endif
  446. Enum->EnumHeader.HandleType = ROUTE_ENUM_TYPE;
  447. Enum->TargetViews = TargetViews;
  448. Enum->EnumFlags = EnumFlags;
  449. if (MatchingFlags)
  450. {
  451. Enum->MatchFlags = MatchingFlags;
  452. if (MatchingFlags & ~RTM_MATCH_INTERFACE)
  453. {
  454. NumBytes = sizeof(RTM_ROUTE_INFO) +
  455. (AddrFamInfo->MaxNextHopsInRoute - 1) *
  456. sizeof(RTM_NEXTHOP_HANDLE);
  457. Enum->CriteriaRoute = AllocMemory(NumBytes);
  458. if (Enum->CriteriaRoute == NULL)
  459. {
  460. break;
  461. }
  462. CopyMemory(Enum->CriteriaRoute, CriteriaRoute, NumBytes);
  463. }
  464. Enum->CriteriaInterface = CriteriaInterface;
  465. }
  466. //
  467. // Initialize the lock to serialize enum requests
  468. //
  469. try
  470. {
  471. InitializeCriticalSection(&Enum->EnumLock);
  472. }
  473. except(EXCEPTION_EXECUTE_HANDLER)
  474. {
  475. Status = GetLastError();
  476. break;
  477. }
  478. LockInited = TRUE;
  479. //
  480. // Are we enumerating routes on all destinations ?
  481. //
  482. if (!ARGUMENT_PRESENT(DestHandle))
  483. {
  484. //
  485. // Create a temp dest info structure for enum
  486. //
  487. Enum->DestInfo = AllocDestInfo(AddrFamInfo->NumberOfViews);
  488. if (Enum->DestInfo == NULL)
  489. {
  490. Status = ERROR_NOT_ENOUGH_MEMORY;
  491. break;
  492. }
  493. //
  494. // Open a dest enumeration to get all dests
  495. //
  496. Status = RtmCreateDestEnum(RtmRegHandle,
  497. TargetViews,
  498. EnumFlags,
  499. StartDest,
  500. RTM_BEST_PROTOCOL,
  501. &Enum->DestEnum);
  502. if (!SUCCESS(Status))
  503. {
  504. break;
  505. }
  506. }
  507. else
  508. {
  509. //
  510. // Ref dest whose routes we are enum'ing
  511. //
  512. Enum->Destination = Dest;
  513. REFERENCE_DEST(Dest, ENUM_REF);
  514. }
  515. #if DBG_HDL
  516. //
  517. // Insert into list of handles opened by entity
  518. //
  519. ACQUIRE_OPEN_HANDLES_LOCK(Entity);
  520. InsertTailList(&Entity->OpenHandles, &Enum->EnumHeader.HandlesLE);
  521. RELEASE_OPEN_HANDLES_LOCK(Entity);
  522. #endif
  523. REFERENCE_ENTITY(Entity, ENUM_REF);
  524. //
  525. // Make a handle to the enum block and return
  526. //
  527. *RtmEnumHandle = MAKE_HANDLE_FROM_POINTER(Enum);
  528. return NO_ERROR;
  529. }
  530. while (FALSE);
  531. //
  532. // Something failed - undo work done and return status
  533. //
  534. if (Enum->DestInfo)
  535. {
  536. FreeMemory(Enum->DestInfo);
  537. }
  538. if (LockInited)
  539. {
  540. DeleteCriticalSection(&Enum->EnumLock);
  541. }
  542. if (Enum->CriteriaRoute)
  543. {
  544. FreeMemory(Enum->CriteriaRoute);
  545. }
  546. FreeObject(Enum);
  547. *RtmEnumHandle = NULL;
  548. return Status;
  549. }
  550. DWORD
  551. WINAPI
  552. RtmGetEnumRoutes (
  553. IN RTM_ENTITY_HANDLE RtmRegHandle,
  554. IN RTM_ENUM_HANDLE EnumHandle,
  555. IN OUT PUINT NumRoutes,
  556. OUT PRTM_ROUTE_HANDLE RouteHandles
  557. )
  558. /*++
  559. Routine Description:
  560. Gets the next set of routes in the given enumeration on the
  561. route table.
  562. Arguments:
  563. RtmRegHandle - RTM registration handle for calling entity,
  564. EnumHandle - Handle to the route enumeration,
  565. NumRoutes - Max. number of routes to fill is passed in,
  566. Num. of routes actually copied is returned.
  567. RouteHandles - Output buffer where route handles are retd.
  568. Return Value:
  569. Status of the operation
  570. --*/
  571. {
  572. PADDRFAM_INFO AddrFamInfo;
  573. PENTITY_INFO Entity;
  574. PROUTE_ENUM Enum;
  575. PDEST_INFO Dest;
  576. PROUTE_INFO Route;
  577. PROUTE_INFO *NextRoute;
  578. UINT NumDests;
  579. UINT RoutesInput;
  580. UINT RoutesCopied;
  581. UINT RoutesOnDest;
  582. UINT RoutesToCopy;
  583. PLIST_ENTRY p;
  584. UINT i;
  585. DWORD Status;
  586. //
  587. // Init the output params in case we fail validation
  588. //
  589. RoutesInput = *NumRoutes;
  590. *NumRoutes = 0;
  591. //
  592. // Do some validation checks on the input params
  593. //
  594. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  595. VALIDATE_ROUTE_ENUM_HANDLE(EnumHandle, &Enum);
  596. AddrFamInfo = Entity->OwningAddrFamily;
  597. if ((RoutesInput > AddrFamInfo->MaxHandlesInEnum) ||
  598. (RoutesInput < 1))
  599. {
  600. return ERROR_INVALID_PARAMETER;
  601. }
  602. // Acquire lock to block other RtmGetEnumRoutes
  603. ACQUIRE_ROUTE_ENUM_LOCK(Enum);
  604. // Make sure enum is active at this point
  605. if (Enum->EnumDone)
  606. {
  607. RELEASE_ROUTE_ENUM_LOCK(Enum);
  608. return ERROR_NO_MORE_ITEMS;
  609. }
  610. //
  611. // Get more routes until you satisfy the request
  612. //
  613. Status = NO_ERROR;
  614. RoutesCopied = 0;
  615. do
  616. {
  617. //
  618. // Do we have any routes in current snapshot ?
  619. //
  620. RoutesOnDest = Enum->NumRoutes - Enum->NextRoute;
  621. if (RoutesOnDest == 0)
  622. {
  623. //
  624. // Destination value in the enum is not set if
  625. //
  626. // 1. we are doing an enum over the whole
  627. // table, and
  628. //
  629. // 2. we did not run out of memory in the
  630. // previous attempt to take a snapshot
  631. // ( if we did make an attempt before )
  632. //
  633. if (Enum->Destination == NULL)
  634. {
  635. ASSERT(Enum->DestEnum);
  636. //
  637. // Get the next destination in the table
  638. //
  639. NumDests = 1;
  640. Status = RtmGetEnumDests(RtmRegHandle,
  641. Enum->DestEnum,
  642. &NumDests,
  643. Enum->DestInfo);
  644. if (NumDests < 1)
  645. {
  646. break;
  647. }
  648. Dest = DEST_FROM_HANDLE(Enum->DestInfo->DestHandle);
  649. Enum->Destination = Dest;
  650. REFERENCE_DEST(Dest, ENUM_REF);
  651. RtmReleaseDestInfo(RtmRegHandle,
  652. Enum->DestInfo);
  653. }
  654. else
  655. {
  656. Dest = Enum->Destination;
  657. }
  658. ASSERT(Enum->Destination != NULL);
  659. //
  660. // Allocate memory to hold snapshot of routes
  661. //
  662. ACQUIRE_DEST_READ_LOCK(Dest);
  663. if (Enum->MaxRoutes < Dest->NumRoutes)
  664. {
  665. //
  666. // Re-adjust the size of snapshot buffer
  667. //
  668. if (Enum->RoutesOnDest)
  669. {
  670. FreeMemory(Enum->RoutesOnDest);
  671. }
  672. Enum->RoutesOnDest = (PROUTE_INFO *)
  673. AllocNZeroMemory(Dest->NumRoutes *
  674. sizeof(PROUTE_INFO));
  675. if (Enum->RoutesOnDest == NULL)
  676. {
  677. RELEASE_DEST_READ_LOCK(Dest);
  678. Enum->MaxRoutes = 0;
  679. Enum->NumRoutes = 0;
  680. Enum->NextRoute = 0;
  681. Status = ERROR_NOT_ENOUGH_MEMORY;
  682. break;
  683. }
  684. Enum->MaxRoutes = Dest->NumRoutes;
  685. }
  686. //
  687. // Get snapshot of all routes on this dest
  688. //
  689. Enum->NumRoutes = Enum->NextRoute = 0;
  690. for (p = Dest->RouteList.Flink; p != &Dest->RouteList; p= p->Flink)
  691. {
  692. Route = CONTAINING_RECORD(p, ROUTE_INFO, DestLE);
  693. //
  694. // Does this route belong one of interesting views ?
  695. //
  696. if ((Enum->TargetViews == RTM_VIEW_MASK_ANY) ||
  697. (Route->RouteInfo.BelongsToViews & Enum->TargetViews))
  698. {
  699. if (Enum->EnumFlags & RTM_ENUM_OWN_ROUTES)
  700. {
  701. // Check if this route is owned by the caller
  702. if (Route->RouteInfo.RouteOwner != RtmRegHandle)
  703. {
  704. continue;
  705. }
  706. }
  707. // Does this route match the enumeration criteria ?
  708. if (Enum->MatchFlags &&
  709. !MatchRouteWithCriteria(Route,
  710. Enum->MatchFlags,
  711. Enum->CriteriaRoute,
  712. Enum->CriteriaInterface))
  713. {
  714. continue;
  715. }
  716. REFERENCE_ROUTE(Route, ENUM_REF);
  717. //
  718. // Reference the route and copy the handle to output
  719. //
  720. Enum->RoutesOnDest[Enum->NumRoutes++] = Route;
  721. }
  722. }
  723. ASSERT(Enum->NumRoutes <= Dest->NumRoutes);
  724. RELEASE_DEST_READ_LOCK(Dest);
  725. //
  726. // If we are enum'ing the whole table, we do
  727. // not need the dest whose snapshot is taken
  728. //
  729. if (Enum->DestEnum)
  730. {
  731. Enum->Destination = NULL;
  732. DEREFERENCE_DEST(Dest, ENUM_REF);
  733. }
  734. // Adjust the number of routes on the dest
  735. RoutesOnDest = Enum->NumRoutes - Enum->NextRoute;
  736. }
  737. //
  738. // Copy routes to output from the current snapshot
  739. //
  740. if (RoutesOnDest)
  741. {
  742. RoutesToCopy = RoutesInput - RoutesCopied;
  743. if (RoutesToCopy > RoutesOnDest)
  744. {
  745. RoutesToCopy = RoutesOnDest;
  746. }
  747. NextRoute = &Enum->RoutesOnDest[Enum->NextRoute];
  748. for (i = 0; i < RoutesToCopy; i++)
  749. {
  750. #if DBG_REF
  751. REFERENCE_ROUTE(*NextRoute, HANDLE_REF);
  752. DEREFERENCE_ROUTE(*NextRoute, ENUM_REF);
  753. #endif
  754. RouteHandles[RoutesCopied++] =
  755. MAKE_HANDLE_FROM_POINTER(*NextRoute++);
  756. }
  757. Enum->NextRoute += RoutesToCopy;
  758. RoutesOnDest -= RoutesToCopy;
  759. }
  760. //
  761. // Are we done with all the routes in snapshot ?
  762. //
  763. if (RoutesOnDest == 0)
  764. {
  765. //
  766. // If we are enum'ing a single dest, we are done
  767. //
  768. if (Enum->DestEnum == NULL)
  769. {
  770. Status = ERROR_NO_MORE_ITEMS;
  771. break;
  772. }
  773. }
  774. }
  775. while (SUCCESS(Status) && (RoutesCopied < RoutesInput));
  776. // If we are at end of the enum, make enum as done
  777. if ((Status == ERROR_NO_MORE_ITEMS) && (RoutesOnDest == 0))
  778. {
  779. Enum->EnumDone = TRUE;
  780. }
  781. RELEASE_ROUTE_ENUM_LOCK(Enum);
  782. //
  783. // Update output to reflect number of routes copied
  784. //
  785. *NumRoutes = RoutesCopied;
  786. return *NumRoutes ? NO_ERROR : ERROR_NO_MORE_ITEMS;
  787. }
  788. BOOL
  789. MatchRouteWithCriteria (
  790. IN PROUTE_INFO Route,
  791. IN RTM_MATCH_FLAGS MatchingFlags,
  792. IN PRTM_ROUTE_INFO CriteriaRouteInfo,
  793. IN ULONG CriteriaInterface
  794. )
  795. /*++
  796. Routine Description:
  797. Matches a route with the input criteria given by input flags
  798. and the route to match.
  799. Arguments:
  800. Route - Route that we are matching criteria with,
  801. MatchingFlags - Flags that indicate which fields to match,
  802. CriteriaRouteInfo - Route info that specifies match criteria,
  803. CriteriaInterface - Interface to match if MATCH_INTERFACE is set.
  804. Return Value:
  805. TRUE if route matches criteria, FALSE if not
  806. --*/
  807. {
  808. PRTM_NEXTHOP_HANDLE NextHops;
  809. PNEXTHOP_INFO NextHop;
  810. UINT NumNHops;
  811. UINT i;
  812. //
  813. // Try matching the route owner if flags say so
  814. //
  815. if (MatchingFlags & RTM_MATCH_OWNER)
  816. {
  817. if (Route->RouteInfo.RouteOwner != CriteriaRouteInfo->RouteOwner)
  818. {
  819. return FALSE;
  820. }
  821. }
  822. //
  823. // Try matching the neighbour if flags say so
  824. //
  825. if (MatchingFlags & RTM_MATCH_NEIGHBOUR)
  826. {
  827. if (Route->RouteInfo.Neighbour != CriteriaRouteInfo->Neighbour)
  828. {
  829. return FALSE;
  830. }
  831. }
  832. //
  833. // Try matching the preference if flags say so
  834. //
  835. if (MatchingFlags & RTM_MATCH_PREF)
  836. {
  837. if (!IsPrefEqual(&Route->RouteInfo, CriteriaRouteInfo))
  838. {
  839. return FALSE;
  840. }
  841. }
  842. //
  843. // Try matching the interface if flags say so
  844. //
  845. if (MatchingFlags & RTM_MATCH_INTERFACE)
  846. {
  847. NumNHops = Route->RouteInfo.NextHopsList.NumNextHops;
  848. NextHops = Route->RouteInfo.NextHopsList.NextHops;
  849. for (i = 0; i < NumNHops; i++)
  850. {
  851. NextHop = NEXTHOP_FROM_HANDLE(NextHops[i]);
  852. if (NextHop->NextHopInfo.InterfaceIndex == CriteriaInterface)
  853. {
  854. break;
  855. }
  856. }
  857. if (i == NumNHops)
  858. {
  859. return FALSE;
  860. }
  861. }
  862. //
  863. // Try matching the nexthop if flags say so
  864. //
  865. if (MatchingFlags & RTM_MATCH_NEXTHOP)
  866. {
  867. NumNHops = Route->RouteInfo.NextHopsList.NumNextHops;
  868. NextHops = Route->RouteInfo.NextHopsList.NextHops;
  869. ASSERT(CriteriaRouteInfo->NextHopsList.NumNextHops == 1);
  870. for (i = 0; i < NumNHops; i++)
  871. {
  872. if (NextHops[i] == CriteriaRouteInfo->NextHopsList.NextHops[0])
  873. {
  874. break;
  875. }
  876. }
  877. if (i == NumNHops)
  878. {
  879. return FALSE;
  880. }
  881. }
  882. return TRUE;
  883. }
  884. DWORD
  885. WINAPI
  886. RtmReleaseRoutes (
  887. IN RTM_ENTITY_HANDLE RtmRegHandle,
  888. IN UINT NumRoutes,
  889. IN PRTM_ROUTE_HANDLE RouteHandles
  890. )
  891. /*++
  892. Routine Description:
  893. Release (also called de-reference) handles to routes
  894. obtained in other RTM calls like route enumerations.
  895. Arguments:
  896. RtmRegHandle - RTM registration handle for calling entity,
  897. NumRoutes - Number of handles that are being released,
  898. RouteHandles - An array of handles that are being released.
  899. Return Value:
  900. Status of the operation
  901. --*/
  902. {
  903. PENTITY_INFO Entity;
  904. PROUTE_INFO Route;
  905. UINT i;
  906. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  907. //
  908. // Dereference each route handle in array
  909. //
  910. for (i = 0; i < NumRoutes; i++)
  911. {
  912. Route = ROUTE_FROM_HANDLE(RouteHandles[i]);
  913. DEREFERENCE_ROUTE(Route, HANDLE_REF);
  914. }
  915. return NO_ERROR;
  916. }
  917. DWORD
  918. WINAPI
  919. RtmCreateNextHopEnum (
  920. IN RTM_ENTITY_HANDLE RtmRegHandle,
  921. IN RTM_ENUM_FLAGS EnumFlags,
  922. IN PRTM_NET_ADDRESS NetAddress,
  923. OUT PRTM_ENUM_HANDLE RtmEnumHandle
  924. )
  925. /*++
  926. Routine Description:
  927. Creates a enumeration over all the next-hops in table.
  928. Arguments:
  929. RtmRegHandle - RTM registration handle for calling entity,
  930. EnumFlags - Flags that control the nexthops retd in enum,
  931. NetAddress - Start and/or stop address of the enumeration,
  932. [ See a description of RTM_ENUM_FLAGS ...]
  933. RtmEnumHandle - Handle to this enumeration, which is used in
  934. subsequent calls to get next-hops, and so on.
  935. Return Value:
  936. Status of the operation
  937. --*/
  938. {
  939. PENTITY_INFO Entity;
  940. PNEXTHOP_ENUM Enum;
  941. PUCHAR AddrBits;
  942. UINT AddrSize;
  943. UINT i, j;
  944. DWORD Status;
  945. //
  946. // Do some validation checks on the input params
  947. //
  948. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  949. if ((EnumFlags & RTM_ENUM_NEXT) && (EnumFlags & RTM_ENUM_RANGE))
  950. {
  951. return ERROR_INVALID_PARAMETER;
  952. }
  953. if (EnumFlags & (RTM_ENUM_NEXT | RTM_ENUM_RANGE))
  954. {
  955. if (!NetAddress)
  956. {
  957. return ERROR_INVALID_PARAMETER;
  958. }
  959. }
  960. //
  961. // Create and initialize an nexthop enumeration block
  962. //
  963. Enum = (PNEXTHOP_ENUM) AllocNZeroObject(sizeof(NEXTHOP_ENUM));
  964. if (Enum == NULL)
  965. {
  966. return ERROR_NOT_ENOUGH_MEMORY;
  967. }
  968. do
  969. {
  970. #if DBG_HDL
  971. Enum->EnumHeader.ObjectHeader.TypeSign = NEXTHOP_ENUM_ALLOC;
  972. #endif
  973. Enum->EnumHeader.HandleType = NEXTHOP_ENUM_TYPE;
  974. Enum->EnumFlags = EnumFlags;
  975. #if DBG
  976. // Initialize the first address in the enum
  977. if (Enum->EnumFlags & (RTM_ENUM_NEXT | RTM_ENUM_RANGE))
  978. {
  979. CopyMemory(&Enum->StartAddress,
  980. NetAddress,
  981. sizeof(RTM_NET_ADDRESS));
  982. }
  983. #endif
  984. AddrSize = Entity->OwningAddrFamily->AddressSize;
  985. //
  986. // Initialize the last address in the enum
  987. //
  988. if (Enum->EnumFlags & RTM_ENUM_RANGE)
  989. {
  990. //
  991. // Convert the NetAddress a.b/n -> a.b.FF.FF/N where N = ADDRSIZE
  992. //
  993. Enum->StopAddress.AddressFamily = NetAddress->AddressFamily;
  994. Enum->StopAddress.NumBits = (USHORT) (AddrSize * BITS_IN_BYTE);
  995. AddrBits = Enum->StopAddress.AddrBits;
  996. for (i = 0; i < (NetAddress->NumBits / BITS_IN_BYTE); i++)
  997. {
  998. AddrBits[i] = NetAddress->AddrBits[i];
  999. }
  1000. j = i;
  1001. for (; i < AddrSize; i++)
  1002. {
  1003. AddrBits[i] = 0xFF;
  1004. }
  1005. if (j < AddrSize)
  1006. {
  1007. AddrBits[j] >>= (NetAddress->NumBits % BITS_IN_BYTE);
  1008. AddrBits[j] |= NetAddress->AddrBits[j];
  1009. }
  1010. }
  1011. try
  1012. {
  1013. InitializeCriticalSection(&Enum->EnumLock);
  1014. }
  1015. except(EXCEPTION_EXECUTE_HANDLER)
  1016. {
  1017. Status = GetLastError();
  1018. break;
  1019. }
  1020. // Initialize the next 'nexthop' context
  1021. if (NetAddress)
  1022. {
  1023. CopyMemory(&Enum->NextAddress,
  1024. NetAddress,
  1025. sizeof(RTM_NET_ADDRESS));
  1026. }
  1027. Enum->NextIfIndex = START_IF_INDEX;
  1028. #if DBG_HDL
  1029. //
  1030. // Insert into list of handles opened by entity
  1031. //
  1032. ACQUIRE_OPEN_HANDLES_LOCK(Entity);
  1033. InsertTailList(&Entity->OpenHandles, &Enum->EnumHeader.HandlesLE);
  1034. RELEASE_OPEN_HANDLES_LOCK(Entity);
  1035. #endif
  1036. REFERENCE_ENTITY(Entity, ENUM_REF);
  1037. //
  1038. // Make a handle to the enum block and return
  1039. //
  1040. *RtmEnumHandle = MAKE_HANDLE_FROM_POINTER(Enum);
  1041. return NO_ERROR;
  1042. }
  1043. while (FALSE);
  1044. //
  1045. // Something failed - undo work done and return status
  1046. //
  1047. #if DBG_HDL
  1048. Enum->EnumHeader.ObjectHeader.TypeSign = NEXTHOP_ENUM_FREED;
  1049. #endif
  1050. FreeObject(Enum);
  1051. *RtmEnumHandle = NULL;
  1052. return Status;
  1053. }
  1054. DWORD
  1055. WINAPI
  1056. RtmGetEnumNextHops (
  1057. IN RTM_ENTITY_HANDLE RtmRegHandle,
  1058. IN RTM_ENUM_HANDLE EnumHandle,
  1059. IN OUT PUINT NumNextHops,
  1060. OUT PRTM_NEXTHOP_HANDLE NextHopHandles
  1061. )
  1062. /*++
  1063. Routine Description:
  1064. Gets the next set of next-hops in the given enumeration
  1065. on the next-hop table.
  1066. Arguments:
  1067. RtmRegHandle - RTM registration handle for calling entity,
  1068. EnumHandle - Handle to the next-hop enumeration,
  1069. NumNextHops - Num. of next-hops in output is passed in,
  1070. Num. of next-hops copied out is returned.
  1071. NextHopHandles - Output buffer where next-hop handles are retd.
  1072. Return Value:
  1073. Status of the operation
  1074. --*/
  1075. {
  1076. PADDRFAM_INFO AddrFamInfo;
  1077. PENTITY_INFO Entity;
  1078. PNEXTHOP_ENUM Enum;
  1079. LOOKUP_CONTEXT Context;
  1080. PNEXTHOP_LIST HopList;
  1081. PNEXTHOP_INFO NextHop;
  1082. PLOOKUP_LINKAGE NextHopData;
  1083. PLIST_ENTRY NextHops, p;
  1084. UINT NextHopsInput;
  1085. UINT NextHopsCopied;
  1086. UINT NumHopLists;
  1087. USHORT StopNumBits;
  1088. PUCHAR StopKeyBits;
  1089. DWORD Status;
  1090. //
  1091. // Init the output params in case we fail validation
  1092. //
  1093. NextHopsInput = *NumNextHops;
  1094. *NumNextHops = 0;
  1095. //
  1096. // Do some validation checks on the input params
  1097. //
  1098. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  1099. VALIDATE_NEXTHOP_ENUM_HANDLE(EnumHandle, &Enum);
  1100. AddrFamInfo = Entity->OwningAddrFamily;
  1101. if ((NextHopsInput > AddrFamInfo->MaxHandlesInEnum) ||
  1102. (NextHopsInput < 1))
  1103. {
  1104. return ERROR_INVALID_PARAMETER;
  1105. }
  1106. // Acquire lock to block other RtmGetEnumNextHops
  1107. ACQUIRE_NEXTHOP_ENUM_LOCK(Enum);
  1108. // Make sure enum is active at this point
  1109. if (Enum->EnumDone)
  1110. {
  1111. RELEASE_NEXTHOP_ENUM_LOCK(Enum);
  1112. return ERROR_NO_MORE_ITEMS;
  1113. }
  1114. // Initialize the lookup context before Enum
  1115. ZeroMemory(&Context, sizeof(LOOKUP_CONTEXT));
  1116. if (Enum->EnumFlags & RTM_ENUM_RANGE)
  1117. {
  1118. StopNumBits = Enum->StopAddress.NumBits;
  1119. StopKeyBits = Enum->StopAddress.AddrBits;
  1120. }
  1121. else
  1122. {
  1123. StopNumBits = 0;
  1124. StopKeyBits = NULL;
  1125. }
  1126. NextHopsCopied = 0;
  1127. ACQUIRE_NHOP_TABLE_READ_LOCK(Entity);
  1128. do
  1129. {
  1130. //
  1131. // Get the next list of next-hops from table
  1132. //
  1133. NumHopLists = 1;
  1134. Status = EnumOverTable(Entity->NextHopTable,
  1135. &Enum->NextAddress.NumBits,
  1136. Enum->NextAddress.AddrBits,
  1137. &Context,
  1138. StopNumBits,
  1139. StopKeyBits,
  1140. &NumHopLists,
  1141. &NextHopData);
  1142. if (NumHopLists < 1)
  1143. {
  1144. break;
  1145. }
  1146. HopList = CONTAINING_RECORD(NextHopData, NEXTHOP_LIST, LookupLinkage);
  1147. NextHops = &HopList->NextHopsList;
  1148. // Skip all the interface indices we have seen
  1149. for (p = NextHops->Flink; p != NextHops; p = p->Flink)
  1150. {
  1151. NextHop = CONTAINING_RECORD(p, NEXTHOP_INFO, NextHopsLE);
  1152. if (NextHop->NextHopInfo.InterfaceIndex <= Enum->NextIfIndex)
  1153. {
  1154. break;
  1155. }
  1156. }
  1157. #if WRN
  1158. NextHop = NULL;
  1159. #endif
  1160. // Copy the rest of the next-hops in the list
  1161. for ( ; p != NextHops; p = p->Flink)
  1162. {
  1163. NextHop = CONTAINING_RECORD(p, NEXTHOP_INFO, NextHopsLE);
  1164. if (NextHopsCopied == NextHopsInput)
  1165. {
  1166. break;
  1167. }
  1168. REFERENCE_NEXTHOP(NextHop, HANDLE_REF);
  1169. NextHopHandles[NextHopsCopied++]=MAKE_HANDLE_FROM_POINTER(NextHop);
  1170. }
  1171. // If we are going to the next list, reset if index
  1172. if (p == NextHops)
  1173. {
  1174. Enum->NextIfIndex = START_IF_INDEX;
  1175. }
  1176. else
  1177. {
  1178. // We have copied enough for this call
  1179. ASSERT(NextHopsCopied == NextHopsInput);
  1180. //
  1181. // We still have next-hops on the list,
  1182. // set back the next 'nexthop address'
  1183. //
  1184. Enum->NextAddress = NextHop->NextHopInfo.NextHopAddress;
  1185. Enum->NextIfIndex = NextHop->NextHopInfo.InterfaceIndex;
  1186. Status = NO_ERROR;
  1187. }
  1188. }
  1189. while (SUCCESS(Status) && (NextHopsCopied < NextHopsInput));
  1190. RELEASE_NHOP_TABLE_READ_LOCK(Entity);
  1191. // If we are at end of the enum, make enum as done
  1192. if (Status == ERROR_NO_MORE_ITEMS)
  1193. {
  1194. Enum->EnumDone = TRUE;
  1195. }
  1196. RELEASE_NEXTHOP_ENUM_LOCK(Enum);
  1197. *NumNextHops = NextHopsCopied;
  1198. return *NumNextHops ? NO_ERROR : ERROR_NO_MORE_ITEMS;
  1199. }
  1200. DWORD
  1201. WINAPI
  1202. RtmReleaseNextHops (
  1203. IN RTM_ENTITY_HANDLE RtmRegHandle,
  1204. IN UINT NumNextHops,
  1205. IN PRTM_NEXTHOP_HANDLE NextHopHandles
  1206. )
  1207. /*++
  1208. Routine Description:
  1209. Release (also called de-reference) handles to next-hops
  1210. obtained in other RTM calls like next hop enumerations.
  1211. Arguments:
  1212. RtmRegHandle - RTM registration handle for calling entity,
  1213. NumNextHops - Number of handles that are being released,
  1214. NextHopHandles - An array of handles that are being released.
  1215. Return Value:
  1216. Status of the operation
  1217. --*/
  1218. {
  1219. PENTITY_INFO Entity;
  1220. PNEXTHOP_INFO NextHop;
  1221. UINT i;
  1222. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  1223. //
  1224. // Dereference each nexthop handle in array
  1225. //
  1226. for (i = 0; i < NumNextHops; i++)
  1227. {
  1228. NextHop = NEXTHOP_FROM_HANDLE(NextHopHandles[i]);
  1229. DEREFERENCE_NEXTHOP(NextHop, HANDLE_REF);
  1230. }
  1231. return NO_ERROR;
  1232. }
  1233. DWORD
  1234. WINAPI
  1235. RtmDeleteEnumHandle (
  1236. IN RTM_ENTITY_HANDLE RtmRegHandle,
  1237. IN RTM_ENUM_HANDLE EnumHandle
  1238. )
  1239. /*++
  1240. Routine Description:
  1241. Deletes the enumeration handle and frees all resources
  1242. allocated to the enumeration.
  1243. Arguments:
  1244. RtmRegHandle - RTM registration handle for calling entity,
  1245. EnumHandle - Handle to the enumeration.
  1246. Return Value:
  1247. Status of the operation
  1248. --*/
  1249. {
  1250. PENTITY_INFO Entity;
  1251. POPEN_HEADER Enum;
  1252. PROUTE_ENUM RouteEnum;
  1253. UCHAR HandleType;
  1254. UINT i;
  1255. VALIDATE_ENTITY_HANDLE(RtmRegHandle, &Entity);
  1256. //
  1257. // Figure out the enum type and act accordingly
  1258. //
  1259. HandleType = GET_ENUM_TYPE(EnumHandle, &Enum);
  1260. #if DBG
  1261. VALIDATE_OBJECT_HANDLE(EnumHandle, HandleType, &Enum);
  1262. #endif
  1263. switch (HandleType)
  1264. {
  1265. case DEST_ENUM_TYPE:
  1266. DeleteCriticalSection(&((PDEST_ENUM)Enum)->EnumLock);
  1267. break;
  1268. case ROUTE_ENUM_TYPE:
  1269. RouteEnum = (PROUTE_ENUM) Enum;
  1270. // Dereference the destination that we are enum'ing
  1271. if (RouteEnum->Destination)
  1272. {
  1273. DEREFERENCE_DEST(RouteEnum->Destination, ENUM_REF);
  1274. }
  1275. //
  1276. // Close the associated destination enum & resources
  1277. //
  1278. if (RouteEnum->DestInfo)
  1279. {
  1280. FreeMemory(RouteEnum->DestInfo);
  1281. }
  1282. if (RouteEnum->DestEnum)
  1283. {
  1284. RtmDeleteEnumHandle(RtmRegHandle, RouteEnum->DestEnum);
  1285. }
  1286. // Dereference all routes in the enum's snapshot
  1287. for (i = RouteEnum->NextRoute; i < RouteEnum->NumRoutes; i++)
  1288. {
  1289. DEREFERENCE_ROUTE(RouteEnum->RoutesOnDest[i], ENUM_REF);
  1290. }
  1291. // Free memory associated with criteria matching
  1292. if (RouteEnum->CriteriaRoute)
  1293. {
  1294. FreeMemory(RouteEnum->CriteriaRoute);
  1295. }
  1296. // Free memory allocated for the enum's snapshot
  1297. FreeMemory(RouteEnum->RoutesOnDest);
  1298. DeleteCriticalSection(&RouteEnum->EnumLock);
  1299. break;
  1300. case NEXTHOP_ENUM_TYPE:
  1301. DeleteCriticalSection(&((PNEXTHOP_ENUM)Enum)->EnumLock);
  1302. break;
  1303. case LIST_ENUM_TYPE:
  1304. //
  1305. // Remove the enum's marker route from route list
  1306. //
  1307. ACQUIRE_ROUTE_LISTS_WRITE_LOCK(Entity);
  1308. RemoveEntryList(&((PLIST_ENUM)Enum)->MarkerRoute.RouteListLE);
  1309. RELEASE_ROUTE_LISTS_WRITE_LOCK(Entity);
  1310. break;
  1311. default:
  1312. return ERROR_INVALID_HANDLE;
  1313. }
  1314. #if DBG_HDL
  1315. //
  1316. // Remove from the list of handles opened by entity
  1317. //
  1318. ACQUIRE_OPEN_HANDLES_LOCK(Entity);
  1319. RemoveEntryList(&Enum->HandlesLE);
  1320. RELEASE_OPEN_HANDLES_LOCK(Entity);
  1321. #endif
  1322. DEREFERENCE_ENTITY(Entity, ENUM_REF);
  1323. // Free the memory allocated for the enum and return
  1324. #if DBG_HDL
  1325. Enum->ObjectHeader.Alloc = FREED;
  1326. #endif
  1327. FreeObject(Enum);
  1328. return NO_ERROR;
  1329. }