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.

1951 lines
55 KiB

  1. #include "allinc.h"
  2. DWORD
  3. RtmEventCallback (
  4. IN RTM_ENTITY_HANDLE hRtmHandle,
  5. IN RTM_EVENT_TYPE retEvent,
  6. IN PVOID pContext1,
  7. IN PVOID pContext2
  8. )
  9. /*++
  10. Routine Description:
  11. This callback is given by RTM when we have changed dests
  12. to process. We just queue a work item to process changed
  13. destinations.
  14. Arguments:
  15. hRtmHandle - Handle that we got during registration
  16. retEvent - Event type - we only handle events of
  17. type "more changes available" for now
  18. pContext1 - Notification handle on which changes
  19. are available
  20. pContext2 - Context supplied during notification
  21. registration time
  22. Return Value:
  23. Status of the operation.
  24. --*/
  25. {
  26. DWORD dwResult;
  27. // Only "change notifications available" is supported
  28. if (retEvent != RTM_CHANGE_NOTIFICATION)
  29. {
  30. return ERROR_NOT_SUPPORTED;
  31. }
  32. return ((HANDLE) pContext1) == g_hNotification ?
  33. ProcessChanges(g_hNotification) :
  34. ProcessDefaultRouteChanges( g_hDefaultRouteNotification );
  35. }
  36. DWORD
  37. WINAPI
  38. ProcessChanges (
  39. IN HANDLE hNotifyHandle
  40. )
  41. /*++
  42. Routine Description:
  43. Upon learning that we have changed destinations to
  44. process, this function gets called. We retrieve all
  45. destinations to process and take appropriate action.
  46. Arguments:
  47. hRtmHandle - RTM registration handle
  48. hNotifyHandle - Handle correponding to the change notification
  49. that is being signalled
  50. Return Value:
  51. Status of the operation.
  52. --*/
  53. {
  54. PRTM_DEST_INFO pDestInfo;
  55. PRTM_ROUTE_INFO pRouteInfo;
  56. DWORD dwDests;
  57. DWORD dwResult;
  58. BOOL bMark = FALSE;
  59. TraceEnter("ProcessChanges");
  60. pRouteInfo = HeapAlloc(
  61. IPRouterHeap,
  62. 0,
  63. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  64. );
  65. if (pRouteInfo == NULL)
  66. {
  67. Trace1(
  68. ERR, "ProcessChanges : error allocating %d bytes for "
  69. "route info",
  70. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  71. );
  72. TraceLeave("ProcessChanges");
  73. return ERROR_NOT_ENOUGH_MEMORY;
  74. }
  75. pDestInfo = HeapAlloc(
  76. IPRouterHeap,
  77. 0,
  78. RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews)
  79. );
  80. if (pDestInfo == NULL)
  81. {
  82. Trace1(
  83. ERR, "ProcessChanges : error allocating %d bytes for "
  84. "dest. info",
  85. RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews)
  86. );
  87. HeapFree(IPRouterHeap, 0, pRouteInfo);
  88. TraceLeave("ProcessChanges");
  89. return ERROR_NOT_ENOUGH_MEMORY;
  90. }
  91. dwDests = 1;
  92. // Get each changed dest from the table
  93. do
  94. {
  95. RtmGetChangedDests(g_hLocalRoute,
  96. hNotifyHandle,
  97. &dwDests,
  98. pDestInfo);
  99. if (dwDests < 1)
  100. {
  101. break;
  102. }
  103. //
  104. // For default routes, mark the route so that future changes
  105. // are managed by ProcessDefaultRouteChanges.
  106. //
  107. // We need to do this here so that default routes added by
  108. // routing protocols RIP/OSPF are marked for change notification
  109. // These default routes are added by entities other than
  110. // RouterManager. Default routes added by RM i.e STATIC,
  111. // AUTO-STATIC and NETMGMT default routes are already marked for
  112. // change notification when they are added by RM.
  113. //
  114. // By marking routing protocol default routes here we make sure
  115. // that all default routes are subsequently handled by marked changed
  116. // mechanism (ProcessDefaultRouteChanges).
  117. //
  118. if (pDestInfo->DestAddress.NumBits is 0)
  119. {
  120. TraceRoute2(
  121. ROUTE, "Checking dest %d.%d.%d.%d/%d is marked",
  122. PRINT_IPADDR(*(ULONG *)pDestInfo->DestAddress.AddrBits),
  123. PRINT_IPADDR(pDestInfo->DestAddress.NumBits)
  124. );
  125. dwResult = RtmIsMarkedForChangeNotification(
  126. g_hNetMgmtRoute,
  127. g_hDefaultRouteNotification,
  128. pDestInfo->DestHandle,
  129. &bMark
  130. );
  131. if (dwResult is NO_ERROR)
  132. {
  133. if (bMark)
  134. {
  135. //
  136. // default route is already marked, nothing further
  137. // to do here. This default route change will be
  138. // handled by ProcessDefaultRouteChanges
  139. //
  140. TraceRoute0(
  141. ROUTE,
  142. "ProcessChanges : Route 0/0 is already marked"
  143. );
  144. RtmReleaseChangedDests(g_hLocalRoute,
  145. hNotifyHandle,
  146. dwDests,
  147. pDestInfo);
  148. continue;
  149. }
  150. //
  151. // Default route is not marked, mark it
  152. //
  153. dwResult = RtmMarkDestForChangeNotification(
  154. g_hNetMgmtRoute,
  155. g_hDefaultRouteNotification,
  156. pDestInfo->DestHandle,
  157. TRUE
  158. );
  159. if (dwResult isnot NO_ERROR)
  160. {
  161. //
  162. // Failed to mark 0/0 route. The consequence is that
  163. // only best route changes are processed. We will
  164. // have to live with the fact that we cannot
  165. // install multiple NETMGMT default routes since
  166. // this is performed by the mark dest. change
  167. // processing (in ProcessDefaultRouteChanges)
  168. //
  169. Trace1(
  170. ERR,
  171. "ProcessChanges: error %d marking default route",
  172. dwResult
  173. );
  174. }
  175. }
  176. else
  177. {
  178. //
  179. // Failed to check is 0/0 destination has been
  180. // marked for change notification
  181. // - Refer previous comment
  182. //
  183. Trace1(
  184. ERR,
  185. "ProcessChanges: error %d checking if default route "
  186. "marked",
  187. dwResult
  188. );
  189. }
  190. }
  191. // Check if we have a route in Unicast view
  192. if (pDestInfo->BelongsToViews & RTM_VIEW_MASK_UCAST)
  193. {
  194. // This is either a new or update route
  195. // Update the same route in KM Frwder
  196. ASSERT(pDestInfo->ViewInfo[0].ViewId is RTM_VIEW_ID_UCAST);
  197. dwResult = RtmGetRouteInfo(g_hLocalRoute,
  198. pDestInfo->ViewInfo[0].Route,
  199. pRouteInfo,
  200. NULL);
  201. // An error mean route just got deleted
  202. // Ignore this change as it is obsolete
  203. if (dwResult is NO_ERROR)
  204. {
  205. ChangeRouteWithForwarder(&pDestInfo->DestAddress,
  206. pRouteInfo,
  207. TRUE,
  208. TRUE);
  209. RtmReleaseRouteInfo(g_hLocalRoute,
  210. pRouteInfo);
  211. }
  212. }
  213. else
  214. {
  215. // The last UCAST route has been deleted
  216. // Delete the same route from KM Frwder
  217. ChangeRouteWithForwarder(&pDestInfo->DestAddress,
  218. NULL,
  219. FALSE,
  220. TRUE);
  221. }
  222. RtmReleaseChangedDests(g_hLocalRoute,
  223. hNotifyHandle,
  224. dwDests,
  225. pDestInfo);
  226. }
  227. while (TRUE);
  228. HeapFree(IPRouterHeap, 0, pRouteInfo);
  229. HeapFree(IPRouterHeap, 0, pDestInfo);
  230. TraceLeave("ProcessChanges");
  231. return NO_ERROR;
  232. }
  233. DWORD
  234. WINAPI
  235. ProcessDefaultRouteChanges(
  236. IN HANDLE hNotifyHandle
  237. )
  238. /*++
  239. Routine Description:
  240. This function is invoked in response to changes to
  241. the default route. If the best default route is owned
  242. by protocol PROTO_IP_NETMGMT enumerate all PROTO_IP_NETMGMT
  243. routes for default route 0/0 and set them as one
  244. multihop route to the forwarder
  245. Arguments:
  246. hRtmHandle - RTM registration handle
  247. hNotifyHandle - Handle correponding to the change notification
  248. that is being signalled
  249. Return Value:
  250. NO_ERROR - Success
  251. System error code - Otherwise
  252. --*/
  253. {
  254. PRTM_DEST_INFO pDestInfo;
  255. PRTM_ROUTE_INFO pRouteInfo;
  256. DWORD dwDests;
  257. DWORD dwResult;
  258. TraceEnter("ProcessDefaultRouteChanges");
  259. pRouteInfo = HeapAlloc(
  260. IPRouterHeap,
  261. 0,
  262. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  263. );
  264. if (pRouteInfo == NULL)
  265. {
  266. Trace1(
  267. ERR, "ProcessDefaultRouteChanges : error allocating %d bytes for "
  268. "route info",
  269. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  270. );
  271. TraceLeave("ProcessDefaultRouteChanges");
  272. return ERROR_NOT_ENOUGH_MEMORY;
  273. }
  274. pDestInfo = HeapAlloc(
  275. IPRouterHeap,
  276. 0,
  277. RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews)
  278. );
  279. if (pDestInfo == NULL)
  280. {
  281. Trace1(
  282. ERR, "ProcessDefaultRouteChanges : error allocating %d bytes for "
  283. "dest. info",
  284. RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews)
  285. );
  286. HeapFree(IPRouterHeap, 0, pRouteInfo);
  287. TraceLeave("ProcessDefaultRouteChanges");
  288. return ERROR_NOT_ENOUGH_MEMORY;
  289. }
  290. do
  291. {
  292. //
  293. // retreive changed dests
  294. //
  295. dwDests = 1;
  296. dwResult = RtmGetChangedDests(
  297. g_hNetMgmtRoute,
  298. hNotifyHandle,
  299. &dwDests,
  300. pDestInfo
  301. );
  302. if ((dwResult isnot NO_ERROR) and
  303. (dwResult isnot ERROR_NO_MORE_ITEMS))
  304. {
  305. Trace1(
  306. ERR,
  307. "ProcessDefaultRouteChanges: error %d retrieving changed dests",
  308. dwResult
  309. );
  310. break;
  311. }
  312. if (dwDests < 1)
  313. {
  314. //
  315. // no more dests to enumerate
  316. //
  317. break;
  318. }
  319. do
  320. {
  321. //
  322. // Make sure this the default route 0/0. This functions
  323. // only processes default route changes.
  324. //
  325. if ((pDestInfo->DestAddress.NumBits isnot 0) or
  326. (*((ULONG *)pDestInfo->DestAddress.AddrBits) isnot 0))
  327. {
  328. Trace2(
  329. ERR,
  330. "ProcessDefaultRouteChanges: Not default route %d.%d.%d.%d/%d",
  331. PRINT_IPADDR(*((ULONG *)pDestInfo->DestAddress.AddrBits)),
  332. pDestInfo->DestAddress.NumBits
  333. );
  334. break;
  335. }
  336. //
  337. // If all routes to 0/0 have been deleted,
  338. // delete it from the forwarder too.
  339. //
  340. if (!(pDestInfo->BelongsToViews & RTM_VIEW_MASK_UCAST))
  341. {
  342. dwResult = ChangeRouteWithForwarder(
  343. &(pDestInfo->DestAddress),
  344. NULL,
  345. FALSE,
  346. TRUE
  347. );
  348. break;
  349. }
  350. //
  351. // A route to 0/0 was added/updated
  352. //
  353. if (pDestInfo->ViewInfo[0].Owner isnot g_hNetMgmtRoute)
  354. {
  355. //
  356. // Default route is not owned by PROTO_IP_NETMGT
  357. // Add only the best route to forwarder
  358. //
  359. TraceRoute1(
  360. ROUTE,
  361. "ProcessDefaultRouteChanges: Adding non-NetMgmt"
  362. " route to forwarder, owner RTM handle 0x%x",
  363. pDestInfo->ViewInfo[0].Owner
  364. );
  365. dwResult = RtmGetRouteInfo(
  366. g_hNetMgmtRoute,
  367. pDestInfo->ViewInfo[0].Route,
  368. pRouteInfo,
  369. NULL
  370. );
  371. if (dwResult is NO_ERROR)
  372. {
  373. ChangeRouteWithForwarder(
  374. &pDestInfo->DestAddress,
  375. pRouteInfo,
  376. TRUE,
  377. TRUE
  378. );
  379. dwResult = RtmReleaseRouteInfo(
  380. g_hNetMgmtRoute,
  381. pRouteInfo
  382. );
  383. if (dwResult isnot NO_ERROR)
  384. {
  385. Trace1(
  386. ERR,
  387. "ProcessDefaultRouteChanges: Failed "
  388. "to release route info",
  389. dwResult
  390. );
  391. }
  392. }
  393. break;
  394. }
  395. //
  396. // Default route owned by PROTO_IP_NETMGMT
  397. //
  398. //
  399. // First delete existing 0/0 from the TCP/IP forwarder
  400. //
  401. dwResult = ChangeRouteWithForwarder(
  402. &(pDestInfo->DestAddress),
  403. NULL,
  404. FALSE,
  405. TRUE
  406. );
  407. if (dwResult isnot NO_ERROR)
  408. {
  409. Trace1(
  410. ERR,
  411. "ProcessDefaultRouteChanges: error %d deleting "
  412. "old NetMgmt default routes from forwarder",
  413. dwResult
  414. );
  415. // break;
  416. }
  417. //
  418. // Second add all NETMGMT 0/0 to the TCP/IP forwarder
  419. //
  420. AddNetmgmtDefaultRoutesToForwarder(pDestInfo);
  421. } while( FALSE );
  422. //
  423. // release handles to changed destinations
  424. //
  425. dwResult = RtmReleaseChangedDests(
  426. g_hNetMgmtRoute,
  427. hNotifyHandle,
  428. dwDests,
  429. pDestInfo
  430. );
  431. if (dwResult isnot NO_ERROR)
  432. {
  433. Trace1(
  434. ERR,
  435. "ProcessDefaultRouteChanges: error %d releasing dests ",
  436. dwResult
  437. );
  438. }
  439. } while ( TRUE );
  440. HeapFree(IPRouterHeap, 0, pRouteInfo);
  441. HeapFree(IPRouterHeap, 0, pDestInfo);
  442. TraceLeave("ProcessDefaultRouteChanges");
  443. return dwResult;
  444. }
  445. DWORD
  446. WINAPI
  447. AddNetmgmtDefaultRoutesToForwarder(
  448. PRTM_DEST_INFO pDestInfo
  449. )
  450. /*++
  451. Routine Description:
  452. This routine enumerates the routes to 0/0 added by protocol
  453. PROTO_IP_NETMGT and adds them to the forwarder. This routine
  454. is invoked in response to any change to the default route
  455. If the best default route is owned by PROTO_IP_NETMGMT, all
  456. PROTO_IP_NETMGMT default routes are added to the TCP/IP
  457. forwarder.
  458. This is required since the TCP/IP stack does dead gateway
  459. detection and that required multiple default routes if
  460. present to be installed in the stack.
  461. An implicit assumption here is that PROTO_IP_NETMGMT routes
  462. alone merit this treatment. In case of static or other
  463. protocol generated 0/0 routes, only the best route is
  464. added to the stack. It is assumed that in the later case(s)
  465. the administrator (for static routes) or the protocol has
  466. a better idea of routing and so the dead gateway detection
  467. is suppressed in the stack by the addition of the best route
  468. to 0/0 alone.
  469. Arguments:
  470. pDestInfo - RTM destination info structure of 0/0 route
  471. Return Value :
  472. NO_ERROR - Sucess
  473. Win32 error code - Otherwise
  474. --*/
  475. {
  476. DWORD dwResult, dwNumHandles = 0, i;
  477. BOOL bRelEnum = FALSE, bRelRoutes = FALSE;
  478. PRTM_ROUTE_INFO pRouteInfo;
  479. PRTM_ROUTE_HANDLE pHandles;
  480. RTM_ENUM_HANDLE hRouteEnum;
  481. dwNumHandles = pDestInfo->ViewInfo[0].NumRoutes;
  482. pHandles = HeapAlloc(
  483. IPRouterHeap,
  484. 0,
  485. dwNumHandles * sizeof(RTM_ROUTE_HANDLE)
  486. );
  487. if (pHandles == NULL)
  488. {
  489. Trace1(
  490. ERR,
  491. "AddNetmgmtDefaultRoutesToForwarder: error allocating %d bytes"
  492. "for route handles",
  493. dwNumHandles * sizeof(RTM_ROUTE_HANDLE)
  494. );
  495. return ERROR_NOT_ENOUGH_MEMORY;
  496. }
  497. pRouteInfo = HeapAlloc(
  498. IPRouterHeap,
  499. 0,
  500. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  501. );
  502. if (pRouteInfo == NULL)
  503. {
  504. Trace1(
  505. ERR,
  506. "AddNetmgmtDefaultRoutesToForwarder: error allocating %d bytes"
  507. "for route info",
  508. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  509. );
  510. HeapFree(IPRouterHeap, 0, pHandles);
  511. return ERROR_NOT_ENOUGH_MEMORY;
  512. }
  513. do
  514. {
  515. //
  516. // Enumerate and add all NETMGMT routes to the forwarder
  517. //
  518. dwResult = RtmCreateRouteEnum(
  519. g_hNetMgmtRoute,
  520. pDestInfo->DestHandle,
  521. RTM_VIEW_MASK_UCAST,
  522. RTM_ENUM_OWN_ROUTES,
  523. NULL,
  524. 0,
  525. NULL,
  526. 0,
  527. &hRouteEnum
  528. );
  529. if (dwResult isnot NO_ERROR)
  530. {
  531. Trace1(
  532. ERR,
  533. "AddNetmgmtDefaultRoutesToForwarder: error %d creating route "
  534. "enumeration",
  535. dwResult
  536. );
  537. break;
  538. }
  539. bRelEnum = TRUE;
  540. dwResult = RtmGetEnumRoutes(
  541. g_hNetMgmtRoute,
  542. hRouteEnum,
  543. &dwNumHandles,
  544. pHandles
  545. );
  546. if (dwResult isnot NO_ERROR)
  547. {
  548. Trace1(
  549. ERR,
  550. "ProcessDefaultRouteChanges:error %d enumerating "
  551. "routes",
  552. dwResult
  553. );
  554. break;
  555. }
  556. bRelRoutes = TRUE;
  557. //
  558. // Change route with the forwarder
  559. //
  560. for (i = 0; i < dwNumHandles; i++)
  561. {
  562. dwResult = RtmGetRouteInfo(
  563. g_hNetMgmtRoute,
  564. pHandles[i],
  565. pRouteInfo,
  566. NULL
  567. );
  568. if (dwResult is NO_ERROR)
  569. {
  570. ChangeRouteWithForwarder(
  571. &(pDestInfo->DestAddress),
  572. pRouteInfo,
  573. TRUE,
  574. FALSE
  575. );
  576. dwResult = RtmReleaseRouteInfo(
  577. g_hNetMgmtRoute,
  578. pRouteInfo
  579. );
  580. if (dwResult isnot NO_ERROR)
  581. {
  582. Trace1(
  583. ERR,
  584. "ProcessDefaultRouteChanges: error %d releasing "
  585. "route info ",
  586. dwResult
  587. );
  588. }
  589. }
  590. else
  591. {
  592. Trace2(
  593. ERR,
  594. "ProcessDefaultRouteChanges: error %d getting route "
  595. "info for route %d",
  596. dwResult, i
  597. );
  598. }
  599. }
  600. } while( FALSE );
  601. //
  602. // Release handles
  603. //
  604. if (bRelRoutes)
  605. {
  606. Trace0(ROUTE, "Releasing routes to 0/0");
  607. dwResult = RtmReleaseRoutes(
  608. g_hNetMgmtRoute,
  609. dwNumHandles,
  610. pHandles
  611. );
  612. if (dwResult isnot NO_ERROR)
  613. {
  614. Trace1(
  615. ERR,
  616. "ProcessDefaultRouteChanges: error %d deleting enum "
  617. "handle",
  618. dwResult
  619. );
  620. }
  621. }
  622. if (bRelEnum)
  623. {
  624. Trace0(ROUTE, "Releasing route enum for 0/0");
  625. dwResult = RtmDeleteEnumHandle(
  626. g_hNetMgmtRoute,
  627. hRouteEnum
  628. );
  629. if (dwResult isnot NO_ERROR)
  630. {
  631. Trace1(
  632. ERR,
  633. "ProcessDefaultRouteChanges: error %d deleting enum "
  634. "handle",
  635. dwResult
  636. );
  637. }
  638. }
  639. HeapFree(IPRouterHeap, 0, pHandles);
  640. HeapFree(IPRouterHeap, 0, pRouteInfo);
  641. return dwResult;
  642. }
  643. DWORD
  644. AddRtmRoute (
  645. IN HANDLE hRtmHandle,
  646. IN PINTERFACE_ROUTE_INFO pRtInfo,
  647. IN DWORD dwRouteFlags,
  648. IN DWORD dwNextHopMask,
  649. IN DWORD dwTimeToLive,
  650. OUT HANDLE *phRtmRoute
  651. )
  652. /*++
  653. Routine Description:
  654. Adds a route to RTM with the specified route information.
  655. Arguments:
  656. hRtmHandle - RTM registration handle used in RTM calls
  657. pRtInfo -
  658. dwNextHopMask -
  659. dwTimeToLive - Time for which the route is kept in RTM
  660. before being deleted (value is seconds).
  661. Return Value:
  662. Status of the operation.
  663. --*/
  664. {
  665. PRTM_NET_ADDRESS pDestAddr;
  666. PRTM_ROUTE_INFO pRouteInfo;
  667. RTM_NEXTHOP_INFO rniInfo;
  668. DWORD dwFlags;
  669. DWORD dwResult;
  670. HANDLE hNextHopHandle;
  671. PADAPTER_INFO pBinding;
  672. // Initialize output before caling ops
  673. if (ARGUMENT_PRESENT(phRtmRoute))
  674. {
  675. *phRtmRoute = NULL;
  676. }
  677. pDestAddr = HeapAlloc(
  678. IPRouterHeap,
  679. 0,
  680. sizeof(RTM_NET_ADDRESS)
  681. );
  682. if (pDestAddr == NULL)
  683. {
  684. Trace1(
  685. ERR,
  686. "AddRtmRoute : error allocating %d bytes"
  687. "for dest. address",
  688. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  689. );
  690. return ERROR_NOT_ENOUGH_MEMORY;
  691. }
  692. pRouteInfo = HeapAlloc(
  693. IPRouterHeap,
  694. 0,
  695. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  696. );
  697. if (pRouteInfo == NULL)
  698. {
  699. Trace1(
  700. ERR,
  701. "AddRtmRoute : error allocating %d bytes"
  702. "for route info",
  703. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  704. );
  705. HeapFree(IPRouterHeap, 0, pDestAddr);
  706. return ERROR_NOT_ENOUGH_MEMORY;
  707. }
  708. //
  709. // Add a next hop if not already present
  710. //
  711. RTM_IPV4_MAKE_NET_ADDRESS(&rniInfo.NextHopAddress,
  712. pRtInfo->dwRtInfoNextHop,
  713. 32);
  714. rniInfo.InterfaceIndex = pRtInfo->dwRtInfoIfIndex;
  715. rniInfo.EntitySpecificInfo = (PVOID) (ULONG_PTR)dwNextHopMask;
  716. rniInfo.Flags = 0;
  717. rniInfo.RemoteNextHop = NULL;
  718. hNextHopHandle = NULL;
  719. dwResult = RtmAddNextHop(hRtmHandle,
  720. &rniInfo,
  721. &hNextHopHandle,
  722. &dwFlags);
  723. if (dwResult is NO_ERROR)
  724. {
  725. TraceRoute2(
  726. ROUTE, "Route to %d.%d.%d.%d/%d.%d.%d.%d",
  727. PRINT_IPADDR(pRtInfo->dwRtInfoDest),
  728. PRINT_IPADDR(pRtInfo->dwRtInfoMask)
  729. );
  730. TraceRoute4(
  731. ROUTE, "Next Hop %d.%d.%d.%d/%d.%d.%d.%d, If 0x%x, handle is 0x%x",
  732. PRINT_IPADDR(pRtInfo->dwRtInfoNextHop),
  733. PRINT_IPADDR(dwNextHopMask),
  734. pRtInfo->dwRtInfoIfIndex,
  735. hNextHopHandle
  736. );
  737. dwResult = ConvertRouteInfoToRtm(hRtmHandle,
  738. pRtInfo,
  739. hNextHopHandle,
  740. dwRouteFlags,
  741. pDestAddr,
  742. pRouteInfo);
  743. if (dwResult is NO_ERROR)
  744. {
  745. //
  746. // If we are adding a non-dod route we should
  747. // adjust the state of the route to match
  748. // that of the interface it is being added on
  749. //
  750. if ((hRtmHandle == g_hNonDodRoute) ||
  751. (hRtmHandle == g_hNetMgmtRoute))
  752. {
  753. //
  754. // Find the binding given the interface id
  755. //
  756. ENTER_READER(BINDING_LIST);
  757. pBinding = GetInterfaceBinding(pRtInfo->dwRtInfoIfIndex);
  758. if ((!pBinding) || (!pBinding->bBound))
  759. {
  760. // Interface has been deleted meanwhile
  761. // or is not bound at this point - quit
  762. EXIT_LOCK(BINDING_LIST);
  763. return ERROR_INVALID_PARAMETER;
  764. }
  765. }
  766. //
  767. // Convert TimeToLive from secs to millisecs
  768. //
  769. if (dwTimeToLive != INFINITE)
  770. {
  771. if (dwTimeToLive < (INFINITE / 1000))
  772. {
  773. dwTimeToLive *= 1000;
  774. }
  775. else
  776. {
  777. dwTimeToLive = INFINITE;
  778. }
  779. }
  780. dwFlags = 0;
  781. //
  782. // Add the new route using the RTMv2 API call
  783. //
  784. dwResult = RtmAddRouteToDest(hRtmHandle,
  785. phRtmRoute,
  786. pDestAddr,
  787. pRouteInfo,
  788. dwTimeToLive,
  789. NULL,
  790. 0,
  791. NULL,
  792. &dwFlags);
  793. if ((hRtmHandle == g_hNonDodRoute) ||
  794. (hRtmHandle == g_hNetMgmtRoute))
  795. {
  796. EXIT_LOCK(BINDING_LIST);
  797. }
  798. //
  799. // check if route is 0/0 and route protocol is
  800. // PROTO_IP_NETMGMT. If so mark for change notification
  801. //
  802. if ((pRtInfo->dwRtInfoDest is 0) and
  803. (pRtInfo->dwRtInfoMask is 0))
  804. {
  805. RTM_DEST_INFO rdi;
  806. BOOL bMark;
  807. BOOL bRelDest = FALSE;
  808. do
  809. {
  810. TraceRoute2(
  811. ROUTE, "Checking dest %d.%d.%d.%d/%d for mark",
  812. PRINT_IPADDR(*(ULONG *)pDestAddr->AddrBits),
  813. PRINT_IPADDR(pDestAddr->NumBits)
  814. );
  815. dwResult = RtmGetExactMatchDestination(
  816. g_hNetMgmtRoute,
  817. pDestAddr,
  818. RTM_THIS_PROTOCOL,
  819. RTM_VIEW_MASK_UCAST,
  820. &rdi
  821. );
  822. if (dwResult isnot NO_ERROR)
  823. {
  824. Trace1(
  825. ERR,
  826. "AddRtmRoute: error %d failed to get "
  827. "destination 0/0 for change notification",
  828. dwResult
  829. );
  830. break;
  831. }
  832. bRelDest = TRUE;
  833. dwResult = RtmIsMarkedForChangeNotification(
  834. g_hNetMgmtRoute,
  835. g_hDefaultRouteNotification,
  836. rdi.DestHandle,
  837. &bMark
  838. );
  839. if (dwResult isnot NO_ERROR)
  840. {
  841. Trace1(
  842. ERR,
  843. "AddRtmRoute: error %d failed to check "
  844. "destination 0/0 for change notification",
  845. dwResult
  846. );
  847. break;
  848. }
  849. if (!bMark)
  850. {
  851. dwResult = RtmMarkDestForChangeNotification(
  852. g_hNetMgmtRoute,
  853. g_hDefaultRouteNotification,
  854. rdi.DestHandle,
  855. TRUE
  856. );
  857. if (dwResult isnot NO_ERROR)
  858. {
  859. Trace1(
  860. ERR,
  861. "AddRtmRoute: error %d failed to nark "
  862. "destination 0/0 for change notification",
  863. dwResult
  864. );
  865. break;
  866. }
  867. //
  868. // Add route once more, to force marked dest
  869. // change notifications to be issued for this
  870. // change
  871. //
  872. dwFlags = 0;
  873. dwResult = RtmAddRouteToDest(
  874. hRtmHandle,
  875. phRtmRoute,
  876. pDestAddr,
  877. pRouteInfo,
  878. dwTimeToLive,
  879. NULL,
  880. 0,
  881. NULL,
  882. &dwFlags
  883. );
  884. if (dwResult isnot NO_ERROR)
  885. {
  886. Trace1(
  887. ERR,
  888. "AddRtmRoute: error %d added route after "
  889. "marking destination",
  890. dwResult
  891. );
  892. break;
  893. }
  894. TraceRoute2(
  895. ROUTE, "Marked dest %d.%d.%d.%d/%d and added",
  896. PRINT_IPADDR(*(ULONG *)pDestAddr->AddrBits),
  897. PRINT_IPADDR(pDestAddr->NumBits)
  898. );
  899. }
  900. } while (FALSE);
  901. if (bRelDest)
  902. {
  903. RtmReleaseDestInfo(
  904. g_hNetMgmtRoute,
  905. &rdi
  906. );
  907. }
  908. }
  909. }
  910. // Release the next hop handle obtained above
  911. RtmReleaseNextHops(hRtmHandle,
  912. 1,
  913. &hNextHopHandle);
  914. }
  915. HeapFree(IPRouterHeap, 0, pDestAddr);
  916. HeapFree(IPRouterHeap, 0, pRouteInfo);
  917. return dwResult;
  918. }
  919. DWORD
  920. DeleteRtmRoute (
  921. IN HANDLE hRtmHandle,
  922. IN PINTERFACE_ROUTE_INFO pRtInfo
  923. )
  924. /*++
  925. Routine Description:
  926. Deletes an RTM route with the specified route information.
  927. Arguments:
  928. hRtmHandle - RTM registration handle used in RTM calls
  929. pRtInfo -
  930. Return Value:
  931. Status of the operation.
  932. --*/
  933. {
  934. PRTM_NET_ADDRESS pDestAddr;
  935. PRTM_ROUTE_INFO pRouteInfo;
  936. RTM_NEXTHOP_INFO rniInfo;
  937. DWORD dwFlags;
  938. DWORD dwResult;
  939. HANDLE hRouteHandle;
  940. HANDLE hNextHopHandle;
  941. pRouteInfo = HeapAlloc(
  942. IPRouterHeap,
  943. 0,
  944. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  945. );
  946. if (pRouteInfo == NULL)
  947. {
  948. Trace1(
  949. ERR,
  950. "DeleteRtmRoute : error allocating %d bytes"
  951. "for route info",
  952. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  953. );
  954. return ERROR_NOT_ENOUGH_MEMORY;
  955. }
  956. pDestAddr = HeapAlloc(
  957. IPRouterHeap,
  958. 0,
  959. sizeof(RTM_NET_ADDRESS)
  960. );
  961. if (pDestAddr == NULL)
  962. {
  963. Trace1(
  964. ERR,
  965. "AddRtmRoute : error allocating %d bytes"
  966. "for dest. address",
  967. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  968. );
  969. HeapFree(IPRouterHeap, 0, pRouteInfo);
  970. return ERROR_NOT_ENOUGH_MEMORY;
  971. }
  972. //
  973. // Obtain a handle to the next hop in the route
  974. //
  975. RTM_IPV4_MAKE_NET_ADDRESS(&rniInfo.NextHopAddress,
  976. pRtInfo->dwRtInfoNextHop,
  977. 32);
  978. rniInfo.InterfaceIndex = pRtInfo->dwRtInfoIfIndex;
  979. rniInfo.NextHopOwner = hRtmHandle;
  980. dwResult = RtmFindNextHop(hRtmHandle,
  981. &rniInfo,
  982. &hNextHopHandle,
  983. NULL);
  984. if (dwResult isnot NO_ERROR)
  985. {
  986. HeapFree(IPRouterHeap, 0, pDestAddr);
  987. HeapFree(IPRouterHeap, 0, pRouteInfo);
  988. return dwResult;
  989. }
  990. //
  991. // We can get this route by matching the route's
  992. // net addr, its owner and neighbour learnt from
  993. //
  994. ConvertRouteInfoToRtm(hRtmHandle,
  995. pRtInfo,
  996. hNextHopHandle,
  997. 0,
  998. pDestAddr,
  999. pRouteInfo);
  1000. dwResult = RtmGetExactMatchRoute(hRtmHandle,
  1001. pDestAddr,
  1002. RTM_MATCH_OWNER | RTM_MATCH_NEIGHBOUR,
  1003. pRouteInfo,
  1004. 0,
  1005. 0,
  1006. &hRouteHandle);
  1007. if (dwResult is NO_ERROR)
  1008. {
  1009. //
  1010. // Delete the route found above using the handle
  1011. //
  1012. dwResult = RtmDeleteRouteToDest(hRtmHandle,
  1013. hRouteHandle,
  1014. &dwFlags);
  1015. if (dwResult isnot NO_ERROR)
  1016. {
  1017. // If delete successful, deref is automatic
  1018. RtmReleaseRoutes(hRtmHandle,
  1019. 1,
  1020. &hRouteHandle);
  1021. }
  1022. // Release the route information obtained above
  1023. RtmReleaseRouteInfo(hRtmHandle,
  1024. pRouteInfo);
  1025. }
  1026. // Release the next hop handle obtained above
  1027. RtmReleaseNextHops(hRtmHandle,
  1028. 1,
  1029. &hNextHopHandle);
  1030. HeapFree(IPRouterHeap, 0, pDestAddr);
  1031. HeapFree(IPRouterHeap, 0, pRouteInfo);
  1032. return dwResult;
  1033. }
  1034. DWORD
  1035. ConvertRouteInfoToRtm(
  1036. IN HANDLE hRtmHandle,
  1037. IN PINTERFACE_ROUTE_INFO pRtInfo,
  1038. IN HANDLE hNextHopHandle,
  1039. IN DWORD dwRouteFlags,
  1040. OUT PRTM_NET_ADDRESS pDestAddr,
  1041. OUT PRTM_ROUTE_INFO pRouteInfo
  1042. )
  1043. {
  1044. DWORD dwAddrLen;
  1045. // Fill the destination addr structure
  1046. RTM_IPV4_LEN_FROM_MASK(dwAddrLen, pRtInfo->dwRtInfoMask);
  1047. RTM_IPV4_MAKE_NET_ADDRESS(pDestAddr,
  1048. pRtInfo->dwRtInfoDest,
  1049. dwAddrLen);
  1050. // Fill in the route information now
  1051. ZeroMemory(pRouteInfo, sizeof(RTM_ROUTE_INFO));
  1052. pRouteInfo->RouteOwner = hRtmHandle;
  1053. pRouteInfo->Neighbour = hNextHopHandle;
  1054. pRouteInfo->PrefInfo.Metric = pRtInfo->dwRtInfoMetric1;
  1055. pRouteInfo->PrefInfo.Preference = pRtInfo->dwRtInfoPreference;
  1056. pRouteInfo->BelongsToViews = pRtInfo->dwRtInfoViewSet;
  1057. //
  1058. // BUG BUG BUG BUG :
  1059. // This is broken for future references
  1060. //
  1061. if(g_pLoopbackInterfaceCb &&
  1062. pRtInfo->dwRtInfoIfIndex is g_pLoopbackInterfaceCb->dwIfIndex)
  1063. {
  1064. pRouteInfo->BelongsToViews &= ~RTM_VIEW_MASK_MCAST;
  1065. }
  1066. pRouteInfo->NextHopsList.NumNextHops = 1;
  1067. pRouteInfo->NextHopsList.NextHops[0] = hNextHopHandle;
  1068. // an unsigned integer is converted to a shorter
  1069. // unsigned integer by truncating the high-order bits!
  1070. pRouteInfo->Flags1 = (UCHAR) dwRouteFlags;
  1071. pRouteInfo->Flags = (USHORT) (dwRouteFlags >> 16);
  1072. // Get the preference for this route
  1073. return ValidateRouteForProtocol(pRtInfo->dwRtInfoProto,
  1074. pRouteInfo,
  1075. pDestAddr);
  1076. // The following information is lost
  1077. //
  1078. // dwForwardMetric2,3
  1079. // dwForwardPolicy
  1080. // dwForwardType
  1081. // dwForwardAge
  1082. // dwForwardNextHopAS
  1083. }
  1084. VOID
  1085. ConvertRtmToRouteInfo (
  1086. IN DWORD ownerProtocol,
  1087. IN PRTM_NET_ADDRESS pDestAddr,
  1088. IN PRTM_ROUTE_INFO pRouteInfo,
  1089. IN PRTM_NEXTHOP_INFO pNextHop,
  1090. OUT PINTERFACE_ROUTE_INFO pRtInfo
  1091. )
  1092. {
  1093. pRtInfo->dwRtInfoDest = *(ULONG *)pDestAddr->AddrBits;
  1094. pRtInfo->dwRtInfoMask = RTM_IPV4_MASK_FROM_LEN(pDestAddr->NumBits);
  1095. pRtInfo->dwRtInfoIfIndex = pNextHop->InterfaceIndex;
  1096. pRtInfo->dwRtInfoNextHop = *(ULONG *)pNextHop->NextHopAddress.AddrBits;
  1097. pRtInfo->dwRtInfoProto = ownerProtocol;
  1098. pRtInfo->dwRtInfoMetric1 =
  1099. pRtInfo->dwRtInfoMetric2 =
  1100. pRtInfo->dwRtInfoMetric3 = pRouteInfo->PrefInfo.Metric;
  1101. pRtInfo->dwRtInfoPreference = pRouteInfo->PrefInfo.Preference;
  1102. pRtInfo->dwRtInfoViewSet = pRouteInfo->BelongsToViews;
  1103. pRtInfo->dwRtInfoPolicy = 0;
  1104. pRtInfo->dwRtInfoType = 0;
  1105. pRtInfo->dwRtInfoAge = 0;
  1106. pRtInfo->dwRtInfoNextHopAS = 0;
  1107. return;
  1108. }
  1109. PINTERFACE_ROUTE_INFO
  1110. ConvertMibRouteToRouteInfo(
  1111. IN PMIB_IPFORWARDROW pMibRow
  1112. )
  1113. {
  1114. PINTERFACE_ROUTE_INFO pRouteInfo = (PINTERFACE_ROUTE_INFO)pMibRow;
  1115. pMibRow->dwForwardMetric2 = 0;
  1116. pMibRow->dwForwardMetric3 = 0;
  1117. pMibRow->dwForwardMetric4 = 0;
  1118. pMibRow->dwForwardMetric5 = 0;
  1119. // Make sure Metric1 isn't 0
  1120. if (pRouteInfo->dwRtInfoMetric1 is 0)
  1121. {
  1122. pRouteInfo->dwRtInfoMetric1 = 1;
  1123. }
  1124. // By default put it in both views
  1125. pRouteInfo->dwRtInfoViewSet = RTM_VIEW_MASK_UCAST | RTM_VIEW_MASK_MCAST;
  1126. return pRouteInfo;
  1127. }
  1128. PMIB_IPFORWARDROW
  1129. ConvertRouteInfoToMibRoute(
  1130. IN PINTERFACE_ROUTE_INFO pRouteInfo
  1131. )
  1132. {
  1133. PMIB_IPFORWARDROW pMibRoute = (PMIB_IPFORWARDROW) pRouteInfo;
  1134. pMibRoute->dwForwardMetric2 =
  1135. pMibRoute->dwForwardMetric3 =
  1136. pMibRoute->dwForwardMetric4 =
  1137. pMibRoute->dwForwardMetric5 = IRE_METRIC_UNUSED;
  1138. pMibRoute->dwForwardAge = INFINITE;
  1139. pMibRoute->dwForwardPolicy = 0;
  1140. pMibRoute->dwForwardNextHopAS = 0;
  1141. pMibRoute->dwForwardType = IRE_TYPE_INDIRECT;
  1142. return pMibRoute;
  1143. }
  1144. VOID
  1145. ConvertRouteNotifyOutputToRouteInfo(
  1146. IN PIPRouteNotifyOutput pirno,
  1147. OUT PINTERFACE_ROUTE_INFO pRtInfo
  1148. )
  1149. {
  1150. ZeroMemory(pRtInfo, sizeof(INTERFACE_ROUTE_INFO));
  1151. pRtInfo->dwRtInfoDest = pirno->irno_dest;
  1152. pRtInfo->dwRtInfoMask = pirno->irno_mask;
  1153. pRtInfo->dwRtInfoIfIndex = pirno->irno_ifindex;
  1154. pRtInfo->dwRtInfoNextHop = pirno->irno_nexthop;
  1155. pRtInfo->dwRtInfoProto = pirno->irno_proto;
  1156. pRtInfo->dwRtInfoMetric1 =
  1157. pRtInfo->dwRtInfoMetric2 =
  1158. pRtInfo->dwRtInfoMetric3 = pirno->irno_metric;
  1159. pRtInfo->dwRtInfoPreference = ComputeRouteMetric(pirno->irno_proto);
  1160. pRtInfo->dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  1161. RTM_VIEW_MASK_MCAST;
  1162. pRtInfo->dwRtInfoType = (pirno->irno_proto == PROTO_IP_LOCAL) ?
  1163. MIB_IPROUTE_TYPE_DIRECT : 0;
  1164. pRtInfo->dwRtInfoAge = INFINITE;
  1165. pRtInfo->dwRtInfoNextHopAS = 0;
  1166. pRtInfo->dwRtInfoPolicy = 0;
  1167. return;
  1168. }
  1169. DWORD
  1170. BlockConvertRoutesToStatic (
  1171. IN HANDLE hRtmHandle,
  1172. IN DWORD dwIfIndex,
  1173. IN DWORD dwProtocolId
  1174. )
  1175. {
  1176. HANDLE hRtmEnum;
  1177. RTM_ENTITY_INFO reiInfo;
  1178. RTM_NET_ADDRESS rnaDest;
  1179. PRTM_ROUTE_INFO pRouteInfo1;
  1180. PRTM_ROUTE_INFO pRouteInfo2;
  1181. RTM_NEXTHOP_INFO nhiInfo;
  1182. RTM_NEXTHOP_HANDLE hNextHop;
  1183. PHANDLE hRoutes;
  1184. DWORD dwHandles;
  1185. DWORD dwFlags;
  1186. DWORD dwNumBytes;
  1187. DWORD i, j, k;
  1188. BOOL fDeleted;
  1189. DWORD dwResult;
  1190. hRoutes = HeapAlloc(
  1191. IPRouterHeap,
  1192. 0,
  1193. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  1194. );
  1195. if (hRoutes == NULL)
  1196. {
  1197. Trace1(
  1198. ERR,
  1199. "BlockConvertRoutesToStatic : error allocating %d bytes"
  1200. "for route handes",
  1201. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  1202. );
  1203. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1204. return ERROR_NOT_ENOUGH_MEMORY;
  1205. }
  1206. dwNumBytes = RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute);
  1207. pRouteInfo1 = HeapAlloc(
  1208. IPRouterHeap,
  1209. 0,
  1210. dwNumBytes
  1211. );
  1212. if (pRouteInfo1 == NULL)
  1213. {
  1214. Trace1(
  1215. ERR,
  1216. "BlockConvertRoutesToStatic : error allocating %d bytes"
  1217. "for route info",
  1218. dwNumBytes
  1219. );
  1220. HeapFree(IPRouterHeap, 0, hRoutes);
  1221. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1222. return ERROR_NOT_ENOUGH_MEMORY;
  1223. }
  1224. pRouteInfo2 = HeapAlloc(
  1225. IPRouterHeap,
  1226. 0,
  1227. dwNumBytes
  1228. );
  1229. if (pRouteInfo2 == NULL)
  1230. {
  1231. Trace1(
  1232. ERR,
  1233. "BlockConvertRoutesToStatic : error allocating %d bytes"
  1234. "for route info",
  1235. dwNumBytes
  1236. );
  1237. HeapFree(IPRouterHeap, 0, hRoutes);
  1238. HeapFree(IPRouterHeap, 0, pRouteInfo1);
  1239. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1240. return ERROR_NOT_ENOUGH_MEMORY;
  1241. }
  1242. //
  1243. // Enum all routes on the interface that we need
  1244. //
  1245. dwResult = RtmCreateRouteEnum(hRtmHandle,
  1246. NULL,
  1247. RTM_VIEW_MASK_ANY,
  1248. RTM_ENUM_ALL_ROUTES,
  1249. NULL,
  1250. RTM_MATCH_INTERFACE,
  1251. NULL,
  1252. dwIfIndex,
  1253. &hRtmEnum);
  1254. if(dwResult isnot NO_ERROR)
  1255. {
  1256. Trace2(ERR,
  1257. "BlockConvertRoutesToStatic: Error %d creating handle for %d\n",
  1258. dwResult,
  1259. hRtmHandle);
  1260. HeapFree(IPRouterHeap, 0, hRoutes);
  1261. HeapFree(IPRouterHeap, 0, pRouteInfo1);
  1262. HeapFree(IPRouterHeap, 0, pRouteInfo2);
  1263. return dwResult;
  1264. }
  1265. do
  1266. {
  1267. dwHandles = g_rtmProfile.MaxHandlesInEnum;
  1268. dwResult = RtmGetEnumRoutes(hRtmHandle,
  1269. hRtmEnum,
  1270. &dwHandles,
  1271. hRoutes);
  1272. for (i = 0; i < dwHandles; i++)
  1273. {
  1274. fDeleted = FALSE;
  1275. // Get the route info from the handle
  1276. if (RtmGetRouteInfo(hRtmHandle,
  1277. hRoutes[i],
  1278. pRouteInfo1,
  1279. &rnaDest) is NO_ERROR)
  1280. {
  1281. // Does this match the routing protocol we want ?
  1282. if ((RtmGetEntityInfo(hRtmHandle,
  1283. pRouteInfo1->RouteOwner,
  1284. &reiInfo) is NO_ERROR) &&
  1285. (reiInfo.EntityId.EntityProtocolId is dwProtocolId))
  1286. {
  1287. //
  1288. // Add new static route with same information
  1289. //
  1290. CopyMemory(pRouteInfo2,
  1291. pRouteInfo1,
  1292. sizeof(RTM_ROUTE_INFO));
  1293. // Adjust the preference to confirm to protocol
  1294. pRouteInfo2->PrefInfo.Preference =
  1295. ComputeRouteMetric(PROTO_IP_NT_AUTOSTATIC);
  1296. // Adjust the neighbour to corr to new protocol
  1297. if (pRouteInfo1->Neighbour)
  1298. {
  1299. // In case we cant get convert the neighbour
  1300. pRouteInfo2->Neighbour = NULL;
  1301. if (RtmGetNextHopInfo(hRtmHandle,
  1302. pRouteInfo1->Neighbour,
  1303. &nhiInfo) is NO_ERROR)
  1304. {
  1305. // Add the same neigbour using new protocol
  1306. hNextHop = NULL;
  1307. if (RtmAddNextHop(hRtmHandle,
  1308. &nhiInfo,
  1309. &hNextHop,
  1310. &dwFlags) is NO_ERROR)
  1311. {
  1312. pRouteInfo2->Neighbour = hNextHop;
  1313. }
  1314. RtmReleaseNextHopInfo(hRtmHandle, &nhiInfo);
  1315. }
  1316. }
  1317. // Adjust the next hops to corr to new protocol
  1318. for (j = k = 0;
  1319. j < pRouteInfo1->NextHopsList.NumNextHops;
  1320. j++)
  1321. {
  1322. if (RtmGetNextHopInfo(hRtmHandle,
  1323. pRouteInfo1->NextHopsList.NextHops[j],
  1324. &nhiInfo) is NO_ERROR)
  1325. {
  1326. // Add the same nexthop using new protocol
  1327. hNextHop = NULL;
  1328. if (RtmAddNextHop(hRtmHandle,
  1329. &nhiInfo,
  1330. &hNextHop,
  1331. &dwFlags) is NO_ERROR)
  1332. {
  1333. pRouteInfo2->NextHopsList.NextHops[k++] = hNextHop;
  1334. }
  1335. RtmReleaseNextHopInfo(hRtmHandle, &nhiInfo);
  1336. }
  1337. }
  1338. pRouteInfo2->NextHopsList.NumNextHops = (USHORT) k;
  1339. // Add the new route with the next hop information
  1340. if (k > 0)
  1341. {
  1342. dwFlags = 0;
  1343. if (RtmAddRouteToDest(hRtmHandle,
  1344. NULL,
  1345. &rnaDest,
  1346. pRouteInfo2,
  1347. INFINITE,
  1348. NULL,
  1349. 0,
  1350. NULL,
  1351. &dwFlags) is NO_ERROR)
  1352. {
  1353. // Route add is successful - delete old route
  1354. if (RtmDeleteRouteToDest(pRouteInfo1->RouteOwner,
  1355. hRoutes[i],
  1356. &dwFlags) is NO_ERROR)
  1357. {
  1358. fDeleted = TRUE;
  1359. }
  1360. }
  1361. RtmReleaseNextHops(hRtmHandle,
  1362. k,
  1363. pRouteInfo2->NextHopsList.NextHops);
  1364. }
  1365. }
  1366. RtmReleaseRouteInfo(hRtmHandle, pRouteInfo1);
  1367. }
  1368. if (!fDeleted)
  1369. {
  1370. RtmReleaseRoutes(hRtmHandle, 1, &hRoutes[i]);
  1371. }
  1372. }
  1373. }
  1374. while (dwResult is NO_ERROR);
  1375. RtmDeleteEnumHandle(hRtmHandle, hRtmEnum);
  1376. HeapFree(IPRouterHeap, 0, hRoutes);
  1377. HeapFree(IPRouterHeap, 0, pRouteInfo1);
  1378. HeapFree(IPRouterHeap, 0, pRouteInfo2);
  1379. return NO_ERROR;
  1380. }
  1381. DWORD
  1382. DeleteRtmRoutes (
  1383. IN HANDLE hRtmHandle,
  1384. IN DWORD dwIfIndex,
  1385. IN BOOL fDeleteAll
  1386. )
  1387. {
  1388. HANDLE hRtmEnum;
  1389. PHANDLE hRoutes;
  1390. DWORD dwHandles;
  1391. DWORD dwFlags;
  1392. DWORD i;
  1393. DWORD dwResult;
  1394. hRoutes = HeapAlloc(
  1395. IPRouterHeap,
  1396. 0,
  1397. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  1398. );
  1399. if (hRoutes == NULL)
  1400. {
  1401. Trace1(ERR,
  1402. "DeleteRtmRoutes: Error allocating %d bytes",
  1403. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE));
  1404. return ERROR_NOT_ENOUGH_MEMORY;
  1405. }
  1406. dwFlags = fDeleteAll ? 0: RTM_MATCH_INTERFACE;
  1407. dwResult = RtmCreateRouteEnum(hRtmHandle,
  1408. NULL,
  1409. RTM_VIEW_MASK_ANY,
  1410. RTM_ENUM_OWN_ROUTES,
  1411. NULL,
  1412. dwFlags,
  1413. NULL,
  1414. dwIfIndex,
  1415. &hRtmEnum);
  1416. if(dwResult isnot NO_ERROR)
  1417. {
  1418. Trace2(ERR,
  1419. "DeleteRtmRoutes: Error %d creating handle for %d\n",
  1420. dwResult,
  1421. hRtmHandle);
  1422. HeapFree(IPRouterHeap, 0, hRoutes);
  1423. return dwResult;
  1424. }
  1425. do
  1426. {
  1427. dwHandles = g_rtmProfile.MaxHandlesInEnum;
  1428. dwResult = RtmGetEnumRoutes(hRtmHandle,
  1429. hRtmEnum,
  1430. &dwHandles,
  1431. hRoutes);
  1432. for (i = 0; i < dwHandles; i++)
  1433. {
  1434. if (RtmDeleteRouteToDest(hRtmHandle,
  1435. hRoutes[i],
  1436. &dwFlags) isnot NO_ERROR)
  1437. {
  1438. // If delete is successful, this is automatic
  1439. RtmReleaseRoutes(hRtmHandle, 1, &hRoutes[i]);
  1440. }
  1441. }
  1442. }
  1443. while (dwResult is NO_ERROR);
  1444. RtmDeleteEnumHandle(hRtmHandle, hRtmEnum);
  1445. HeapFree(IPRouterHeap, 0, hRoutes);
  1446. return NO_ERROR;
  1447. }
  1448. DWORD
  1449. DeleteRtmNexthops (
  1450. IN HANDLE hRtmHandle,
  1451. IN DWORD dwIfIndex,
  1452. IN BOOL fDeleteAll
  1453. )
  1454. {
  1455. PRTM_NEXTHOP_INFO pNexthop;
  1456. PHANDLE hNexthops;
  1457. HANDLE hRtmEnum;
  1458. DWORD dwHandles;
  1459. DWORD i;
  1460. DWORD dwResult;
  1461. hNexthops = HeapAlloc(
  1462. IPRouterHeap,
  1463. 0,
  1464. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  1465. );
  1466. if (hNexthops == NULL)
  1467. {
  1468. Trace1(ERR,
  1469. "DeleteRtmNextHops: Error allocating %d bytes",
  1470. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE));
  1471. return ERROR_NOT_ENOUGH_MEMORY;
  1472. }
  1473. dwResult = RtmCreateNextHopEnum(hRtmHandle,
  1474. 0,
  1475. NULL,
  1476. &hRtmEnum);
  1477. if(dwResult isnot NO_ERROR)
  1478. {
  1479. Trace2(ERR,
  1480. "DeleteAllNexthops: Error %d creating handle for %d\n",
  1481. dwResult,
  1482. hRtmHandle);
  1483. HeapFree(IPRouterHeap, 0, hNexthops);
  1484. return dwResult;
  1485. }
  1486. do
  1487. {
  1488. dwHandles = g_rtmProfile.MaxHandlesInEnum;
  1489. dwResult = RtmGetEnumNextHops(hRtmHandle,
  1490. hRtmEnum,
  1491. &dwHandles,
  1492. hNexthops);
  1493. for (i = 0; i < dwHandles; i++)
  1494. {
  1495. if (!fDeleteAll)
  1496. {
  1497. //
  1498. // Make sure that the interface matches
  1499. //
  1500. if ((RtmGetNextHopPointer(hRtmHandle,
  1501. hNexthops[i],
  1502. &pNexthop) isnot NO_ERROR) ||
  1503. (pNexthop->InterfaceIndex != dwIfIndex))
  1504. {
  1505. RtmReleaseNextHops(hRtmHandle, 1, &hNexthops[i]);
  1506. continue;
  1507. }
  1508. }
  1509. // We need to delete this next hop here
  1510. if (RtmDeleteNextHop(hRtmHandle,
  1511. hNexthops[i],
  1512. NULL) isnot NO_ERROR)
  1513. {
  1514. // If delete is successful, this is automatic
  1515. RtmReleaseNextHops(hRtmHandle, 1, &hNexthops[i]);
  1516. }
  1517. }
  1518. }
  1519. while (dwResult is NO_ERROR);
  1520. RtmDeleteEnumHandle(hRtmHandle, hRtmEnum);
  1521. HeapFree(IPRouterHeap, 0, hNexthops);
  1522. return NO_ERROR;
  1523. }