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.

894 lines
18 KiB

  1. /*++
  2. Copyright (c) 1997 - 98, Microsoft Corporation
  3. Module Name:
  4. rtmobj2.c
  5. Abstract:
  6. Contains routines for managing RTM objects
  7. like Destinations, Routes and Next Hops.
  8. Author:
  9. Chaitanya Kodeboyina (chaitk) 23-Aug-1998
  10. Revision History:
  11. --*/
  12. #include "pchrtm.h"
  13. #pragma hdrstop
  14. DWORD
  15. CreateDest (
  16. IN PADDRFAM_INFO AddrFamilyInfo,
  17. IN PRTM_NET_ADDRESS DestAddress,
  18. OUT PDEST_INFO *NewDest
  19. )
  20. /*++
  21. Routine Description:
  22. Creates a new destination info structure and initializes it.
  23. Arguments:
  24. AddrFamilyInfo - Address family that identifies route table,
  25. DestAddress - Destination network address for new dest,
  26. NewDest - Pointer to the destination info structure
  27. will be returned through this parameter.
  28. Return Value:
  29. Status of the operation
  30. --*/
  31. {
  32. PDEST_INFO Dest;
  33. UINT NumOpaquePtrs;
  34. UINT NumBytes;
  35. UINT NumViews;
  36. DWORD Status;
  37. *NewDest = NULL;
  38. //
  39. // Allocate and initialize a new route info
  40. //
  41. NumOpaquePtrs = AddrFamilyInfo->MaxOpaquePtrs;
  42. NumViews = AddrFamilyInfo->NumberOfViews;
  43. NumBytes = sizeof(DEST_INFO) +
  44. NumOpaquePtrs * sizeof(PVOID) +
  45. (NumViews - 1) * sizeof(Dest->ViewInfo);
  46. Dest = (PDEST_INFO) AllocNZeroObject(NumBytes);
  47. if (Dest == NULL)
  48. {
  49. return ERROR_NOT_ENOUGH_MEMORY;
  50. }
  51. do
  52. {
  53. #if DBG_HDL
  54. Dest->ObjectHeader.TypeSign = DEST_ALLOC;
  55. #endif
  56. // Will be removed when first route on dest is added
  57. INITIALIZE_DEST_REFERENCE(Dest, CREATION_REF);
  58. //
  59. // Initialize change notification bits and list entry
  60. //
  61. Dest->ChangeListLE.Next = NULL;
  62. //
  63. // Initialize the list of routes ont the destination
  64. //
  65. InitializeListHead(&Dest->RouteList);
  66. Dest->NumRoutes = 0;
  67. // Set the opaque ptr dir to memory at the end of dest
  68. Dest->OpaqueInfoPtrs = (PVOID *) ((PUCHAR) Dest +
  69. NumBytes -
  70. NumOpaquePtrs * sizeof(PVOID));
  71. // Set the destination address from the input parameter
  72. CopyMemory(&Dest->DestAddress,
  73. DestAddress,
  74. sizeof(RTM_NET_ADDRESS));
  75. *NewDest = Dest;
  76. return NO_ERROR;
  77. }
  78. while (FALSE);
  79. //
  80. // Some error occured in the initialization , clean up
  81. //
  82. #if DBG_HDL
  83. Dest->ObjectHeader.TypeSign = DEST_FREED;
  84. #endif
  85. FreeObject(Dest);
  86. *NewDest = NULL;
  87. return Status;
  88. }
  89. DWORD
  90. DestroyDest (
  91. IN PDEST_INFO Dest
  92. )
  93. /*++
  94. Routine Description:
  95. Destroys the destination by freeing resources and
  96. deallocating it. This function is called when the
  97. reference count on the dest drops to 0.
  98. Arguments:
  99. Dest - Pointer to the dest being destroyed.
  100. Return Value:
  101. None
  102. --*/
  103. {
  104. ASSERT(Dest->ObjectHeader.RefCount == 0);
  105. ASSERT(Dest->HoldRefCount == 0);
  106. //
  107. // Dynamic lock should have been freed
  108. //
  109. ASSERT(Dest->DestLock == NULL);
  110. //
  111. // Free the memory allocated for dest
  112. //
  113. #if DBG_HDL
  114. Dest->ObjectHeader.TypeSign = DEST_FREED;
  115. #endif
  116. FreeObject(Dest);
  117. return NO_ERROR;
  118. }
  119. DWORD
  120. CreateRoute (
  121. IN PENTITY_INFO Entity,
  122. IN PRTM_ROUTE_INFO RouteInfo,
  123. OUT PROUTE_INFO *NewRoute
  124. )
  125. /*++
  126. Routine Description:
  127. Creates a new route info structure and initializes it.
  128. Arguments:
  129. Entity - Entity creating the new route on a dest,
  130. RouteInfo - Route info for the new route being created,
  131. NewRoute - Pointer to the new route info structure
  132. will be returned through this parameter.
  133. Return Value:
  134. Status of the operation
  135. --*/
  136. {
  137. RTM_NEXTHOP_HANDLE NextHopHandle;
  138. PRTM_ROUTE_INFO Info;
  139. PROUTE_INFO Route;
  140. PNEXTHOP_INFO NextHop;
  141. UINT NumNextHops;
  142. UINT i;
  143. DWORD Status;
  144. *NewRoute = NULL;
  145. //
  146. // Allocate and initialize a new route info
  147. //
  148. NumNextHops = Entity->OwningAddrFamily->MaxNextHopsInRoute;
  149. Route = (PROUTE_INFO) AllocNZeroObject(sizeof(ROUTE_INFO) +
  150. (NumNextHops - 1) *
  151. sizeof(RTM_NEXTHOP_HANDLE));
  152. if (Route == NULL)
  153. {
  154. return ERROR_NOT_ENOUGH_MEMORY;
  155. }
  156. do
  157. {
  158. #if DBG_HDL
  159. Route->ObjectHeader.TypeSign = ROUTE_ALLOC;
  160. #endif
  161. INITIALIZE_ROUTE_REFERENCE(Route, CREATION_REF);
  162. InitializeListHead(&Route->DestLE);
  163. InitializeListHead(&Route->RouteListLE);
  164. //
  165. // Initialize the public half of route info
  166. //
  167. Info = &Route->RouteInfo;
  168. Info->RouteOwner = MAKE_HANDLE_FROM_POINTER(Entity);
  169. REFERENCE_ENTITY(Entity, ROUTE_REF);
  170. if (RouteInfo->Neighbour)
  171. {
  172. NextHop = NEXTHOP_FROM_HANDLE(RouteInfo->Neighbour);
  173. REFERENCE_NEXTHOP(NextHop, ROUTE_REF);
  174. // "Neighbour learnt from" entry is owned by caller
  175. ASSERT((NextHop) &&
  176. (NextHop->NextHopInfo.NextHopOwner == Info->RouteOwner));
  177. Info->Neighbour = RouteInfo->Neighbour;
  178. }
  179. Info->State = RTM_ROUTE_STATE_CREATED;
  180. Info->Flags1 = RouteInfo->Flags1;
  181. Info->Flags = RouteInfo->Flags;
  182. Info->PrefInfo = RouteInfo->PrefInfo;
  183. Info->BelongsToViews = RouteInfo->BelongsToViews;
  184. Info->EntitySpecificInfo = RouteInfo->EntitySpecificInfo;
  185. //
  186. // Make a copy of the next hops list (as much as u can)
  187. //
  188. if (NumNextHops > RouteInfo->NextHopsList.NumNextHops)
  189. {
  190. NumNextHops = RouteInfo->NextHopsList.NumNextHops;
  191. }
  192. Info->NextHopsList.NumNextHops = (USHORT) NumNextHops;
  193. for (i = 0; i < NumNextHops; i++)
  194. {
  195. NextHopHandle = RouteInfo->NextHopsList.NextHops[i];
  196. // Make sure that the next-hop is owned by caller
  197. NextHop = NEXTHOP_FROM_HANDLE(NextHopHandle);
  198. ASSERT((NextHop) &&
  199. (NextHop->NextHopInfo.NextHopOwner == Info->RouteOwner));
  200. Info->NextHopsList.NextHops[i] = NextHopHandle;
  201. REFERENCE_NEXTHOP(NextHop, ROUTE_REF);
  202. }
  203. //
  204. // Return a pointer to the new initialized route
  205. //
  206. *NewRoute = Route;
  207. return NO_ERROR;
  208. }
  209. while (FALSE);
  210. //
  211. // Some error occured in the initialization , clean up
  212. //
  213. #if DBG_HDL
  214. Route->ObjectHeader.TypeSign = ROUTE_FREED;
  215. #endif
  216. FreeObject(Route);
  217. *NewRoute = NULL;
  218. return Status;
  219. }
  220. VOID
  221. ComputeRouteInfoChange(
  222. IN PRTM_ROUTE_INFO OldRouteInfo,
  223. IN PRTM_ROUTE_INFO NewRouteInfo,
  224. IN ULONG PrefChanged,
  225. OUT PULONG RouteInfoChanged,
  226. OUT PULONG ForwardingInfoChanged
  227. )
  228. /*++
  229. Routine Description:
  230. Updates an exising route with new route info. Note that
  231. only the route's owner is allowed to do this.
  232. Arguments:
  233. OldRoute - Old route information (except the PrefInfo and
  234. BelongsToViews info fields already updated),
  235. NewRoute - New route information to update old route with,
  236. PrefChanged - Whether PrefInfo values changed from old to new,
  237. RouteInfoChanged - Whether the route information has changed,
  238. ForwardingInfoChanged - Whether forwarding info has been changed.
  239. Return Value:
  240. None
  241. --*/
  242. {
  243. ULONG DiffFlags;
  244. UINT i;
  245. *RouteInfoChanged = *ForwardingInfoChanged = 0;
  246. do
  247. {
  248. //
  249. // Has the preference changed from old to new ?
  250. //
  251. if (PrefChanged)
  252. {
  253. break;
  254. }
  255. //
  256. // Are the number and handles to next hops same ?
  257. //
  258. if (OldRouteInfo->NextHopsList.NumNextHops !=
  259. NewRouteInfo->NextHopsList.NumNextHops)
  260. {
  261. break;
  262. }
  263. for (i = 0; i < OldRouteInfo->NextHopsList.NumNextHops; i++)
  264. {
  265. if (OldRouteInfo->NextHopsList.NextHops[i] !=
  266. NewRouteInfo->NextHopsList.NextHops[i])
  267. {
  268. break;
  269. }
  270. }
  271. if (i != OldRouteInfo->NextHopsList.NumNextHops)
  272. {
  273. break;
  274. }
  275. //
  276. // Have the forwarding flags changed from old ?
  277. //
  278. DiffFlags = OldRouteInfo->Flags ^ NewRouteInfo->Flags;
  279. if (DiffFlags & RTM_ROUTE_FLAGS_FORWARDING)
  280. {
  281. break;
  282. }
  283. //
  284. // Have non forwarding flags changed from old ?
  285. //
  286. if (DiffFlags)
  287. {
  288. *RouteInfoChanged = 1;
  289. }
  290. return;
  291. }
  292. while (FALSE);
  293. //
  294. // Forwarding info is a subset of route info
  295. //
  296. *ForwardingInfoChanged = *RouteInfoChanged = 1;
  297. return;
  298. }
  299. VOID
  300. CopyToRoute (
  301. IN PENTITY_INFO Entity,
  302. IN PRTM_ROUTE_INFO RouteInfo,
  303. IN PROUTE_INFO Route
  304. )
  305. /*++
  306. Routine Description:
  307. Updates an exising route with new route info. Note that
  308. only the route's owner is allowed to do this.
  309. Arguments:
  310. Entity - Entity that is updating the existing route,
  311. RouteInfo - Route info using which route is being updated,
  312. Route - Route that is being updated with above info.
  313. Return Value:
  314. None
  315. --*/
  316. {
  317. RTM_NEXTHOP_HANDLE NextHopHandle;
  318. PRTM_ROUTE_INFO Info;
  319. PNEXTHOP_INFO NextHop;
  320. UINT NumNextHops;
  321. UINT i;
  322. Info = &Route->RouteInfo;
  323. //
  324. // Update the route with the new information
  325. //
  326. Info->State = RTM_ROUTE_STATE_CREATED;
  327. Info->Flags1 = RouteInfo->Flags1;
  328. Info->Flags = RouteInfo->Flags;
  329. Info->PrefInfo = RouteInfo->PrefInfo;
  330. Info->BelongsToViews = RouteInfo->BelongsToViews;
  331. Info->EntitySpecificInfo = RouteInfo->EntitySpecificInfo;
  332. //
  333. // Update the neighbour "learnt from" field
  334. //
  335. if (Info->Neighbour != RouteInfo->Neighbour)
  336. {
  337. // Free the previous "neighbour learnt from"
  338. if (Info->Neighbour)
  339. {
  340. NextHop = NEXTHOP_FROM_HANDLE(Info->Neighbour);
  341. DEREFERENCE_NEXTHOP(NextHop, ROUTE_REF);
  342. }
  343. // Copy the new neighbour "learnt from" now
  344. if (RouteInfo->Neighbour)
  345. {
  346. NextHop = NEXTHOP_FROM_HANDLE(RouteInfo->Neighbour);
  347. REFERENCE_NEXTHOP(NextHop, ROUTE_REF);
  348. // "Neighbour learnt from" entry is owned by caller
  349. ASSERT((NextHop) &&
  350. (NextHop->NextHopInfo.NextHopOwner == Info->RouteOwner));
  351. }
  352. Info->Neighbour = RouteInfo->Neighbour;
  353. }
  354. //
  355. // Count the number of next-hops you can copy
  356. //
  357. NumNextHops = Entity->OwningAddrFamily->MaxNextHopsInRoute;
  358. if (NumNextHops > RouteInfo->NextHopsList.NumNextHops)
  359. {
  360. NumNextHops = RouteInfo->NextHopsList.NumNextHops;
  361. }
  362. //
  363. // Reference all next-hops that you will copy
  364. //
  365. for (i = 0; i < NumNextHops; i++)
  366. {
  367. NextHopHandle = RouteInfo->NextHopsList.NextHops[i];
  368. NextHop = NEXTHOP_FROM_HANDLE(NextHopHandle);
  369. REFERENCE_NEXTHOP(NextHop, ROUTE_REF);
  370. }
  371. //
  372. // Dereference existing next-hops before update
  373. //
  374. for (i = 0; i < Info->NextHopsList.NumNextHops; i++)
  375. {
  376. NextHopHandle = Info->NextHopsList.NextHops[i];
  377. NextHop = NEXTHOP_FROM_HANDLE(NextHopHandle);
  378. DEREFERENCE_NEXTHOP(NextHop, ROUTE_REF);
  379. }
  380. //
  381. // Make a copy of the next hops in input list
  382. //
  383. Info->NextHopsList.NumNextHops = (USHORT) NumNextHops;
  384. for (i = 0; i < NumNextHops; i++)
  385. {
  386. Info->NextHopsList.NextHops[i] = RouteInfo->NextHopsList.NextHops[i];
  387. }
  388. return;
  389. }
  390. DWORD
  391. DestroyRoute (
  392. IN PROUTE_INFO Route
  393. )
  394. /*++
  395. Routine Description:
  396. Destroys the route by freeing resources and
  397. deallocating it. This function is called when
  398. reference count on the route drops to 0.
  399. Arguments:
  400. Route - Pointer to the route being destroyed.
  401. Return Value:
  402. None
  403. --*/
  404. {
  405. RTM_NEXTHOP_HANDLE NextHopHandle;
  406. PRTM_ROUTE_INFO Info;
  407. PNEXTHOP_INFO NextHop;
  408. PENTITY_INFO Entity;
  409. PDEST_INFO Dest;
  410. UINT i;
  411. ASSERT(Route->ObjectHeader.RefCount == 0);
  412. Info = &Route->RouteInfo;
  413. //
  414. // Dereference all next-hops before delete
  415. //
  416. for (i = 0; i < Info->NextHopsList.NumNextHops; i++)
  417. {
  418. NextHopHandle = Info->NextHopsList.NextHops[i];
  419. NextHop = NEXTHOP_FROM_HANDLE(NextHopHandle);
  420. DEREFERENCE_NEXTHOP(NextHop, ROUTE_REF);
  421. }
  422. //
  423. // Dereference advertising neighbour handle
  424. //
  425. if (Info->Neighbour)
  426. {
  427. NextHop = NEXTHOP_FROM_HANDLE(Info->Neighbour);
  428. DEREFERENCE_NEXTHOP(NextHop, ROUTE_REF);
  429. }
  430. //
  431. // Dereference the owning entity handle
  432. //
  433. Entity = ENTITY_FROM_HANDLE(Info->RouteOwner);
  434. DEREFERENCE_ENTITY(Entity, ROUTE_REF);
  435. //
  436. // Dereference the destination for the route
  437. //
  438. if (Info->DestHandle)
  439. {
  440. Dest = DEST_FROM_HANDLE(Info->DestHandle);
  441. DEREFERENCE_DEST(Dest, ROUTE_REF);
  442. }
  443. //
  444. // Free the resources allocated for the route
  445. //
  446. #if DBG_HDL
  447. Route->ObjectHeader.TypeSign = ROUTE_FREED;
  448. #endif
  449. FreeObject(Route);
  450. return NO_ERROR;
  451. }
  452. DWORD
  453. CreateNextHop (
  454. IN PENTITY_INFO Entity,
  455. IN PRTM_NEXTHOP_INFO NextHopInfo,
  456. OUT PNEXTHOP_INFO *NewNextHop
  457. )
  458. /*++
  459. Routine Description:
  460. Creates a new nexthop info structure and initializes it.
  461. Arguments:
  462. Entity - Entity creating the new nexthop in table,
  463. NextHopInfo - Nexthop info for the nexthop being created,
  464. NewNextHop - Pointer to the new nexthop info structure
  465. will be returned through this parameter.
  466. Return Value:
  467. Status of the operation
  468. --*/
  469. {
  470. PRTM_NEXTHOP_INFO HopInfo;
  471. PNEXTHOP_INFO NextHop;
  472. PDEST_INFO Dest;
  473. *NewNextHop = NULL;
  474. //
  475. // Allocate and initialize a new next hop info
  476. //
  477. NextHop = (PNEXTHOP_INFO) AllocNZeroObject(sizeof(NEXTHOP_INFO));
  478. if (NextHop == NULL)
  479. {
  480. return ERROR_NOT_ENOUGH_MEMORY;
  481. }
  482. #if DBG_HDL
  483. NextHop->ObjectHeader.TypeSign = NEXTHOP_ALLOC;
  484. #endif
  485. INITIALIZE_NEXTHOP_REFERENCE(NextHop, CREATION_REF);
  486. HopInfo = &NextHop->NextHopInfo;
  487. HopInfo->NextHopAddress = NextHopInfo->NextHopAddress;
  488. HopInfo->NextHopOwner = MAKE_HANDLE_FROM_POINTER(Entity);
  489. HopInfo->InterfaceIndex = NextHopInfo->InterfaceIndex;
  490. REFERENCE_ENTITY(Entity, NEXTHOP_REF);
  491. HopInfo->State = RTM_NEXTHOP_STATE_CREATED;
  492. HopInfo->Flags = NextHopInfo->Flags;
  493. HopInfo->EntitySpecificInfo = NextHopInfo->EntitySpecificInfo;
  494. HopInfo->RemoteNextHop = NextHopInfo->RemoteNextHop;
  495. //
  496. // Reference the remote nexthop's destination
  497. //
  498. if (HopInfo->RemoteNextHop)
  499. {
  500. Dest = DEST_FROM_HANDLE(HopInfo->RemoteNextHop);
  501. REFERENCE_DEST(Dest, NEXTHOP_REF);
  502. }
  503. //
  504. // Return a pointer to the new initialized nexthop
  505. //
  506. *NewNextHop = NextHop;
  507. return NO_ERROR;
  508. }
  509. VOID
  510. CopyToNextHop (
  511. IN PENTITY_INFO Entity,
  512. IN PRTM_NEXTHOP_INFO NextHopInfo,
  513. IN PNEXTHOP_INFO NextHop
  514. )
  515. /*++
  516. Routine Description:
  517. Updates an exising nexthop with new nexthop info. Note that
  518. only the nexthop's owner is allowed to do this.
  519. Arguments:
  520. Entity - Entity that is updating the existing nexthop,
  521. NextHopInfo - Info using which nexthop is being updated,
  522. NextHop - Nexthop that is being updated with above info.
  523. Return Value:
  524. None
  525. --*/
  526. {
  527. PRTM_NEXTHOP_INFO HopInfo;
  528. PDEST_INFO Dest;
  529. UNREFERENCED_PARAMETER(Entity);
  530. HopInfo = &NextHop->NextHopInfo;
  531. //
  532. // Update the nexthop with the new information
  533. //
  534. HopInfo->Flags = NextHopInfo->Flags;
  535. HopInfo->EntitySpecificInfo = NextHopInfo->EntitySpecificInfo;
  536. if (HopInfo->RemoteNextHop != NextHopInfo->RemoteNextHop)
  537. {
  538. // Dereference the old next hop and reference new one
  539. if (HopInfo->RemoteNextHop)
  540. {
  541. Dest = DEST_FROM_HANDLE(HopInfo->RemoteNextHop);
  542. DEREFERENCE_DEST(Dest, NEXTHOP_REF);
  543. }
  544. HopInfo->RemoteNextHop = NextHopInfo->RemoteNextHop;
  545. if (HopInfo->RemoteNextHop)
  546. {
  547. Dest = DEST_FROM_HANDLE(HopInfo->RemoteNextHop);
  548. REFERENCE_DEST(Dest, NEXTHOP_REF);
  549. }
  550. }
  551. return;
  552. }
  553. DWORD
  554. DestroyNextHop (
  555. IN PNEXTHOP_INFO NextHop
  556. )
  557. /*++
  558. Routine Description:
  559. Destroys the nexthop by freeing resources and
  560. deallocating it. This function is called when
  561. reference count on the nexthop drops to 0.
  562. Arguments:
  563. Nexthop - Pointer to the nexthop being destroyed.
  564. Return Value:
  565. None
  566. --*/
  567. {
  568. PRTM_NEXTHOP_INFO HopInfo;
  569. PDEST_INFO Dest;
  570. PENTITY_INFO Entity;
  571. ASSERT(NextHop->ObjectHeader.RefCount == 0);
  572. HopInfo = &NextHop->NextHopInfo;
  573. //
  574. // Dereference remote nexthop's destination
  575. //
  576. if (HopInfo->RemoteNextHop)
  577. {
  578. Dest = DEST_FROM_HANDLE(HopInfo->RemoteNextHop);
  579. DEREFERENCE_DEST(Dest, NEXTHOP_REF);
  580. }
  581. Entity = ENTITY_FROM_HANDLE(HopInfo->NextHopOwner);
  582. DEREFERENCE_ENTITY(Entity, NEXTHOP_REF);
  583. //
  584. // Free the memory allocated for the next-hop
  585. //
  586. #if DBG_HDL
  587. NextHop->ObjectHeader.TypeSign = NEXTHOP_FREED;
  588. #endif
  589. FreeObject(NextHop);
  590. return NO_ERROR;
  591. }