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.

3595 lines
90 KiB

  1. /*++
  2. Copyright (c) 1997 - 98, Microsoft Corporation
  3. Module Name:
  4. rtm1to2.c
  5. Abstract:
  6. Contains routines that wrap RTMv2 functions
  7. in the RTMv1 API.
  8. Author:
  9. Chaitanya Kodeboyina (chaitk) 13-Oct-1998
  10. Revision History:
  11. --*/
  12. #include "pchrtm.h"
  13. #pragma hdrstop
  14. #if WRAPPER
  15. #include "rtm1to2.h"
  16. // Wrapper Globals
  17. V1_GLOBAL_INFO V1Globals;
  18. DWORD
  19. RtmCreateRouteTable (
  20. IN DWORD ProtocolFamily,
  21. IN PRTM_PROTOCOL_FAMILY_CONFIG Config
  22. )
  23. /*++
  24. Routine Description:
  25. Triggers the creation of a new route table corresponding
  26. to a protocol family (same as address family in RTMv2)
  27. in the default instance of RTMv2 by performing the very
  28. first registration in that protocol family.
  29. This default registration is also used for mapping RTMv1
  30. operations that do not require a registration handle
  31. (V1 enums etc.) to their corresponding RTMv2 operations.
  32. Note that all RTMv2 calls require a registration handle.
  33. This call also creates a list of all V1 registrations at
  34. any time. This is used to automatically deregister all
  35. RTMv1 registrations before destroying this route table.
  36. We also set up the notification of changes in best routes
  37. to the router manager (RM) that invoked this function.
  38. Arguments:
  39. ProtocolFamily - Protocol Family (same as v2 address family)
  40. Config - Protocol family's router manager callbacks
  41. (Only the "route change callback" and the
  42. "validate route callback" funcs are used)
  43. Return Value:
  44. Status of the operation
  45. --*/
  46. {
  47. HANDLE V1RegHandle;
  48. DWORD Status;
  49. //
  50. // Validate incoming parameters before action
  51. //
  52. if (ProtocolFamily >= RTM_NUM_OF_PROTOCOL_FAMILIES)
  53. {
  54. return ERROR_INVALID_PARAMETER;
  55. }
  56. if (V1Globals.PfRegInfo[ProtocolFamily])
  57. {
  58. return ERROR_ALREADY_EXISTS;
  59. }
  60. //
  61. // Initialize the lock that guards regns list
  62. //
  63. try
  64. {
  65. InitializeCriticalSection(&V1Globals.PfRegnsLock[ProtocolFamily]);
  66. }
  67. except(EXCEPTION_EXECUTE_HANDLER)
  68. {
  69. return ERROR_NOT_ENOUGH_MEMORY;
  70. }
  71. // Initialize list of regns on protocol family
  72. InitializeListHead(&V1Globals.PfRegistrations[ProtocolFamily]);
  73. //
  74. // Register on behalf of this protocol family
  75. //
  76. // This handle is also used for ops that
  77. // need a handle in RTM v2 but not in v1
  78. //
  79. // We are also setting up best route change
  80. // notifications for RM using its callback
  81. //
  82. V1RegHandle = RtmpRegisterClient(ProtocolFamily,
  83. V1_WRAPPER_REGN_ID,
  84. Config->RPFC_Change,
  85. NULL,
  86. 0);
  87. if (V1RegHandle == NULL)
  88. {
  89. Status = GetLastError();
  90. DeleteCriticalSection(&V1Globals.PfRegnsLock[ProtocolFamily]);
  91. return Status;
  92. }
  93. V1Globals.PfValidateRouteFunc[ProtocolFamily] = Config->RPFC_Validate;
  94. V1Globals.PfRegInfo[ProtocolFamily] = GET_POINTER_FROM_HANDLE(V1RegHandle);
  95. return NO_ERROR;
  96. }
  97. DWORD
  98. RtmDeleteRouteTable (
  99. IN DWORD ProtocolFamily
  100. )
  101. /*++
  102. Routine Description:
  103. Deletes the route table for a particular address family
  104. after deregistering any active V1 registrations present.
  105. Note that atleast 1 registration (the wrapper's default
  106. registration) is active at this point.
  107. We assume that all RTMv2 protocols have deregistered by
  108. the time this function is called. We also assume that
  109. no RTMv1 protocols are trying to register or deregister
  110. while this function is executing, as we do not hold the
  111. lock that protects the list of registrations.
  112. Arguments:
  113. ProtocolFamily - Protocol Family whose table is deleted.
  114. Return Value:
  115. Status of the operation
  116. --*/
  117. {
  118. PV1_REGN_INFO Regn;
  119. PLIST_ENTRY Regns;
  120. DWORD Status;
  121. //
  122. // Validate incoming parameters before action
  123. //
  124. if (ProtocolFamily >= RTM_NUM_OF_PROTOCOL_FAMILIES)
  125. {
  126. return ERROR_INVALID_PARAMETER;
  127. }
  128. if (V1Globals.PfRegInfo[ProtocolFamily] == NULL)
  129. {
  130. return ERROR_INVALID_PARAMETER;
  131. }
  132. //
  133. // Deregister existing regns on protocol family
  134. // including the default regn of the V1 wrapper
  135. //
  136. Regns = &V1Globals.PfRegistrations[ProtocolFamily];
  137. // We have atleast the default regn available
  138. ASSERT(!IsListEmpty(Regns));
  139. while (!IsListEmpty(Regns))
  140. {
  141. Regn = CONTAINING_RECORD(Regns->Flink, V1_REGN_INFO, RegistrationsLE);
  142. Status = RtmDeregisterClient(MAKE_HANDLE_FROM_POINTER(Regn));
  143. ASSERT(Status == NO_ERROR);
  144. }
  145. // Free the lock used to guard the regns list
  146. DeleteCriticalSection(&V1Globals.PfRegnsLock[ProtocolFamily]);
  147. V1Globals.PfRegInfo[ProtocolFamily] = NULL;
  148. return NO_ERROR;
  149. }
  150. HANDLE
  151. WINAPI
  152. RtmRegisterClient (
  153. IN DWORD ProtocolFamily,
  154. IN DWORD RoutingProtocol,
  155. IN HANDLE ChangeEvent OPTIONAL,
  156. IN DWORD Flags
  157. )
  158. /*++
  159. Routine Description:
  160. Registers an RTMv1 client with the default instance and
  161. given protocol family in RTMv2. Also sets up notification
  162. of best route changes if caller asks for it.
  163. Arguments:
  164. ProtocolFamily - Protocol Family we are registering with.
  165. RoutingProtocol - Protocol ID of registering component.
  166. ChangeEvent - Event to indicate changes in best routes.
  167. Flags - RTM_PROTOCOL_SINGLE_ROUTE indicates that
  168. this protocol adds atmost one route per
  169. destination.
  170. Return Value:
  171. Registration Handle or NULL ( Use GetLastError() to get error )
  172. --*/
  173. {
  174. return RtmpRegisterClient(ProtocolFamily,
  175. RoutingProtocol,
  176. NULL,
  177. ChangeEvent,
  178. Flags);
  179. }
  180. HANDLE
  181. RtmpRegisterClient (
  182. IN DWORD ProtocolFamily,
  183. IN DWORD RoutingProtocol,
  184. IN PROUTE_CHANGE_CALLBACK ChangeFunc OPTIONAL,
  185. IN HANDLE ChangeEvent OPTIONAL,
  186. IN DWORD Flags
  187. )
  188. /*++
  189. Routine Description:
  190. Registers an RTMv1 client with the default instance and
  191. given protocol family in RTMv2. Also sets up notification
  192. of best route changes if caller asks for it.
  193. Note that any protocol that needs to be indicated of best
  194. -route changes can either specify an event OR a callback
  195. for this purpose.
  196. Arguments:
  197. ProtocolFamily - Protocol Family we are registering with.
  198. RoutingProtocol - Protocol ID of registering component.
  199. ChangeFunc - Callback to indicates changes in best routes.
  200. ChangeEvent - Event to indicate changes in best routes.
  201. Flags - RTM_PROTOCOL_SINGLE_ROUTE indicates that
  202. this component keeps atmost one route per
  203. network (destination in RTMv2) in RTM.
  204. Return Value:
  205. Registration Handle or NULL ( Use GetLastError() to get error )
  206. --*/
  207. {
  208. PV1_REGN_INFO V1Regn;
  209. RTM_ENTITY_INFO EntityInfo;
  210. BOOL LockInited;
  211. BOOL Success;
  212. DWORD Status;
  213. //
  214. // Check parameters for validity (in v1 bounds)
  215. //
  216. if ((ProtocolFamily >= RTM_NUM_OF_PROTOCOL_FAMILIES) ||
  217. (Flags & (~RTM_PROTOCOL_SINGLE_ROUTE)))
  218. {
  219. SetLastError(ERROR_INVALID_PARAMETER);
  220. return NULL;
  221. }
  222. //
  223. // Create a RTMv1->v2 registration wrapper
  224. //
  225. V1Regn = (PV1_REGN_INFO) AllocNZeroObject(sizeof(V1_REGN_INFO));
  226. if (V1Regn == NULL)
  227. {
  228. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  229. return NULL;
  230. }
  231. LockInited = FALSE;
  232. do
  233. {
  234. #if DBG_HDL
  235. V1Regn->ObjectHeader.TypeSign = V1_REGN_ALLOC;
  236. #endif
  237. //
  238. // Register with RTMv2 after mapping input params to RTMv2
  239. //
  240. // All v1 registrations fall in default Instance in RTMv2
  241. EntityInfo.RtmInstanceId = 0;
  242. // We need to convert v1 protocol family id to winsock id
  243. EntityInfo.AddressFamily = ADDRESS_FAMILY[ProtocolFamily];
  244. // All v1 protocols can register atmost once with RTMv2
  245. // as they all will use the same "Protocol Instance Id"
  246. EntityInfo.EntityId.EntityProtocolId = RoutingProtocol;
  247. EntityInfo.EntityId.EntityInstanceId = V1_PROTOCOL_INSTANCE;
  248. Status = RtmRegisterEntity(&EntityInfo,
  249. (PRTM_ENTITY_EXPORT_METHODS) NULL,
  250. V2EventCallback,
  251. FALSE,
  252. &V1Regn->Rtmv2Profile,
  253. &V1Regn->Rtmv2RegHandle);
  254. if (Status != NO_ERROR)
  255. {
  256. break;
  257. }
  258. //
  259. // Cache RTMv1 specific params in RTMv1 regn
  260. //
  261. V1Regn->ProtocolFamily = ProtocolFamily;
  262. V1Regn->RoutingProtocol = RoutingProtocol;
  263. V1Regn->Flags = Flags;
  264. //
  265. // Store actual number of views in this regn
  266. //
  267. V1Regn->Rtmv2NumViews = V1Regn->Rtmv2Profile.NumberOfViews;
  268. //
  269. // Is caller interested in being notified of best route changes ?
  270. //
  271. if (/*ARGUMENT_PRESENT*/(ChangeFunc) || ARGUMENT_PRESENT(ChangeEvent))
  272. {
  273. if (/*ARGUMENT_PRESENT*/(ChangeFunc))
  274. {
  275. // The caller to be notified of changes directly
  276. V1Regn->NotificationFunc = ChangeFunc;
  277. }
  278. else
  279. {
  280. // Caller to be notified of changes with an event
  281. Success = ResetEvent(ChangeEvent);
  282. if (!Success)
  283. {
  284. Status = GetLastError();
  285. break;
  286. }
  287. V1Regn->NotificationEvent = ChangeEvent;
  288. // Initialize lock to syncronize set/reset event
  289. try
  290. {
  291. InitializeCriticalSection(&V1Regn->NotificationLock);
  292. LockInited = TRUE;
  293. }
  294. except(EXCEPTION_EXECUTE_HANDLER)
  295. {
  296. Status = ERROR_NOT_ENOUGH_MEMORY;
  297. break;
  298. }
  299. }
  300. //
  301. // Register for change notifications with v2
  302. //
  303. Status =
  304. RtmRegisterForChangeNotification(V1Regn->Rtmv2RegHandle,
  305. RTM_VIEW_MASK_UCAST,
  306. RTM_CHANGE_TYPE_ALL,
  307. (PVOID) V1Regn,
  308. &V1Regn->Rtmv2NotifyHandle);
  309. if (Status != NO_ERROR)
  310. {
  311. break;
  312. }
  313. }
  314. //
  315. // Stick it in the list of regns on protocol family
  316. //
  317. ACQUIRE_V1_REGNS_LOCK(ProtocolFamily);
  318. InsertHeadList(&V1Globals.PfRegistrations[ProtocolFamily],
  319. &V1Regn->RegistrationsLE);
  320. RELEASE_V1_REGNS_LOCK(ProtocolFamily);
  321. return MAKE_HANDLE_FROM_POINTER(V1Regn);
  322. }
  323. while (FALSE);
  324. //
  325. // Some error occured - clean up and return NULL
  326. //
  327. if (LockInited)
  328. {
  329. DeleteCriticalSection(&V1Regn->NotificationLock);
  330. }
  331. if (V1Regn->Rtmv2RegHandle)
  332. {
  333. ASSERT(RtmDeregisterEntity(V1Regn->Rtmv2RegHandle) == NO_ERROR);
  334. }
  335. #if DBG_HDL
  336. V1Regn->ObjectHeader.TypeSign = V1_REGN_FREED;
  337. #endif
  338. FreeObject(V1Regn);
  339. SetLastError(Status);
  340. return NULL;
  341. }
  342. DWORD
  343. WINAPI
  344. RtmDeregisterClient (
  345. IN HANDLE ClientHandle
  346. )
  347. /*++
  348. Routine Description:
  349. Deregisters an RTMv1 client from the default instance and
  350. given protocol family in RTMv2. Also deletes any state
  351. that the RTMv1 caller left out - routes, nexthops etc.
  352. and deregisters any change notifications set up during
  353. registration time.
  354. Arguments:
  355. ClientHandle - RTMv1 registration handle being deregistered.
  356. Return Value:
  357. Status of the operation.
  358. --*/
  359. {
  360. RTM_NEXTHOP_HANDLE EnumHandle;
  361. PV1_REGN_INFO V1Regn;
  362. HANDLE *Handles;
  363. UINT NumHandles, i;
  364. BOOL Success;
  365. DWORD Status;
  366. VALIDATE_V1_REGN_HANDLE(ClientHandle, &V1Regn);
  367. //
  368. // Remove the regn from the list of regns on protocol family
  369. //
  370. ACQUIRE_V1_REGNS_LOCK(V1Regn->ProtocolFamily);
  371. RemoveEntryList(&V1Regn->RegistrationsLE);
  372. RELEASE_V1_REGNS_LOCK(V1Regn->ProtocolFamily);
  373. do
  374. {
  375. // Allocate this var-size handles array on the stack
  376. Handles = ALLOC_HANDLES(V1Regn->Rtmv2Profile.MaxHandlesInEnum);
  377. //
  378. // Remove all the next-hops added by this client protocol
  379. //
  380. Status = RtmCreateNextHopEnum(V1Regn->Rtmv2RegHandle,
  381. 0,
  382. NULL,
  383. &EnumHandle);
  384. if (Status != NO_ERROR)
  385. {
  386. break;
  387. }
  388. do
  389. {
  390. NumHandles = V1Regn->Rtmv2Profile.MaxHandlesInEnum;
  391. Status = RtmGetEnumNextHops(V1Regn->Rtmv2RegHandle,
  392. EnumHandle,
  393. &NumHandles,
  394. Handles);
  395. for (i = 0; i < NumHandles; i++)
  396. {
  397. ASSERT(RtmDeleteNextHop(V1Regn->Rtmv2RegHandle,
  398. Handles[i],
  399. NULL) == NO_ERROR);
  400. }
  401. }
  402. while (Status == NO_ERROR);
  403. ASSERT(RtmDeleteEnumHandle(V1Regn->Rtmv2RegHandle,
  404. EnumHandle) == NO_ERROR);
  405. //
  406. // Clean up resources allocated for change processing
  407. //
  408. if (V1Regn->NotificationFunc || V1Regn->NotificationEvent)
  409. {
  410. // Stop the notification of changes to best routes
  411. Status =
  412. RtmDeregisterFromChangeNotification(V1Regn->Rtmv2RegHandle,
  413. V1Regn->Rtmv2NotifyHandle);
  414. if (Status != NO_ERROR)
  415. {
  416. break;
  417. }
  418. if (V1Regn->NotificationEvent)
  419. {
  420. // Free the lock that serves in syncronization
  421. DeleteCriticalSection(&V1Regn->NotificationLock);
  422. // Reset the event to indicate no more changes
  423. Success = ResetEvent(V1Regn->NotificationEvent);
  424. if (!Success)
  425. {
  426. Status = GetLastError();
  427. break;
  428. }
  429. }
  430. }
  431. //
  432. // Deregister with RTMv2 using RTMv2 regn handle
  433. //
  434. Status = RtmDeregisterEntity(V1Regn->Rtmv2RegHandle);
  435. if (Status != NO_ERROR)
  436. {
  437. break;
  438. }
  439. //
  440. // Free resources allocated for the regn wrapper
  441. //
  442. #if DBG_HDL
  443. V1Regn->ObjectHeader.TypeSign = V1_REGN_FREED;
  444. #endif
  445. FreeObject(V1Regn);
  446. return NO_ERROR;
  447. }
  448. while (FALSE);
  449. //
  450. // Some error occured - clean up and return status
  451. //
  452. ASSERT(FALSE);
  453. return Status;
  454. }
  455. DWORD
  456. WINAPI
  457. RtmAddRoute (
  458. IN HANDLE ClientHandle,
  459. IN PVOID Route,
  460. IN DWORD TimeToLive,
  461. OUT DWORD *Flags OPTIONAL,
  462. OUT PVOID CurBestRoute OPTIONAL,
  463. OUT PVOID PrevBestRoute OPTIONAL
  464. )
  465. /*++
  466. Routine Description:
  467. Adds a route to RTMv2 after converting the RTMv1 route to
  468. RTMv2 format.
  469. We create a next hop object if one does not exist, and add
  470. a route through it.
  471. Arguments:
  472. ClientHandle - RTMv1 registration handle of the caller.
  473. Route - Info for V1 route being added/updated.
  474. TimeToLive - Time for which the route is kept in RTM
  475. before being deleted (value is seconds).
  476. THE FOLLOWING PARAMETERS ARE OBSOLETE IN THIS WRAPPER
  477. Flags - Returns error if this param is not NULL.
  478. CurBestRoute - Returns error if this param is not NULL.
  479. PrevBestRoute - Returns error if this param is not NULL.
  480. Return Value:
  481. Status of the operation.
  482. --*/
  483. {
  484. PV1_REGN_INFO V1Regn;
  485. RTM_NET_ADDRESS DestAddr;
  486. RTM_ROUTE_INFO V2RouteInfo;
  487. RTM_NEXTHOP_INFO V2NextHopInfo;
  488. RTM_NEXTHOP_HANDLE V2NextHop;
  489. DWORD ChangeFlags;
  490. DWORD Status;
  491. VALIDATE_V1_REGN_HANDLE(ClientHandle, &V1Regn);
  492. // Protocols specify Flags parameter but don't use it
  493. *Flags = RTM_NO_CHANGE;
  494. if (ARGUMENT_PRESENT(CurBestRoute) || ARGUMENT_PRESENT(PrevBestRoute))
  495. {
  496. return ERROR_NOT_SUPPORTED;
  497. }
  498. //
  499. // Call back into RM to validate route, set priority
  500. //
  501. Status = V1Globals.PfValidateRouteFunc[V1Regn->ProtocolFamily](Route);
  502. if (Status != NO_ERROR)
  503. {
  504. return Status;
  505. }
  506. //
  507. // Create a new next-hop with this interface
  508. // (if this next-hop is not already present)
  509. //
  510. MakeV2NextHopFromV1Route(V1Regn, Route, &V2NextHopInfo);
  511. V2NextHop = NULL;
  512. Status = RtmAddNextHop(V1Regn->Rtmv2RegHandle,
  513. &V2NextHopInfo,
  514. &V2NextHop,
  515. &ChangeFlags);
  516. if (Status != NO_ERROR)
  517. {
  518. return Status;
  519. }
  520. //
  521. // Create a new route with the above nexthop
  522. //
  523. MakeV2RouteFromV1Route(V1Regn, Route, V2NextHop, &DestAddr, &V2RouteInfo);
  524. //
  525. // Convert TimeToLive for secs to ms
  526. //
  527. if (TimeToLive != INFINITE)
  528. {
  529. TimeToLive *= 1000;
  530. if (TimeToLive > (MAXTICKS/2-1))
  531. {
  532. TimeToLive = MAXTICKS/2-1;
  533. }
  534. }
  535. // Setup flags that control RTMv2's add route
  536. ChangeFlags = (V1Regn->Flags & RTM_PROTOCOL_SINGLE_ROUTE)
  537. ? RTM_ROUTE_CHANGE_FIRST : 0;
  538. //
  539. // Add the new route using the RTMv2 API call
  540. //
  541. Status = RtmAddRouteToDest(V1Regn->Rtmv2RegHandle,
  542. NULL,
  543. &DestAddr,
  544. &V2RouteInfo,
  545. TimeToLive,
  546. NULL,
  547. 0,
  548. NULL,
  549. &ChangeFlags);
  550. //
  551. // Remove the handle ref we got on the nexthop above
  552. //
  553. ASSERT(RtmReleaseNextHops(V1Regn->Rtmv2RegHandle,
  554. 1,
  555. &V2NextHop) == NO_ERROR);
  556. return Status;
  557. }
  558. DWORD
  559. WINAPI
  560. RtmDeleteRoute (
  561. IN HANDLE ClientHandle,
  562. IN PVOID Route,
  563. OUT DWORD *Flags OPTIONAL,
  564. OUT PVOID CurBestRoute OPTIONAL
  565. )
  566. /*++
  567. Routine Description:
  568. Deletes the route in RTMv2 that corresponds to input RTMv1
  569. route.
  570. Arguments:
  571. ClientHandle - RTMv1 registration handle of the caller.
  572. Route - Info for V1 route being deleted in RTM.
  573. THE FOLLOWING PARAMETERS ARE OBSOLETE IN THIS WRAPPER
  574. Flags - Returns error if this param is not NULL.
  575. CurBestRoute - Returns error if this param is not NULL.
  576. Return Value:
  577. Status of the operation.
  578. --*/
  579. {
  580. PV1_REGN_INFO V1Regn;
  581. RTM_NET_ADDRESS DestAddr;
  582. RTM_ROUTE_INFO V2RouteInfo;
  583. RTM_ROUTE_HANDLE V2Route;
  584. RTM_NEXTHOP_INFO V2NextHopInfo;
  585. RTM_NEXTHOP_HANDLE V2NextHop;
  586. DWORD ChangeFlags;
  587. DWORD Status;
  588. VALIDATE_V1_REGN_HANDLE(ClientHandle, &V1Regn);
  589. // Protocols specify Flags parameter but don't use it
  590. *Flags = RTM_NO_CHANGE;
  591. if (ARGUMENT_PRESENT(CurBestRoute))
  592. {
  593. return ERROR_NOT_SUPPORTED;
  594. }
  595. //
  596. // Find the next-hop with this interface
  597. //
  598. MakeV2NextHopFromV1Route(V1Regn, Route, &V2NextHopInfo);
  599. V2NextHop = NULL;
  600. Status = RtmFindNextHop(V1Regn->Rtmv2RegHandle,
  601. &V2NextHopInfo,
  602. &V2NextHop,
  603. NULL);
  604. if (Status != NO_ERROR)
  605. {
  606. return Status;
  607. }
  608. //
  609. // Delete the route with the above nexthop
  610. //
  611. MakeV2RouteFromV1Route(V1Regn, Route, V2NextHop, &DestAddr, &V2RouteInfo);
  612. //
  613. // We can get this route by matching the route's
  614. // net addr, its owner and neighbour learnt from
  615. //
  616. Status = RtmGetExactMatchRoute(V1Regn->Rtmv2RegHandle,
  617. &DestAddr,
  618. RTM_MATCH_OWNER | RTM_MATCH_NEIGHBOUR,
  619. &V2RouteInfo,
  620. 0,
  621. 0,
  622. &V2Route);
  623. if (Status == NO_ERROR)
  624. {
  625. //
  626. // Delete the route found above using the handle
  627. //
  628. Status = RtmDeleteRouteToDest(V1Regn->Rtmv2RegHandle,
  629. V2Route,
  630. &ChangeFlags);
  631. if (Status != NO_ERROR)
  632. {
  633. // If delete was successful, this deref is automatic
  634. ASSERT(RtmReleaseRoutes(V1Regn->Rtmv2RegHandle,
  635. 1,
  636. &V2Route) == NO_ERROR);
  637. }
  638. ASSERT(RtmReleaseRouteInfo(V1Regn->Rtmv2RegHandle,
  639. &V2RouteInfo) == NO_ERROR);
  640. }
  641. //
  642. // Remove the handle ref we got on the nexthop
  643. //
  644. ASSERT(RtmReleaseNextHops(V1Regn->Rtmv2RegHandle,
  645. 1,
  646. &V2NextHop) == NO_ERROR);
  647. return Status;
  648. }
  649. DWORD
  650. WINAPI
  651. RtmDequeueRouteChangeMessage (
  652. IN HANDLE ClientHandle,
  653. OUT DWORD *Flags,
  654. OUT PVOID CurBestRoute OPTIONAL,
  655. OUT PVOID PrevBestRoute OPTIONAL
  656. )
  657. /*++
  658. Routine Description:
  659. Removes a route change message (basically a dest that has
  660. changed recently) from the client's own queue of pending
  661. changes to be notified.
  662. If a best route exists on the dest, RTM_CURRENT_BEST_ROUTE
  663. is set in flags and CurBestRoute is filled with best info.
  664. If the dest has no best routes (in unicast view), then the
  665. flags are set to RTM_PREVIOUS_BEST_ROUTE, and a route with
  666. correct network address and rest of route info set to some
  667. dummy info is returned.
  668. At no point are both flags set (as was the case in RTMv1).
  669. Arguments:
  670. ClientHandle - RTMv1 registration handle of the caller.
  671. THESE HAVE A SLIGHTLY DIFFERENT MEANING IN THE WRAPPER
  672. Flags - RTM_NO_CHANGE, RTM_PREVIOUS_BEST_ROUTE
  673. or RTM_CURRENT_BEST_ROUTE
  674. CurBestRoute - Info for current best route is filled.
  675. ( See routine description just above )
  676. PrevBestRoute - Info for previous best route is filled.
  677. ( See routine description just above )
  678. Return Value:
  679. Status of the operation.
  680. --*/
  681. {
  682. PV1_REGN_INFO V1Regn;
  683. PRTM_DEST_INFO DestInfo;
  684. PRTM_ROUTE_INFO V2RouteInfo;
  685. RTM_ROUTE_HANDLE V2RouteHandle;
  686. UINT NumDests;
  687. DWORD Status;
  688. DWORD Status1;
  689. VALIDATE_V1_REGN_HANDLE(ClientHandle, &V1Regn);
  690. *Flags = RTM_NO_CHANGE;
  691. // Allocate this var-size dest-info on the stack
  692. DestInfo = ALLOC_DEST_INFO(V1Regn->Rtmv2NumViews, 1);
  693. if (V1Regn->NotificationEvent)
  694. {
  695. //
  696. // This lock serves to make the RtmGetChangedDests
  697. // call and resetting of the "more changes" event
  698. // a single combined atomic operation, preventing
  699. // a case when a set gets lost due to a late reset.
  700. //
  701. ACQUIRE_V1_NOTIFY_LOCK(V1Regn);
  702. }
  703. Status = NO_ERROR;
  704. NumDests = 0;
  705. while (Status == NO_ERROR)
  706. {
  707. //
  708. // Release any destination we got in the prev loop
  709. //
  710. if (NumDests == 1)
  711. {
  712. ASSERT(RtmReleaseChangedDests(V1Regn->Rtmv2RegHandle,
  713. V1Regn->Rtmv2NotifyHandle,
  714. 1,
  715. DestInfo) == NO_ERROR);
  716. }
  717. //
  718. // Get the next changed destination for client
  719. //
  720. NumDests = 1;
  721. Status = RtmGetChangedDests(V1Regn->Rtmv2RegHandle,
  722. V1Regn->Rtmv2NotifyHandle,
  723. &NumDests,
  724. DestInfo);
  725. if (NumDests < 1)
  726. {
  727. break;
  728. }
  729. //
  730. // Get the current best route for this dest
  731. //
  732. V2RouteHandle = DestInfo->ViewInfo[0].Route;
  733. if (V2RouteHandle != NULL)
  734. {
  735. //
  736. // We have a best route on the changed dest
  737. // Give the caller the new best route info
  738. //
  739. if (ARGUMENT_PRESENT(CurBestRoute))
  740. {
  741. // Get the route's information from RTMv2
  742. V2RouteInfo =
  743. ALLOC_ROUTE_INFO(V1Regn->Rtmv2Profile.MaxNextHopsInRoute, 1);
  744. Status1 = RtmGetRouteInfo(V1Regn->Rtmv2RegHandle,
  745. V2RouteHandle,
  746. V2RouteInfo,
  747. NULL);
  748. if (Status1 != NO_ERROR)
  749. {
  750. // Best Route would have got deleted - get next change
  751. continue;
  752. };
  753. Status1 =
  754. MakeV1RouteFromV2Route(V1Regn, V2RouteInfo, CurBestRoute);
  755. ASSERT(RtmReleaseRouteInfo(V1Regn->Rtmv2RegHandle,
  756. V2RouteInfo) == NO_ERROR);
  757. if (Status1 != NO_ERROR)
  758. {
  759. // Best Route would have got changed - get next change
  760. continue;
  761. }
  762. }
  763. *Flags = RTM_CURRENT_BEST_ROUTE;
  764. }
  765. else
  766. {
  767. //
  768. // We have no best route on the changed dest,
  769. // Give dummy best route info with this dest
  770. //
  771. if (ARGUMENT_PRESENT(PrevBestRoute))
  772. {
  773. MakeV1RouteFromV2Dest(V1Regn, DestInfo, PrevBestRoute);
  774. }
  775. *Flags = RTM_PREVIOUS_BEST_ROUTE;
  776. }
  777. //
  778. // Do we have more changes to process here ?
  779. //
  780. if (Status == ERROR_NO_MORE_ITEMS)
  781. {
  782. // We have no more changes to notify - reset event if present
  783. if (V1Regn->NotificationEvent)
  784. {
  785. ResetEvent(V1Regn->NotificationEvent);
  786. }
  787. Status = NO_ERROR;
  788. }
  789. else
  790. {
  791. // We have more changes to give out - indicate so in status
  792. ASSERT(Status == NO_ERROR);
  793. Status = ERROR_MORE_DATA;
  794. }
  795. break;
  796. }
  797. if (NumDests == 1)
  798. {
  799. ASSERT(SUCCESS(RtmReleaseChangedDests(V1Regn->Rtmv2RegHandle,
  800. V1Regn->Rtmv2NotifyHandle,
  801. 1,
  802. DestInfo)));
  803. }
  804. if (V1Regn->NotificationEvent)
  805. {
  806. RELEASE_V1_NOTIFY_LOCK(V1Regn);
  807. }
  808. return Status;
  809. }
  810. DWORD
  811. V2EventCallback (
  812. IN RTM_ENTITY_HANDLE Rtmv2RegHandle,
  813. IN RTM_EVENT_TYPE EventType,
  814. IN PVOID Context1,
  815. IN PVOID Context2
  816. )
  817. /*++
  818. Routine Description:
  819. This is the callback function that gets called when any
  820. RTMv2 event happens like change notification available,
  821. route's timed out etc.
  822. Context1 & Context2 contain event specific information.
  823. Arguments:
  824. Rtmv2RegHandle - Regn handle of entity being informed.
  825. EventType - Type of event that caused this call.
  826. Context1 - Context associated with this event.
  827. Context2 - Context associated with this event.
  828. Return Value:
  829. Status of the operation being returned to RTMv2
  830. --*/
  831. {
  832. PV1_REGN_INFO V1Regn;
  833. HANDLE V1RegHandle;
  834. V1_ROUTE_INFO CurBestRoute;
  835. V1_ROUTE_INFO PrevBestRoute;
  836. DWORD Flags;
  837. DWORD Status;
  838. UNREFERENCED_PARAMETER(Rtmv2RegHandle);
  839. UNREFERENCED_PARAMETER(Context1);
  840. switch(EventType)
  841. {
  842. case RTM_CHANGE_NOTIFICATION:
  843. V1Regn = (PV1_REGN_INFO) Context2;
  844. //
  845. // Signal availability of new changes using either callback or event
  846. //
  847. if (V1Regn->NotificationFunc)
  848. {
  849. V1RegHandle = MAKE_HANDLE_FROM_POINTER(V1Regn);
  850. do
  851. {
  852. // Get the next change in this regn's queue
  853. Status = RtmDequeueRouteChangeMessage(V1RegHandle,
  854. &Flags,
  855. &CurBestRoute,
  856. &PrevBestRoute);
  857. if (Status != ERROR_MORE_DATA)
  858. {
  859. break;
  860. }
  861. // Call the notification callback with data
  862. V1Regn->NotificationFunc(Flags, &CurBestRoute, &PrevBestRoute);
  863. }
  864. while (TRUE);
  865. // Give the final notification call if needed
  866. if (Status == NO_ERROR)
  867. {
  868. // Call the notification callback with data
  869. V1Regn->NotificationFunc(Flags, &CurBestRoute, &PrevBestRoute);
  870. }
  871. }
  872. else
  873. {
  874. //
  875. // Set event to signal availability of changes
  876. //
  877. ASSERT(V1Regn->NotificationEvent);
  878. ACQUIRE_V1_NOTIFY_LOCK(V1Regn);
  879. SetEvent(V1Regn->NotificationEvent);
  880. RELEASE_V1_NOTIFY_LOCK(V1Regn);
  881. }
  882. return NO_ERROR;
  883. case RTM_ROUTE_EXPIRED:
  884. //
  885. // Do not handle this route expiry notification.
  886. // This will automatically cause deletion of the
  887. // route and the appropriate change notification
  888. // generated and indicated to all the protocols.
  889. //
  890. return ERROR_NOT_SUPPORTED;
  891. }
  892. return ERROR_NOT_SUPPORTED;
  893. }
  894. HANDLE
  895. WINAPI
  896. RtmCreateEnumerationHandle (
  897. IN DWORD ProtocolFamily,
  898. IN DWORD EnumerationFlags,
  899. IN PVOID CriteriaRoute
  900. )
  901. /*++
  902. Routine Description:
  903. Creates an enumeration on routes in RTM that match the
  904. appropriate criteria in the input route.
  905. This call does not need an RTMv1 registration handle,
  906. so we use the wrapper's default V1 registration with
  907. RTMv2 to make RTMv2 calls.
  908. Matching Routes are returned in the order governed the
  909. following fields -
  910. ( Dest Address and Mask, Route Preference and Metric )
  911. Arguments:
  912. ProtocolFamily - Protocol family of the routes we want
  913. EnumerationFlags - Flags indicating the criteria to match
  914. CriteriaRoute - The route that we are matching against
  915. Return Value:
  916. Enumeration Handle or NULL ( GetLastError() to get error )
  917. --*/
  918. {
  919. PV1_REGN_INFO V1Regn;
  920. RTM_DEST_HANDLE DestHandle;
  921. PRTM_DEST_INFO DestInfo;
  922. RTM_NET_ADDRESS DestAddr;
  923. PV1_ENUM_INFO V1Enum;
  924. PVOID Network;
  925. RTM_VIEW_SET TargetViews;
  926. ULONG TempUlong;
  927. DWORD EnumFlags;
  928. DWORD MatchFlags;
  929. ULONG InterfaceIndex;
  930. DWORD Status;
  931. //
  932. // Validate incoming parameters before action
  933. //
  934. if ((ProtocolFamily >= RTM_NUM_OF_PROTOCOL_FAMILIES) ||
  935. (EnumerationFlags & ~(RTM_ONLY_THIS_NETWORK |
  936. RTM_ONLY_THIS_PROTOCOL |
  937. RTM_ONLY_THIS_INTERFACE |
  938. RTM_ONLY_BEST_ROUTES |
  939. RTM_ONLY_OWND_ROUTES |
  940. RTM_INCLUDE_DISABLED_ROUTES)))
  941. {
  942. SetLastError(ERROR_INVALID_PARAMETER);
  943. return NULL;
  944. }
  945. // Specify Criteria if these flags are set
  946. if ((!ARGUMENT_PRESENT(CriteriaRoute)) &&
  947. (EnumerationFlags & (RTM_ONLY_THIS_NETWORK |
  948. RTM_ONLY_THIS_PROTOCOL |
  949. RTM_ONLY_THIS_INTERFACE)))
  950. {
  951. SetLastError(ERROR_INVALID_PARAMETER);
  952. return NULL;
  953. }
  954. V1Regn = V1Globals.PfRegInfo[ProtocolFamily];
  955. if (V1Regn == NULL)
  956. {
  957. SetLastError(ERROR_INVALID_HANDLE);
  958. return NULL;
  959. }
  960. //
  961. // If we don't need disabled routes, just use unicast view;
  962. // or use 0 views to get all routes including disabled ones
  963. //
  964. if (EnumerationFlags & RTM_INCLUDE_DISABLED_ROUTES)
  965. {
  966. TargetViews = RTM_VIEW_MASK_ANY;
  967. }
  968. else
  969. {
  970. TargetViews = RTM_VIEW_MASK_UCAST;
  971. }
  972. //
  973. // If enuming a certain n/w, check if corr. dest exists
  974. //
  975. DestHandle = NULL;
  976. #if WRN
  977. DestInfo = NULL;
  978. #endif
  979. if (EnumerationFlags & RTM_ONLY_THIS_NETWORK)
  980. {
  981. V1GetRouteNetwork(CriteriaRoute, ProtocolFamily, &Network);
  982. MakeNetAddress(Network, ProtocolFamily, TempUlong, &DestAddr);
  983. // Allocate this var-size dest-info on the stack
  984. DestInfo = ALLOC_DEST_INFO(V1Regn->Rtmv2NumViews, 1);
  985. Status = RtmGetExactMatchDestination(V1Regn->Rtmv2RegHandle,
  986. &DestAddr,
  987. RTM_BEST_PROTOCOL,
  988. TargetViews,
  989. DestInfo);
  990. if (Status != NO_ERROR)
  991. {
  992. SetLastError(Status);
  993. return NULL;
  994. }
  995. DestHandle = DestInfo->DestHandle;
  996. }
  997. do
  998. {
  999. //
  1000. // Allocate a V1 enumeration wrapper structure
  1001. //
  1002. V1Enum = (PV1_ENUM_INFO) AllocNZeroObject(sizeof(V1_ENUM_INFO));
  1003. if (V1Enum == NULL)
  1004. {
  1005. Status = ERROR_NOT_ENOUGH_MEMORY;
  1006. break;
  1007. }
  1008. #if DBG_HDL
  1009. V1Enum->ObjectHeader.TypeSign = V1_ENUM_ALLOC;
  1010. #endif
  1011. //
  1012. // Cache RTMv1 specific params in RTMv1 enum
  1013. //
  1014. V1Enum->ProtocolFamily = ProtocolFamily;
  1015. V1Enum->EnumFlags = EnumerationFlags;
  1016. if (ARGUMENT_PRESENT(CriteriaRoute))
  1017. {
  1018. // Convert the V1 criteria into V2 criteria
  1019. V1CopyRoute(V1Enum->CriteriaRoute.Route,
  1020. CriteriaRoute,
  1021. ProtocolFamily);
  1022. }
  1023. //
  1024. // Create a route enum on a dest or all dests
  1025. //
  1026. if (EnumerationFlags & RTM_ONLY_OWND_ROUTES)
  1027. {
  1028. EnumFlags = RTM_ENUM_OWN_ROUTES;
  1029. }
  1030. else
  1031. {
  1032. EnumFlags = RTM_ENUM_ALL_ROUTES;
  1033. }
  1034. MatchFlags = InterfaceIndex = 0;
  1035. // Do we have to enum's routes on an interface
  1036. if (EnumerationFlags & RTM_ONLY_THIS_INTERFACE)
  1037. {
  1038. MatchFlags = RTM_MATCH_INTERFACE;
  1039. InterfaceIndex =
  1040. ((PV1_ROUTE_INFO) CriteriaRoute)->XxRoute.RR_InterfaceID;
  1041. }
  1042. Status = RtmCreateRouteEnum(V1Regn->Rtmv2RegHandle,
  1043. DestHandle,
  1044. TargetViews,
  1045. EnumFlags,
  1046. NULL,
  1047. MatchFlags,
  1048. NULL,
  1049. InterfaceIndex,
  1050. &V1Enum->Rtmv2RouteEnum);
  1051. if (Status != NO_ERROR)
  1052. {
  1053. break;
  1054. }
  1055. //
  1056. // Initialize lock used to serialize enum ops
  1057. //
  1058. try
  1059. {
  1060. InitializeCriticalSection(&V1Enum->EnumLock);
  1061. }
  1062. except(EXCEPTION_EXECUTE_HANDLER)
  1063. {
  1064. Status = ERROR_NOT_ENOUGH_MEMORY;
  1065. break;
  1066. }
  1067. //
  1068. // Release the destination info as we are done
  1069. //
  1070. if (EnumerationFlags & RTM_ONLY_THIS_NETWORK)
  1071. {
  1072. ASSERT(SUCCESS(RtmReleaseDestInfo(V1Regn->Rtmv2RegHandle,
  1073. DestInfo)));
  1074. }
  1075. return MAKE_HANDLE_FROM_POINTER(V1Enum);
  1076. }
  1077. while (FALSE);
  1078. //
  1079. // Some error occurred - clean up and return NULL
  1080. //
  1081. if (EnumerationFlags & RTM_ONLY_THIS_NETWORK)
  1082. {
  1083. ASSERT(SUCCESS(RtmReleaseDestInfo(V1Regn->Rtmv2RegHandle,
  1084. DestInfo)));
  1085. }
  1086. if (V1Enum)
  1087. {
  1088. if (V1Enum->Rtmv2RouteEnum)
  1089. {
  1090. ASSERT(SUCCESS(RtmDeleteEnumHandle(V1Regn->Rtmv2RegHandle,
  1091. V1Enum->Rtmv2RouteEnum)));
  1092. }
  1093. #if DBG_HDL
  1094. V1Enum->ObjectHeader.TypeSign = V1_ENUM_FREED;
  1095. #endif
  1096. FreeObject(V1Enum);
  1097. }
  1098. SetLastError(Status);
  1099. return NULL;
  1100. }
  1101. DWORD
  1102. WINAPI
  1103. RtmEnumerateGetNextRoute (
  1104. IN HANDLE EnumerationHandle,
  1105. OUT PVOID Route
  1106. )
  1107. /*++
  1108. Routine Description:
  1109. Get the next route in the V1 enumeration (satisfying the
  1110. enumeration critieria).
  1111. Arguments:
  1112. EnumerationHandle - Handle that identifies the enumeration
  1113. Route - Next route is returned in this param
  1114. Return Value:
  1115. Status of the operation
  1116. --*/
  1117. {
  1118. PV1_REGN_INFO V1Regn;
  1119. RTM_ROUTE_HANDLE V2Route;
  1120. PV1_ENUM_INFO V1Enum;
  1121. UINT NumRoutes;
  1122. BOOL Match;
  1123. DWORD Status;
  1124. VALIDATE_V1_ENUM_HANDLE(EnumerationHandle, &V1Enum);
  1125. V1Regn = V1Globals.PfRegInfo[V1Enum->ProtocolFamily];
  1126. // Acquire the enum lock to serialize requests
  1127. ACQUIRE_V1_ENUM_LOCK(V1Enum);
  1128. //
  1129. // Do until you have a matching route or no more routes
  1130. //
  1131. Match = FALSE;
  1132. do
  1133. {
  1134. // Get next route in enum, and check if it matches
  1135. //
  1136. // Routes are enum'ed in the following order,
  1137. // Network Addr, Route Priority, Route Metric
  1138. //
  1139. NumRoutes = 1;
  1140. Status = RtmGetEnumRoutes(V1Regn->Rtmv2RegHandle,
  1141. V1Enum->Rtmv2RouteEnum,
  1142. &NumRoutes,
  1143. &V2Route);
  1144. if (NumRoutes < 1)
  1145. {
  1146. break;
  1147. }
  1148. Match = MatchCriteriaAndCopyRoute(V1Regn, V2Route, V1Enum, Route);
  1149. ASSERT(SUCCESS(RtmReleaseRoutes(V1Regn->Rtmv2RegHandle,
  1150. 1,
  1151. &V2Route)));
  1152. }
  1153. while (!Match);
  1154. RELEASE_V1_ENUM_LOCK(V1Enum);
  1155. return Match ? NO_ERROR : Status;
  1156. }
  1157. DWORD
  1158. WINAPI
  1159. RtmCloseEnumerationHandle (
  1160. IN HANDLE EnumerationHandle
  1161. )
  1162. /*++
  1163. Routine Description:
  1164. Closes the enumeration and releases its resources.
  1165. Arguments:
  1166. EnumerationHandle - Handle that identifies the enumeration
  1167. Return Value:
  1168. Status of the operation
  1169. --*/
  1170. {
  1171. PV1_REGN_INFO V1Regn;
  1172. PV1_ENUM_INFO V1Enum;
  1173. DWORD Status;
  1174. VALIDATE_V1_ENUM_HANDLE(EnumerationHandle, &V1Enum);
  1175. V1Regn = V1Globals.PfRegInfo[V1Enum->ProtocolFamily];
  1176. do
  1177. {
  1178. //
  1179. // Free the RTMv2 route enumeration and resouces
  1180. //
  1181. if (V1Enum->Rtmv2RouteEnum)
  1182. {
  1183. Status = RtmDeleteEnumHandle(V1Regn->Rtmv2RegHandle,
  1184. V1Enum->Rtmv2RouteEnum);
  1185. ASSERT(Status == NO_ERROR);
  1186. V1Enum->Rtmv2RouteEnum = NULL;
  1187. }
  1188. //
  1189. // Free resources allocated for the enum wrapper
  1190. //
  1191. DeleteCriticalSection(&V1Enum->EnumLock);
  1192. #if DBG_HDL
  1193. V1Enum->ObjectHeader.TypeSign = V1_ENUM_FREED;
  1194. #endif
  1195. FreeObject(V1Enum);
  1196. return NO_ERROR;
  1197. }
  1198. while (FALSE);
  1199. ASSERT(FALSE);
  1200. return Status;
  1201. }
  1202. DWORD
  1203. WINAPI
  1204. RtmGetFirstRoute (
  1205. IN DWORD ProtocolFamily,
  1206. IN DWORD EnumerationFlags,
  1207. IN OUT PVOID Route
  1208. )
  1209. /*++
  1210. Routine Description:
  1211. Returns the first route in the table that matches the
  1212. criteria.
  1213. This function just opens a new enumeration and gets
  1214. the first route that matches enumeration critiria,
  1215. and closes the enumeration.
  1216. Arguments:
  1217. ProtocolFamily - Protocol family of the route we want
  1218. EnumerationFlags - Flags indicating the criteria to match
  1219. CriteriaRoute - The route that we are matching against
  1220. Return Value:
  1221. Status of the operation
  1222. --*/
  1223. {
  1224. HANDLE V1EnumHandle;
  1225. DWORD Status;
  1226. //
  1227. // Create an enumeration and return the first route in it
  1228. //
  1229. V1EnumHandle = RtmCreateEnumerationHandle(ProtocolFamily,
  1230. EnumerationFlags,
  1231. Route);
  1232. if (V1EnumHandle == NULL)
  1233. {
  1234. return GetLastError();
  1235. }
  1236. Status = RtmEnumerateGetNextRoute(V1EnumHandle, Route);
  1237. ASSERT(SUCCESS(RtmCloseEnumerationHandle(V1EnumHandle)));
  1238. return Status;
  1239. }
  1240. DWORD
  1241. WINAPI
  1242. RtmGetNextRoute (
  1243. IN DWORD ProtocolFamily,
  1244. IN DWORD EnumerationFlags,
  1245. OUT PVOID Route
  1246. )
  1247. /*++
  1248. Routine Description:
  1249. Returns the next route in the table that matches the
  1250. criteria.
  1251. The routes in RTMv2 are ordered using the following
  1252. fields -
  1253. (Dest Address and Mask, Route Preference and Metric)
  1254. If we have 2 routes with identical values for all the
  1255. above fields, then you have no way of knowing which
  1256. of these routes you returned the last time this call
  1257. was made. For this reason, this call is not supported
  1258. in this wrapper.
  1259. One should create an enumeration to actually get the
  1260. next route in the table.
  1261. Arguments:
  1262. ProtocolFamily - Protocol family of the route we want
  1263. EnumerationFlags - Flags indicating the criteria to match
  1264. CriteriaRoute - The route that we are matching against
  1265. Return Value:
  1266. Status of the operation
  1267. --*/
  1268. {
  1269. UNREFERENCED_PARAMETER(ProtocolFamily);
  1270. UNREFERENCED_PARAMETER(EnumerationFlags);
  1271. UNREFERENCED_PARAMETER(Route);
  1272. return ERROR_NOT_SUPPORTED;
  1273. }
  1274. DWORD
  1275. WINAPI
  1276. RtmBlockDeleteRoutes (
  1277. IN HANDLE ClientHandle,
  1278. IN DWORD EnumerationFlags,
  1279. IN PVOID CriteriaRoute
  1280. )
  1281. /*++
  1282. Routine Description:
  1283. Deletes all routes in the route table that match the
  1284. criteria specified.
  1285. Note that if we have multiple instances of a protocol
  1286. running (say RIP), then each version can delete only
  1287. the routes in owns.
  1288. Arguments:
  1289. ClientHandle - RTM v1 registration handle of caller
  1290. EnumerationFlags - Flags indicating the criteria to match
  1291. CriteriaRoute - The route that we are matching against
  1292. Return Value:
  1293. Status of the operation
  1294. --*/
  1295. {
  1296. PV1_REGN_INFO V1Regn;
  1297. //
  1298. // Check parameters for validity (in v1 bounds)
  1299. //
  1300. VALIDATE_V1_REGN_HANDLE(ClientHandle, &V1Regn);
  1301. if (EnumerationFlags & ~(RTM_ONLY_THIS_NETWORK | RTM_ONLY_THIS_INTERFACE))
  1302. {
  1303. return ERROR_INVALID_PARAMETER;
  1304. }
  1305. //
  1306. // Deletes only routes of this instance of the protocol
  1307. // Also include all disabled routes in the enumeration
  1308. //
  1309. EnumerationFlags |= (RTM_ONLY_OWND_ROUTES | RTM_INCLUDE_DISABLED_ROUTES);
  1310. //
  1311. // Call block operation to delete all matching routes
  1312. //
  1313. return BlockOperationOnRoutes(V1Regn,
  1314. EnumerationFlags,
  1315. CriteriaRoute,
  1316. MatchCriteriaAndDeleteRoute);
  1317. }
  1318. BOOL
  1319. MatchCriteriaAndDeleteRoute (
  1320. IN PV1_REGN_INFO V1Regn,
  1321. IN PRTM_ROUTE_HANDLE V2RouteHandle,
  1322. IN PV1_ENUM_INFO V1Enum
  1323. )
  1324. /*++
  1325. Routine Description:
  1326. Deletes input route if it matches the enumeration criteria.
  1327. The enumeration criteria returns only routes owned by the
  1328. caller. See RTM_ONLY_OWND_ROUTES in RtmBlockDeleteRoutes.
  1329. Arguments:
  1330. V1Regn - RTM v1 registration info of the caller
  1331. V2RouteHandle - Handle of the route being considered
  1332. V1Enum - Enum info that gives matching criteria
  1333. Return Value:
  1334. TRUE if you have released input route handle, FALSE if not
  1335. --*/
  1336. {
  1337. DWORD ChangeFlags;
  1338. BOOL Match;
  1339. DWORD Status;
  1340. Match = MatchCriteria(V1Regn, V2RouteHandle, V1Enum);
  1341. if (Match)
  1342. {
  1343. // Caller can delete the route only if he owns it
  1344. Status = RtmDeleteRouteToDest(V1Regn->Rtmv2RegHandle,
  1345. V2RouteHandle,
  1346. &ChangeFlags);
  1347. if (Status != NO_ERROR)
  1348. {
  1349. ASSERT(FALSE);
  1350. Match = FALSE;
  1351. }
  1352. }
  1353. return Match;
  1354. }
  1355. DWORD
  1356. WINAPI
  1357. RtmBlockSetRouteEnable (
  1358. IN HANDLE ClientHandle,
  1359. IN DWORD EnumerationFlags,
  1360. IN PVOID CriteriaRoute,
  1361. IN BOOL Enable
  1362. )
  1363. /*++
  1364. Routine Description:
  1365. Enables or disables all routes in the route table that
  1366. match the criteria specified.
  1367. Disabling a route removes it from consideration in all
  1368. best route computations. We do this by adding this
  1369. route in "no" views in RTMv2. In other words, this
  1370. route is not considered for best route computations
  1371. in any views.
  1372. Note that if we have multiple instances of a protocol
  1373. running (say RIP), then each version can disable or
  1374. enable only the routes it owns.
  1375. Arguments:
  1376. ClientHandle - RTM v1 registration handle of caller
  1377. EnumerationFlags - Flags indicating the criteria to match
  1378. CriteriaRoute - The route that we are matching against
  1379. Enable - TRUE to enable, and FALSE to disable
  1380. Return Value:
  1381. Status of the operation
  1382. --*/
  1383. {
  1384. PV1_REGN_INFO V1Regn;
  1385. DWORD *Flags;
  1386. VALIDATE_V1_REGN_HANDLE(ClientHandle, &V1Regn);
  1387. if (EnumerationFlags & ~(RTM_ONLY_THIS_NETWORK | RTM_ONLY_THIS_INTERFACE))
  1388. {
  1389. return ERROR_INVALID_PARAMETER;
  1390. }
  1391. // Enable/Disable routes only of this instance of the protocol
  1392. EnumerationFlags |= RTM_ONLY_OWND_ROUTES;
  1393. // If we are enabling routes, get disable routes too
  1394. if (Enable)
  1395. {
  1396. EnumerationFlags |= RTM_INCLUDE_DISABLED_ROUTES;
  1397. }
  1398. //
  1399. // Set the enable/disable flag in the criteria route
  1400. //
  1401. V1GetRouteFlags(CriteriaRoute, V1Regn->ProtocolFamily, Flags);
  1402. if (Enable)
  1403. {
  1404. (*Flags) |= IP_VALID_ROUTE;
  1405. }
  1406. else
  1407. {
  1408. (*Flags) &= ~IP_VALID_ROUTE;
  1409. }
  1410. //
  1411. // Call block operation to enable/disable all matching routes
  1412. //
  1413. return BlockOperationOnRoutes(V1Regn,
  1414. EnumerationFlags,
  1415. CriteriaRoute,
  1416. MatchCriteriaAndEnableRoute);
  1417. }
  1418. BOOL
  1419. MatchCriteriaAndEnableRoute (
  1420. IN PV1_REGN_INFO V1Regn,
  1421. IN PRTM_ROUTE_HANDLE V2RouteHandle,
  1422. IN PV1_ENUM_INFO V1Enum
  1423. )
  1424. /*++
  1425. Routine Description:
  1426. Enables/disables route if it matches enumeration criteria.
  1427. We enable or disable a route by adding or removing it
  1428. from the unicast view, as we assume that v1 protocols
  1429. understand only the unicast view. This will work only
  1430. if we enable or disable route owned by caller.
  1431. Enumeration criteria returns only routes owned by caller.
  1432. See RTM_ONLY_OWND_ROUTES in RtmBlockSetRouteEnable.
  1433. Arguments:
  1434. V1Regn - RTM v1 registration info of the caller
  1435. V2RouteHandle - Handle of the route being considered
  1436. V1Enum - Enum info that gives matching criteria
  1437. Return Value:
  1438. TRUE if you have released input route handle, FALSE if not
  1439. --*/
  1440. {
  1441. PRTM_ROUTE_INFO V2RoutePointer;
  1442. RTM_VIEW_SET Views;
  1443. DWORD ChangeFlags;
  1444. BOOL Match;
  1445. DWORD *Flags;
  1446. DWORD Status;
  1447. Match = MatchCriteria(V1Regn, V2RouteHandle, V1Enum);
  1448. if (!Match)
  1449. {
  1450. return FALSE;
  1451. }
  1452. do
  1453. {
  1454. // Do we need to enable or disable the route ?
  1455. V1GetRouteFlags(&V1Enum->CriteriaRoute, V1Regn->ProtocolFamily, Flags);
  1456. //
  1457. // Remove route from unicast view to disable;
  1458. // add it back to the unicast view to enable
  1459. //
  1460. if ((*Flags) & IP_VALID_ROUTE)
  1461. {
  1462. Views = RTM_VIEW_MASK_UCAST;
  1463. }
  1464. else
  1465. {
  1466. Views = RTM_VIEW_MASK_NONE;
  1467. }
  1468. //
  1469. // Only the route's owner can lock and update it
  1470. //
  1471. Status = RtmLockRoute(V1Regn->Rtmv2RegHandle,
  1472. V2RouteHandle,
  1473. TRUE,
  1474. &V2RoutePointer);
  1475. if (Status != NO_ERROR)
  1476. {
  1477. break;
  1478. }
  1479. V2RoutePointer->BelongsToViews = Views;
  1480. // Note that we are not preserving timeout value
  1481. Status = RtmUpdateAndUnlockRoute(V1Regn->Rtmv2RegHandle,
  1482. V2RouteHandle,
  1483. INFINITE,
  1484. NULL,
  1485. 0,
  1486. NULL,
  1487. &ChangeFlags);
  1488. if (Status != NO_ERROR)
  1489. {
  1490. break;
  1491. }
  1492. return FALSE;
  1493. }
  1494. while (FALSE);
  1495. ASSERT(FALSE);
  1496. return FALSE;
  1497. }
  1498. DWORD
  1499. WINAPI
  1500. RtmBlockConvertRoutesToStatic (
  1501. IN HANDLE ClientHandle,
  1502. IN DWORD EnumerationFlags,
  1503. IN PVOID CriteriaRoute
  1504. )
  1505. /*++
  1506. Routine Description:
  1507. Makes the caller the owner of all the routes matching
  1508. the input criteria.
  1509. Changing the owner is done by adding a new route for
  1510. each matching route with the same info. The caller
  1511. is the owner of the new route.
  1512. Arguments:
  1513. ClientHandle - RTM v1 registration handle of caller
  1514. EnumerationFlags - Flags indicating the criteria to match
  1515. CriteriaRoute - The route that we are matching against
  1516. Return Value:
  1517. Status of the operation
  1518. --*/
  1519. {
  1520. PV1_REGN_INFO V1Regn;
  1521. VALIDATE_V1_REGN_HANDLE(ClientHandle, &V1Regn);
  1522. //
  1523. // In accordance with RTMv1, act only on enabled routes
  1524. //
  1525. EnumerationFlags &= ~RTM_INCLUDE_DISABLED_ROUTES;
  1526. //
  1527. // Call block op to add a new route for each matching one.
  1528. //
  1529. return BlockOperationOnRoutes(V1Regn,
  1530. EnumerationFlags,
  1531. CriteriaRoute,
  1532. MatchCriteriaAndChangeOwner);
  1533. }
  1534. BOOL
  1535. MatchCriteriaAndChangeOwner (
  1536. IN PV1_REGN_INFO V1Regn,
  1537. IN PRTM_ROUTE_HANDLE V2RouteHandle,
  1538. IN PV1_ENUM_INFO V1Enum
  1539. )
  1540. /*++
  1541. Routine Description:
  1542. Makes a copy of the route if it matches the enum criteria.
  1543. The new copy of the route will have the caller as its
  1544. owner. The matching route can then be deleted (if needed).
  1545. Arguments:
  1546. V1Regn - RTM v1 registration info of the caller
  1547. V2RouteHandle - Handle of the route being considered
  1548. V1Enum - Enum info that gives matching criteria
  1549. Return Value:
  1550. TRUE if you have released input route handle, FALSE if not
  1551. --*/
  1552. {
  1553. RTM_ENTITY_INFO EntityInfo;
  1554. PRTM_DEST_INFO DestInfo;
  1555. PRTM_ROUTE_INFO V2RouteInfo;
  1556. RTM_NEXTHOP_HANDLE NextHopHandle;
  1557. RTM_NEXTHOP_HANDLE OldNextHop;
  1558. RTM_NEXTHOP_HANDLE OldNeighbour;
  1559. RTM_NEXTHOP_INFO NextHopInfo;
  1560. RTM_VIEW_SET BestInViews;
  1561. ULONG Protocol;
  1562. BOOL Match;
  1563. DWORD ChangeFlags;
  1564. DWORD Status;
  1565. //
  1566. // Get the route's information from RTMv2
  1567. //
  1568. V2RouteInfo =
  1569. ALLOC_ROUTE_INFO(V1Regn->Rtmv2Profile.MaxNextHopsInRoute, 1);
  1570. Status = RtmGetRouteInfo(V1Regn->Rtmv2RegHandle,
  1571. V2RouteHandle,
  1572. V2RouteInfo,
  1573. NULL);
  1574. if (Status != NO_ERROR)
  1575. {
  1576. return FALSE;
  1577. }
  1578. Match = FALSE;
  1579. do
  1580. {
  1581. //
  1582. // Is the route owner already target protocol ?
  1583. //
  1584. if (V2RouteInfo->RouteOwner == V1Regn->Rtmv2RegHandle)
  1585. {
  1586. break;
  1587. }
  1588. //
  1589. // Does it match the criteria route's protocol ?
  1590. //
  1591. if (V1Enum->EnumFlags & RTM_ONLY_THIS_PROTOCOL)
  1592. {
  1593. //
  1594. // Get the protocol type for this route
  1595. //
  1596. Status = RtmGetEntityInfo(V1Regn->Rtmv2RegHandle,
  1597. V2RouteInfo->RouteOwner,
  1598. &EntityInfo);
  1599. if (Status != NO_ERROR)
  1600. {
  1601. break;
  1602. }
  1603. Protocol = EntityInfo.EntityId.EntityProtocolId;
  1604. Status = RtmReleaseEntityInfo(V1Regn->Rtmv2RegHandle,
  1605. &EntityInfo);
  1606. ASSERT(Status == NO_ERROR);
  1607. // Is this the routing protocol we need ?
  1608. if (V1Enum->CriteriaRoute.XxRoute.RR_RoutingProtocol
  1609. != Protocol)
  1610. {
  1611. break;
  1612. }
  1613. }
  1614. //
  1615. // And does it match other criteria in enum ?
  1616. //
  1617. if (V1Enum->EnumFlags & RTM_ONLY_BEST_ROUTES)
  1618. {
  1619. Status = RtmIsBestRoute(V1Regn->Rtmv2RegHandle,
  1620. V2RouteHandle,
  1621. &BestInViews);
  1622. if ((BestInViews & RTM_VIEW_MASK_UCAST) == 0)
  1623. {
  1624. break;
  1625. }
  1626. }
  1627. //
  1628. // We are checking only the first next hop
  1629. // as we expect this function to be used
  1630. // only by V1 protocols on their own routes
  1631. //
  1632. ASSERT(V2RouteInfo->NextHopsList.NumNextHops == 1);
  1633. Status = RtmGetNextHopInfo(V1Regn->Rtmv2RegHandle,
  1634. V2RouteInfo->NextHopsList.NextHops[0],
  1635. &NextHopInfo);
  1636. if (Status != NO_ERROR)
  1637. {
  1638. break;
  1639. }
  1640. #if DBG
  1641. // Do we need to match the nexthop intf ?
  1642. if (V1Enum->EnumFlags & RTM_ONLY_THIS_INTERFACE)
  1643. {
  1644. // Compare this next-hops interface with criteria
  1645. if (NextHopInfo.InterfaceIndex ==
  1646. V1Enum->CriteriaRoute.XxRoute.RR_InterfaceID)
  1647. {
  1648. Match = TRUE;
  1649. }
  1650. // We have already done this filtering in RTM v2
  1651. ASSERT(Match == TRUE);
  1652. }
  1653. #endif
  1654. // Add the same next hop with a different owner
  1655. if (Match)
  1656. {
  1657. NextHopHandle = NULL;
  1658. do
  1659. {
  1660. Status = RtmAddNextHop(V1Regn->Rtmv2RegHandle,
  1661. &NextHopInfo,
  1662. &NextHopHandle,
  1663. &ChangeFlags);
  1664. if (Status != NO_ERROR)
  1665. {
  1666. Match = FALSE;
  1667. break;
  1668. }
  1669. // Allocate this var-size dest-info on the stack
  1670. DestInfo = ALLOC_DEST_INFO(V1Regn->Rtmv2NumViews, 1);
  1671. //
  1672. // Get the destination address corr to handle
  1673. //
  1674. Status = RtmGetDestInfo(V1Regn->Rtmv2RegHandle,
  1675. V2RouteInfo->DestHandle,
  1676. RTM_BEST_PROTOCOL,
  1677. RTM_VIEW_ID_UCAST,
  1678. DestInfo);
  1679. if (Status != NO_ERROR)
  1680. {
  1681. Match = FALSE;
  1682. break;
  1683. }
  1684. //
  1685. // Add this route again with a different owner
  1686. //
  1687. ChangeFlags = (V1Regn->Flags & RTM_PROTOCOL_SINGLE_ROUTE)
  1688. ? RTM_ROUTE_CHANGE_FIRST : 0;
  1689. // Update route with new next hop neighbour
  1690. OldNeighbour = V2RouteInfo->Neighbour;
  1691. V2RouteInfo->Neighbour = NextHopHandle;
  1692. // Update route with new forwarding next hop
  1693. OldNextHop = V2RouteInfo->NextHopsList.NextHops[0];
  1694. V2RouteInfo->NextHopsList.NextHops[0] = NextHopHandle;
  1695. //
  1696. // Add the new route using the RTMv2 API call
  1697. //
  1698. Status = RtmAddRouteToDest(V1Regn->Rtmv2RegHandle,
  1699. NULL,
  1700. &DestInfo->DestAddress,
  1701. V2RouteInfo,
  1702. INFINITE,
  1703. NULL,
  1704. 0,
  1705. NULL,
  1706. &ChangeFlags);
  1707. if (Status != NO_ERROR)
  1708. {
  1709. Match = FALSE;
  1710. }
  1711. //
  1712. // Restore old information nexthop information
  1713. //
  1714. V2RouteInfo->Neighbour = OldNeighbour;
  1715. V2RouteInfo->NextHopsList.NextHops[0] = OldNextHop;
  1716. Status = RtmReleaseDestInfo(V1Regn->Rtmv2RegHandle,
  1717. DestInfo);
  1718. ASSERT(Status == NO_ERROR);
  1719. }
  1720. while (FALSE);
  1721. // If we have a next hop handle, release it
  1722. if (NextHopHandle)
  1723. {
  1724. Status = RtmReleaseNextHops(V1Regn->Rtmv2RegHandle,
  1725. 1,
  1726. &NextHopHandle);
  1727. ASSERT(Status == NO_ERROR);
  1728. }
  1729. }
  1730. Status = RtmReleaseNextHopInfo(V1Regn->Rtmv2RegHandle, &NextHopInfo);
  1731. ASSERT(Status == NO_ERROR);
  1732. }
  1733. while (FALSE);
  1734. #if DELETE_OLD
  1735. //
  1736. // Impersonate previous owner and delete his route
  1737. //
  1738. if (Match)
  1739. {
  1740. Status = RtmDeleteRouteToDest(V2RouteInfo->RouteOwner,
  1741. V2RouteHandle,
  1742. &ChangeFlags);
  1743. if (Status != NO_ERROR)
  1744. {
  1745. // Must have been deleted meanwhile - ignore
  1746. Match = FALSE;
  1747. }
  1748. }
  1749. #else
  1750. Match = FALSE;
  1751. #endif
  1752. ASSERT(SUCCESS(RtmReleaseRouteInfo(V1Regn->Rtmv2RegHandle, V2RouteInfo)));
  1753. return Match;
  1754. }
  1755. DWORD
  1756. BlockOperationOnRoutes (
  1757. IN PV1_REGN_INFO V1Regn,
  1758. IN DWORD EnumerationFlags,
  1759. IN PVOID CriteriaRoute,
  1760. IN PFUNC RouteOperation
  1761. )
  1762. /*++
  1763. Routine Description:
  1764. Performs the route operation specified on each route in
  1765. the table that matches the enumeration criteria.
  1766. The route operation is called with the route handle of
  1767. each matching route. If the operation returns FALSE,
  1768. then the route handle is released, else it is expected
  1769. that the handle was released by the operation itself.
  1770. Arguments:
  1771. V1Regn - RTM v1 registration info of the caller
  1772. EnumerationFlags - Flags indicating the criteria to match
  1773. CriteriaRoute - The route that we are matching against
  1774. RouteOperation - Operation performed on matching routes
  1775. Return Value:
  1776. Status of the operation
  1777. --*/
  1778. {
  1779. HANDLE V1EnumHandle;
  1780. PV1_ENUM_INFO V1Enum;
  1781. PRTM_ROUTE_HANDLE V2RouteHandles;
  1782. UINT NumRoutes;
  1783. UINT i;
  1784. DWORD Status1;
  1785. DWORD Status;
  1786. //
  1787. // Create an enumeration to get all matching routes
  1788. //
  1789. V1EnumHandle = RtmCreateEnumerationHandle(V1Regn->ProtocolFamily,
  1790. EnumerationFlags,
  1791. CriteriaRoute);
  1792. if (V1EnumHandle == NULL)
  1793. {
  1794. return GetLastError();
  1795. }
  1796. VALIDATE_V1_ENUM_HANDLE(V1EnumHandle, &V1Enum);
  1797. //
  1798. // Get list of all matching routes and call operation
  1799. //
  1800. // Allocate this var-size handles array on the stack
  1801. V2RouteHandles = ALLOC_HANDLES(V1Regn->Rtmv2Profile.MaxHandlesInEnum);
  1802. do
  1803. {
  1804. // Get next route in enum, and run operation on it
  1805. NumRoutes = V1Regn->Rtmv2Profile.MaxHandlesInEnum;
  1806. Status = RtmGetEnumRoutes(V1Regn->Rtmv2RegHandle,
  1807. V1Enum->Rtmv2RouteEnum,
  1808. &NumRoutes,
  1809. V2RouteHandles);
  1810. for (i = 0; i < NumRoutes; i++)
  1811. {
  1812. if (!RouteOperation(V1Regn, V2RouteHandles[i], V1Enum))
  1813. {
  1814. // Operation not successful - release handle
  1815. Status1 = RtmReleaseRoutes(V1Regn->Rtmv2RegHandle,
  1816. 1,
  1817. &V2RouteHandles[i]);
  1818. ASSERT(SUCCESS(Status1));
  1819. }
  1820. }
  1821. }
  1822. while (Status == NO_ERROR);
  1823. ASSERT(SUCCESS(RtmCloseEnumerationHandle(V1EnumHandle)));
  1824. return (Status == ERROR_NO_MORE_ROUTES) ? NO_ERROR : Status;
  1825. }
  1826. BOOL
  1827. MatchCriteriaAndCopyRoute (
  1828. IN PV1_REGN_INFO V1Regn,
  1829. IN PRTM_ROUTE_HANDLE V2RouteHandle,
  1830. IN PV1_ENUM_INFO V1Enum OPTIONAL,
  1831. OUT PVOID V1Route OPTIONAL
  1832. )
  1833. /*++
  1834. Routine Description:
  1835. If the input route matches enumeration criteria, it converts
  1836. to a V1 route and copies it to the output buffer.
  1837. Arguments:
  1838. V1Regn - RTM v1 registration info of the caller
  1839. V2RouteHandle - Handle of the route being considered
  1840. V1Enum - Enum info that gives matching criteria
  1841. V1Route - Buffer in which the V1 route is copied
  1842. Return Value:
  1843. TRUE if route matches criteria, and FALSE if it does not
  1844. --*/
  1845. {
  1846. RTM_ENTITY_INFO EntityInfo;
  1847. PRTM_ROUTE_INFO V2RouteInfo;
  1848. RTM_VIEW_SET BestInViews;
  1849. ULONG Protocol;
  1850. BOOL Match;
  1851. DWORD Status;
  1852. //
  1853. // Get the route's information from RTMv2
  1854. //
  1855. V2RouteInfo =
  1856. ALLOC_ROUTE_INFO(V1Regn->Rtmv2Profile.MaxNextHopsInRoute, 1);
  1857. Status = RtmGetRouteInfo(V1Regn->Rtmv2RegHandle,
  1858. V2RouteHandle,
  1859. V2RouteInfo,
  1860. NULL);
  1861. if (Status != NO_ERROR)
  1862. {
  1863. return FALSE;
  1864. }
  1865. //
  1866. // If we have no criteria, we match every route
  1867. //
  1868. if (!ARGUMENT_PRESENT(V1Enum))
  1869. {
  1870. Match = TRUE;
  1871. }
  1872. else
  1873. {
  1874. Match = FALSE;
  1875. do
  1876. {
  1877. if (V1Enum->EnumFlags & RTM_INCLUDE_DISABLED_ROUTES)
  1878. {
  1879. // Is route anything but a unicast or disabled one ?
  1880. if (V2RouteInfo->BelongsToViews & ~RTM_VIEW_MASK_UCAST)
  1881. {
  1882. break;
  1883. }
  1884. }
  1885. //
  1886. // Does it match the criteria route's protocol ?
  1887. //
  1888. if (V1Enum->EnumFlags & RTM_ONLY_THIS_PROTOCOL)
  1889. {
  1890. //
  1891. // Get the protocol type for this route
  1892. //
  1893. Status = RtmGetEntityInfo(V1Regn->Rtmv2RegHandle,
  1894. V2RouteInfo->RouteOwner,
  1895. &EntityInfo);
  1896. if (Status != NO_ERROR)
  1897. {
  1898. break;
  1899. }
  1900. Protocol = EntityInfo.EntityId.EntityProtocolId;
  1901. Status = RtmReleaseEntityInfo(V1Regn->Rtmv2RegHandle,
  1902. &EntityInfo);
  1903. ASSERT(Status == NO_ERROR);
  1904. // Is this the routing protocol we need ?
  1905. if (V1Enum->CriteriaRoute.XxRoute.RR_RoutingProtocol
  1906. != Protocol)
  1907. {
  1908. break;
  1909. }
  1910. }
  1911. //
  1912. // And does it match other criteria in enum ?
  1913. //
  1914. if (V1Enum->EnumFlags & RTM_ONLY_BEST_ROUTES)
  1915. {
  1916. Status = RtmIsBestRoute(V1Regn->Rtmv2RegHandle,
  1917. V2RouteHandle,
  1918. &BestInViews);
  1919. if ((BestInViews & RTM_VIEW_MASK_UCAST) == 0)
  1920. {
  1921. break;
  1922. }
  1923. }
  1924. #if DBG
  1925. if (V1Enum->EnumFlags & RTM_ONLY_THIS_INTERFACE)
  1926. {
  1927. RTM_NEXTHOP_INFO NextHopInfo;
  1928. ULONG IfIndex;
  1929. //
  1930. // We are checking only the first next hop
  1931. // as we expect this function to be used
  1932. // only by V1 protocols on their own routes
  1933. //
  1934. ASSERT(V2RouteInfo->NextHopsList.NumNextHops == 1);
  1935. Status =
  1936. RtmGetNextHopInfo(V1Regn->Rtmv2RegHandle,
  1937. V2RouteInfo->NextHopsList.NextHops[0],
  1938. &NextHopInfo);
  1939. if (Status != NO_ERROR)
  1940. {
  1941. break;
  1942. }
  1943. // Get the interface index for this nexthop
  1944. IfIndex = NextHopInfo.InterfaceIndex;
  1945. Status = RtmReleaseNextHopInfo(V1Regn->Rtmv2RegHandle,
  1946. &NextHopInfo);
  1947. ASSERT(Status == NO_ERROR);
  1948. // Is this the interface that we are enum'ing
  1949. if (IfIndex !=V1Enum->CriteriaRoute.XxRoute.RR_InterfaceID)
  1950. {
  1951. // We have already done this filtering in RTM v2
  1952. ASSERT(FALSE);
  1953. break;
  1954. }
  1955. }
  1956. #endif
  1957. Match = TRUE;
  1958. }
  1959. while (FALSE);
  1960. }
  1961. //
  1962. // If we have a match, then make a copy of this route
  1963. //
  1964. if (Match)
  1965. {
  1966. if (ARGUMENT_PRESENT(V1Route))
  1967. {
  1968. Status = MakeV1RouteFromV2Route(V1Regn, V2RouteInfo, V1Route);
  1969. if (Status != NO_ERROR)
  1970. {
  1971. Match = FALSE;
  1972. }
  1973. }
  1974. }
  1975. Status = RtmReleaseRouteInfo(V1Regn->Rtmv2RegHandle, V2RouteInfo);
  1976. ASSERT(Status == NO_ERROR);
  1977. return Match;
  1978. }
  1979. BOOL
  1980. WINAPI
  1981. RtmIsRoute (
  1982. IN DWORD ProtocolFamily,
  1983. IN PVOID Network,
  1984. OUT PVOID BestRoute OPTIONAL
  1985. )
  1986. /*++
  1987. Routine Description:
  1988. Checks the route table corr. to a protocol family
  1989. for the existence of a route to the input network.
  1990. Arguments:
  1991. ProtocolFamily - Protocol family of the route table
  1992. Network - Network address we are trying to reach
  1993. BestRoute - Best route to the network is filled
  1994. Return Value:
  1995. TRUE if a best route exists, FALSE if not,
  1996. Use GetLastError to check the status code
  1997. --*/
  1998. {
  1999. PV1_REGN_INFO V1Regn;
  2000. RTM_ROUTE_HANDLE V2RouteHandle;
  2001. PRTM_DEST_INFO DestInfo;
  2002. RTM_NET_ADDRESS NetAddr;
  2003. BOOL Match;
  2004. DWORD Status;
  2005. //
  2006. // Validate incoming parameters before action
  2007. //
  2008. if (ProtocolFamily >= RTM_NUM_OF_PROTOCOL_FAMILIES)
  2009. {
  2010. SetLastError(ERROR_INVALID_PARAMETER);
  2011. return FALSE;
  2012. }
  2013. V1Regn = V1Globals.PfRegInfo[ProtocolFamily];
  2014. if (V1Regn == NULL)
  2015. {
  2016. SetLastError(ERROR_INVALID_HANDLE);
  2017. return FALSE;
  2018. }
  2019. // Allocate this var-size dest-info on the stack
  2020. DestInfo = ALLOC_DEST_INFO(V1Regn->Rtmv2NumViews, 1);
  2021. MakeNetAddress(Network, TempUlong, ProtocolFamily, &NetAddr);
  2022. Status = RtmGetExactMatchDestination(V1Regn->Rtmv2RegHandle,
  2023. &NetAddr,
  2024. RTM_BEST_PROTOCOL,
  2025. RTM_VIEW_MASK_UCAST,
  2026. DestInfo);
  2027. if (Status == NO_ERROR)
  2028. {
  2029. //
  2030. // We have a unicast route to the network
  2031. //
  2032. if (ARGUMENT_PRESENT(BestRoute))
  2033. {
  2034. V2RouteHandle = DestInfo->ViewInfo[0].Route;
  2035. ASSERT(V2RouteHandle != NULL);
  2036. // We have no criteria; so pass NULL for it
  2037. Match = MatchCriteriaAndCopyRoute(V1Regn,
  2038. V2RouteHandle,
  2039. NULL,
  2040. BestRoute);
  2041. ASSERT(Match == TRUE);
  2042. }
  2043. Status = RtmReleaseDestInfo(V1Regn->Rtmv2RegHandle, DestInfo);
  2044. ASSERT(Status == NO_ERROR);
  2045. return TRUE;
  2046. }
  2047. return FALSE;
  2048. }
  2049. BOOL
  2050. WINAPI
  2051. RtmLookupIPDestination(
  2052. IN DWORD DestAddr,
  2053. OUT PRTM_IP_ROUTE IPRoute
  2054. )
  2055. /*++
  2056. Routine Description:
  2057. Gets the best non-loopback IP route to the
  2058. input destination address.
  2059. Arguments:
  2060. DestAddr - Network address of the input dest
  2061. IPRoute - Best non-loopback route is filled
  2062. Return Value:
  2063. TRUE if a best route exists, FALSE if not,
  2064. Use GetLastError to check the status code
  2065. --*/
  2066. {
  2067. PV1_REGN_INFO V1Regn;
  2068. RTM_NET_ADDRESS NetAddr;
  2069. PRTM_DEST_INFO DestInfo1;
  2070. PRTM_DEST_INFO DestInfo2;
  2071. DWORD Status;
  2072. //
  2073. // Validate incoming parameters before action
  2074. //
  2075. V1Regn = V1Globals.PfRegInfo[RTM_PROTOCOL_FAMILY_IP];
  2076. if (V1Regn == NULL)
  2077. {
  2078. SetLastError(ERROR_INVALID_HANDLE);
  2079. return FALSE;
  2080. }
  2081. // Allocate this var-size dest-infos on the stack
  2082. DestInfo1 = ALLOC_DEST_INFO(V1Regn->Rtmv2NumViews, 1);
  2083. DestInfo2 = ALLOC_DEST_INFO(V1Regn->Rtmv2NumViews, 1);
  2084. // Convert the V1 addr to a V2 net address format
  2085. MakeHostAddress((PUCHAR)&DestAddr, RTM_PROTOCOL_FAMILY_IP, &NetAddr);
  2086. //
  2087. // Get the best route to the input dest
  2088. //
  2089. Status = RtmGetMostSpecificDestination(V1Regn->Rtmv2RegHandle,
  2090. &NetAddr,
  2091. RTM_BEST_PROTOCOL,
  2092. RTM_VIEW_MASK_UCAST,
  2093. DestInfo1);
  2094. while (Status == NO_ERROR)
  2095. {
  2096. //
  2097. // Check if this route is a non-loopback one
  2098. //
  2099. if (CopyNonLoopbackIPRoute(V1Regn, DestInfo1, IPRoute))
  2100. {
  2101. break;
  2102. }
  2103. //
  2104. // Backtrack up the tree for next best route
  2105. //
  2106. Status = RtmGetLessSpecificDestination(V1Regn->Rtmv2RegHandle,
  2107. DestInfo1->DestHandle,
  2108. RTM_BEST_PROTOCOL,
  2109. RTM_VIEW_MASK_UCAST,
  2110. DestInfo2);
  2111. ASSERT(SUCCESS(RtmReleaseDestInfo(V1Regn->Rtmv2RegHandle, DestInfo1)));
  2112. SWAP_POINTERS(DestInfo1, DestInfo2);
  2113. }
  2114. if (Status == NO_ERROR)
  2115. {
  2116. ASSERT(SUCCESS(RtmReleaseDestInfo(V1Regn->Rtmv2RegHandle, DestInfo1)));
  2117. return TRUE;
  2118. }
  2119. SetLastError(Status);
  2120. return FALSE;
  2121. }
  2122. BOOL
  2123. CopyNonLoopbackIPRoute (
  2124. IN PV1_REGN_INFO V1Regn,
  2125. IN PRTM_DEST_INFO V2DestInfo,
  2126. OUT PVOID V1Route
  2127. )
  2128. /*++
  2129. Routine Description:
  2130. Check if the input destination has a non-
  2131. loopback best route, and if so copy route to
  2132. the output buffer after conversion to v1
  2133. Arguments:
  2134. V1Regn - RTMv1 Registration info of caller
  2135. V2DestInfo - Dest whose route we are checking
  2136. V1Route - Best route is converted to V1
  2137. and filled if it is not-loopack
  2138. Return Value:
  2139. TRUE if best route is non-loopback, or FALSE
  2140. --*/
  2141. {
  2142. RTM_ROUTE_HANDLE V2RouteHandle;
  2143. PRTM_ROUTE_INFO V2RouteInfo;
  2144. BOOL Match;
  2145. ULONG Address;
  2146. DWORD Status;
  2147. //
  2148. // Check if the destination addr is loopback
  2149. // [ Optimized to avoid getting route info ]
  2150. //
  2151. Address = * (ULONG *) V2DestInfo->DestAddress.AddrBits;
  2152. if ((Address & 0x000000FF) == 0x0000007F)
  2153. {
  2154. return FALSE;
  2155. }
  2156. V2RouteHandle = V2DestInfo->ViewInfo[0].Route;
  2157. V2RouteInfo =
  2158. ALLOC_ROUTE_INFO(V1Regn->Rtmv2Profile.MaxNextHopsInRoute, 1);
  2159. // Get the route's information from RTMv2
  2160. Status = RtmGetRouteInfo(V1Regn->Rtmv2RegHandle,
  2161. V2RouteHandle,
  2162. V2RouteInfo,
  2163. NULL);
  2164. if (Status != NO_ERROR)
  2165. {
  2166. return FALSE;
  2167. };
  2168. // If this is a non-loopback route, copy it
  2169. Match = !(V2RouteInfo->Flags & RTM_ROUTE_FLAGS_LOOPBACK);
  2170. if (Match)
  2171. {
  2172. Status = MakeV1RouteFromV2Route(V1Regn, V2RouteInfo, V1Route);
  2173. if (Status != NO_ERROR)
  2174. {
  2175. Match = FALSE;
  2176. }
  2177. }
  2178. Status = RtmReleaseRouteInfo(V1Regn->Rtmv2RegHandle, V2RouteInfo);
  2179. ASSERT(Status == NO_ERROR);
  2180. return Match;
  2181. }
  2182. ULONG
  2183. WINAPI
  2184. RtmGetNetworkCount (
  2185. IN DWORD ProtocolFamily
  2186. )
  2187. /*++
  2188. Routine Description:
  2189. Get the number of networks (same as RTMv2 destinations)
  2190. in the route table corr. to the input protocol family
  2191. Arguments:
  2192. ProtocolFamily - Protocol family of the route table
  2193. Return Value:
  2194. Number of destinations, or 0 (Use GetLastError() here)
  2195. --*/
  2196. {
  2197. RTM_ADDRESS_FAMILY_INFO AddrFamilyInfo;
  2198. PV1_REGN_INFO V1Regn;
  2199. UINT NumEntities;
  2200. DWORD Status;
  2201. do
  2202. {
  2203. //
  2204. // Validate incoming parameters before action
  2205. //
  2206. if (ProtocolFamily >= RTM_NUM_OF_PROTOCOL_FAMILIES)
  2207. {
  2208. Status = ERROR_INVALID_PARAMETER;
  2209. break;
  2210. }
  2211. V1Regn = V1Globals.PfRegInfo[ProtocolFamily];
  2212. if (V1Regn == NULL)
  2213. {
  2214. Status = ERROR_INVALID_HANDLE;
  2215. break;
  2216. }
  2217. //
  2218. // Query the appropriate table for reqd info
  2219. //
  2220. NumEntities = 0;
  2221. Status = RtmGetAddressFamilyInfo(0, // v1 maps to default Instance
  2222. ADDRESS_FAMILY[ProtocolFamily],
  2223. &AddrFamilyInfo,
  2224. &NumEntities,
  2225. NULL);
  2226. if (Status != NO_ERROR)
  2227. {
  2228. break;
  2229. }
  2230. return AddrFamilyInfo.NumDests;
  2231. }
  2232. while (FALSE);
  2233. //
  2234. // Some error occured - clean up and return 0
  2235. //
  2236. SetLastError(Status);
  2237. return 0;
  2238. }
  2239. ULONG
  2240. WINAPI
  2241. RtmGetRouteAge (
  2242. IN PVOID Route
  2243. )
  2244. /*++
  2245. Routine Description:
  2246. Computes the age of the route from its creation
  2247. time and the current time in seconds.
  2248. Assumes that the creation time of the route is
  2249. correctly filled in, which is not the case as
  2250. we are currently not keeping a FILETIME in the
  2251. route to save space. If we do keep time, then
  2252. this function would work without any changes.
  2253. Arguments:
  2254. Route - Route whose age we want.
  2255. Return Value:
  2256. Age of the route in seconds, or FFFFFFFF
  2257. (GetLastError gives error in this case).
  2258. --*/
  2259. {
  2260. ULONGLONG CurTime;
  2261. //
  2262. // This code has been directly copied from RTMv1
  2263. //
  2264. GetSystemTimeAsFileTime((FILETIME *)&CurTime);
  2265. CurTime -= * (PULONGLONG) &(((PRTM_IP_ROUTE)Route)->RR_TimeStamp);
  2266. if (((PULARGE_INTEGER)&CurTime)->HighPart<10000000)
  2267. {
  2268. return (ULONG)(CurTime/10000000);
  2269. }
  2270. else
  2271. {
  2272. SetLastError (ERROR_INVALID_PARAMETER);
  2273. return 0xFFFFFFFF;
  2274. }
  2275. }
  2276. //
  2277. // Common Helper routines
  2278. //
  2279. VOID
  2280. MakeV2RouteFromV1Route (
  2281. IN PV1_REGN_INFO V1Regn,
  2282. IN PVOID V1Route,
  2283. IN PRTM_NEXTHOP_HANDLE V2NextHop,
  2284. OUT PRTM_NET_ADDRESS V2DestAddr OPTIONAL,
  2285. OUT PRTM_ROUTE_INFO V2RouteInfo OPTIONAL
  2286. )
  2287. /*++
  2288. Routine Description:
  2289. Converts a route in RTM v1 format to a route in
  2290. the RTM v2 format (at present for IP only).
  2291. The nexthop for the V2 route should have been
  2292. computed before and passed in as a parameter.
  2293. Also see function 'MakeV2NextHopFromV1Route'.
  2294. The function also returns the destination addr
  2295. along with the RTMv2 route info, as the route
  2296. info itself does not contain the dest address.
  2297. Arguments:
  2298. V1Regn - RTMv1 Registration info of caller
  2299. V1Route - RTMv1 route being converted to V2
  2300. V2NextHop - The V2 nexthop for the V2 route
  2301. V2DestAddr - V2 destination addr is filled here
  2302. V2RouteInfo - V2 route information is filled here
  2303. Return Value:
  2304. None
  2305. --*/
  2306. {
  2307. PRTM_IP_ROUTE IPRoute;
  2308. ULONG TempUlong;
  2309. //
  2310. // Do conversion for IP alone (worry about IPX later)
  2311. //
  2312. IPRoute = (PRTM_IP_ROUTE) V1Route;
  2313. if (ARGUMENT_PRESENT(V2RouteInfo))
  2314. {
  2315. ZeroMemory(V2RouteInfo, sizeof(RTM_ROUTE_INFO));
  2316. // Fill up the V2 Route Info with V1 info
  2317. // Assumes caller is owner of the route
  2318. V2RouteInfo->RouteOwner = V1Regn->Rtmv2RegHandle;
  2319. V2RouteInfo->Neighbour = V2NextHop;
  2320. // Should keep all the V1 flags in the V2 route
  2321. V2RouteInfo->Flags1 =
  2322. (UCHAR) IPRoute->RR_FamilySpecificData.FSD_Flags;
  2323. // The only flag we understand is the valid flag
  2324. // If route is not valid, we add it to no views
  2325. #if DBG
  2326. V2RouteInfo->BelongsToViews = RTM_VIEW_MASK_NONE;
  2327. #endif
  2328. if (V2RouteInfo->Flags1 & IP_VALID_ROUTE)
  2329. {
  2330. V2RouteInfo->BelongsToViews = RTM_VIEW_MASK_UCAST;
  2331. }
  2332. if (IsRouteLoopback(IPRoute))
  2333. {
  2334. V2RouteInfo->Flags = RTM_ROUTE_FLAGS_LOOPBACK;
  2335. }
  2336. switch (IPRoute->RR_FamilySpecificData.FSD_Type)
  2337. {
  2338. case 3:
  2339. V2RouteInfo->Flags |= RTM_ROUTE_FLAGS_LOCAL;
  2340. break;
  2341. case 4:
  2342. V2RouteInfo->Flags |= RTM_ROUTE_FLAGS_REMOTE;
  2343. break;
  2344. }
  2345. V2RouteInfo->PrefInfo.Preference =
  2346. IPRoute->RR_FamilySpecificData.FSD_Priority;
  2347. V2RouteInfo->PrefInfo.Metric =
  2348. IPRoute->RR_FamilySpecificData.FSD_Metric;
  2349. // Only the first DWORD is copied by wrapper
  2350. V2RouteInfo->EntitySpecificInfo =
  2351. (PVOID) (ULONG_PTR) IPRoute->RR_ProtocolSpecificData.PSD_Data[0];
  2352. V2RouteInfo->NextHopsList.NumNextHops = 1;
  2353. V2RouteInfo->NextHopsList.NextHops[0] = V2NextHop;
  2354. }
  2355. // Fill up the V2 Dest Address with V1 info
  2356. if (ARGUMENT_PRESENT(V2DestAddr))
  2357. {
  2358. MakeNetAddressForIP(&IPRoute->RR_Network, TempUlong, V2DestAddr);
  2359. }
  2360. return;
  2361. }
  2362. VOID
  2363. MakeV2NextHopFromV1Route (
  2364. IN PV1_REGN_INFO V1Regn,
  2365. IN PVOID V1Route,
  2366. OUT PRTM_NEXTHOP_INFO V2NextHopInfo
  2367. )
  2368. /*++
  2369. Routine Description:
  2370. Computes RTMv2 next hop info using the nexthop
  2371. address and interface index in the RTMv1 route.
  2372. Arguments:
  2373. V1Regn - RTMv1 Registration info of caller
  2374. V1Route - V1 route that is being considered
  2375. V2NextHopInfo - V2 Next hop info for input route
  2376. Return Value:
  2377. None
  2378. --*/
  2379. {
  2380. PRTM_IP_ROUTE IPRoute;
  2381. ULONG TempUlong;
  2382. ZeroMemory(V2NextHopInfo, sizeof(RTM_NEXTHOP_INFO));
  2383. //
  2384. // Do conversion for IP alone (worry about IPX later)
  2385. //
  2386. IPRoute = (PRTM_IP_ROUTE) V1Route;
  2387. //
  2388. // We ignore the next hop mask in the conversion
  2389. //
  2390. //
  2391. // MakeNetAddressForIP(&IPRoute->RR_NextHopAddress,
  2392. // TempUlong,
  2393. // &V2NextHopInfo->NextHopAddress);
  2394. //
  2395. UNREFERENCED_PARAMETER(TempUlong);
  2396. MakeHostAddressForIP(&IPRoute->RR_NextHopAddress,
  2397. &V2NextHopInfo->NextHopAddress);
  2398. V2NextHopInfo->NextHopOwner = V1Regn->Rtmv2RegHandle;
  2399. V2NextHopInfo->InterfaceIndex = IPRoute->RR_InterfaceID;
  2400. return;
  2401. }
  2402. VOID
  2403. MakeV1RouteFromV2Dest (
  2404. IN PV1_REGN_INFO V1Regn,
  2405. IN PRTM_DEST_INFO DestInfo,
  2406. OUT PVOID V1Route
  2407. )
  2408. /*++
  2409. Routine Description:
  2410. Fills a V1 route buffer with the destination addr
  2411. from the V2 route.
  2412. Arguments:
  2413. V1Regn - RTMv1 Registration info of caller
  2414. DestInfo - Destination info in RTMv2
  2415. V1Route - V1 route that is being filled in
  2416. Return Value:
  2417. None
  2418. --*/
  2419. {
  2420. PRTM_IP_ROUTE IPRoute;
  2421. UINT AddrLen;
  2422. UNREFERENCED_PARAMETER(V1Regn);
  2423. //
  2424. // Do conversion for IP alone (worry about IPX later)
  2425. //
  2426. IPRoute = (PRTM_IP_ROUTE) V1Route;
  2427. ZeroMemory(IPRoute, sizeof(RTM_IP_ROUTE));
  2428. //
  2429. // Get the destination addr for this route
  2430. //
  2431. IPRoute->RR_Network.N_NetNumber =
  2432. * (ULONG *) DestInfo->DestAddress.AddrBits;
  2433. AddrLen = DestInfo->DestAddress.NumBits;
  2434. ASSERT(AddrLen <= 32);
  2435. if (AddrLen != 0)
  2436. {
  2437. IPRoute->RR_Network.N_NetMask =
  2438. RtlUlongByteSwap((~0) << (32 - AddrLen));
  2439. }
  2440. //
  2441. // Fill in dummy family specific data for route
  2442. //
  2443. // We make the route the least preferred - by
  2444. // minimizing its priority and maximizing its
  2445. // metric - we also treat the route as being
  2446. // valid and added to the stack - this will
  2447. // force router manager to delete the route
  2448. // to this dest in the stack if all routes
  2449. // to this destination are deleted from RTM.
  2450. //
  2451. IPRoute->RR_FamilySpecificData.FSD_Priority = (ULONG) 0;
  2452. IPRoute->RR_FamilySpecificData.FSD_Metric =
  2453. IPRoute->RR_FamilySpecificData.FSD_Metric1 = (ULONG) ~0;
  2454. IPRoute->RR_FamilySpecificData.FSD_Flags = (ULONG) ~0;
  2455. return;
  2456. }
  2457. DWORD
  2458. MakeV1RouteFromV2Route (
  2459. IN PV1_REGN_INFO V1Regn,
  2460. IN PRTM_ROUTE_INFO V2RouteInfo,
  2461. OUT PVOID V1Route
  2462. )
  2463. /*++
  2464. Routine Description:
  2465. Converts a route in the RTMv2 format to a V1 route
  2466. ( at present for IP only ).
  2467. Arguments:
  2468. V1Regn - RTMv1 Registration info of caller
  2469. V2RouteInfo - V2 route information being converted
  2470. V1Route - Buffer in which V1 route is filled
  2471. Return Value:
  2472. Status of the operation
  2473. --*/
  2474. {
  2475. RTM_ENTITY_INFO EntityInfo;
  2476. PRTM_DEST_INFO DestInfo;
  2477. PRTM_IP_ROUTE IPRoute;
  2478. RTM_NEXTHOP_INFO NextHopInfo;
  2479. UINT AddrLen;
  2480. DWORD Status;
  2481. //
  2482. // Do conversion for IP alone (worry about IPX later)
  2483. //
  2484. IPRoute = (PRTM_IP_ROUTE) V1Route;
  2485. ZeroMemory(IPRoute, sizeof(RTM_IP_ROUTE));
  2486. //
  2487. // Get the routing protocol for this route
  2488. //
  2489. Status = RtmGetEntityInfo(V1Regn->Rtmv2RegHandle,
  2490. V2RouteInfo->RouteOwner,
  2491. &EntityInfo);
  2492. if (Status != NO_ERROR)
  2493. {
  2494. return Status;
  2495. }
  2496. IPRoute->RR_RoutingProtocol = EntityInfo.EntityId.EntityProtocolId;
  2497. Status = RtmReleaseEntityInfo(V1Regn->Rtmv2RegHandle,
  2498. &EntityInfo);
  2499. ASSERT(Status == NO_ERROR);
  2500. //
  2501. // Get the destination addr for this route
  2502. //
  2503. // Allocate this var-size dest-info on the stack
  2504. DestInfo = ALLOC_DEST_INFO(V1Regn->Rtmv2NumViews, 1);
  2505. Status = RtmGetDestInfo(V1Regn->Rtmv2RegHandle,
  2506. V2RouteInfo->DestHandle,
  2507. RTM_BEST_PROTOCOL,
  2508. RTM_VIEW_ID_UCAST,
  2509. DestInfo);
  2510. if (Status != NO_ERROR)
  2511. {
  2512. return Status;
  2513. }
  2514. IPRoute->RR_Network.N_NetNumber =
  2515. * (ULONG *) DestInfo->DestAddress.AddrBits;
  2516. AddrLen = DestInfo->DestAddress.NumBits;
  2517. ASSERT(AddrLen <= 32);
  2518. if (AddrLen != 0)
  2519. {
  2520. IPRoute->RR_Network.N_NetMask =
  2521. RtlUlongByteSwap((~0) << (32 - AddrLen));
  2522. }
  2523. Status = RtmReleaseDestInfo(V1Regn->Rtmv2RegHandle,
  2524. DestInfo);
  2525. ASSERT(Status == NO_ERROR);
  2526. //
  2527. // Get the next hop address and interface
  2528. //
  2529. ASSERT(V2RouteInfo->NextHopsList.NumNextHops > 0);
  2530. Status = RtmGetNextHopInfo(V1Regn->Rtmv2RegHandle,
  2531. V2RouteInfo->NextHopsList.NextHops[0],
  2532. &NextHopInfo);
  2533. if (Status != NO_ERROR)
  2534. {
  2535. return Status;
  2536. }
  2537. IPRoute->RR_InterfaceID = NextHopInfo.InterfaceIndex;
  2538. IPRoute->RR_NextHopAddress.N_NetNumber =
  2539. * (ULONG *) NextHopInfo.NextHopAddress.AddrBits;
  2540. AddrLen = NextHopInfo.NextHopAddress.NumBits;
  2541. ASSERT(AddrLen <= 32);
  2542. if (AddrLen != 0)
  2543. {
  2544. IPRoute->RR_NextHopAddress.N_NetMask =
  2545. RtlUlongByteSwap((~0) >> (32 - AddrLen));
  2546. }
  2547. Status = RtmReleaseNextHopInfo(V1Regn->Rtmv2RegHandle,
  2548. &NextHopInfo);
  2549. ASSERT(Status == NO_ERROR);
  2550. //
  2551. // Get the family specific data for route
  2552. //
  2553. IPRoute->RR_FamilySpecificData.FSD_Priority =
  2554. V2RouteInfo->PrefInfo.Preference;
  2555. IPRoute->RR_FamilySpecificData.FSD_Metric =
  2556. IPRoute->RR_FamilySpecificData.FSD_Metric1 =
  2557. V2RouteInfo->PrefInfo.Metric;
  2558. IPRoute->RR_FamilySpecificData.FSD_Flags = V2RouteInfo->Flags1;
  2559. if (V2RouteInfo->Flags & RTM_ROUTE_FLAGS_LOCAL)
  2560. {
  2561. IPRoute->RR_FamilySpecificData.FSD_Type = 3;
  2562. }
  2563. else
  2564. if (V2RouteInfo->Flags & RTM_ROUTE_FLAGS_REMOTE)
  2565. {
  2566. IPRoute->RR_FamilySpecificData.FSD_Type = 4;
  2567. }
  2568. //
  2569. // Get the protocol specific data for route
  2570. //
  2571. IPRoute->RR_ProtocolSpecificData.PSD_Data[0] =
  2572. PtrToUlong(V2RouteInfo->EntitySpecificInfo);
  2573. return NO_ERROR;
  2574. }
  2575. #endif // WRAPPER