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.

3407 lines
90 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. routing\ip\rtrmgr\route.c
  5. Abstract:
  6. All routes related code lives here.
  7. Revision History:
  8. Gurdeep Singh Pall 6/15/95 Created
  9. --*/
  10. #include "allinc.h"
  11. DWORD
  12. WINAPI
  13. GetBestRoute(
  14. IN DWORD dwDestAddr,
  15. IN DWORD dwSourceAddr, OPTIONAL
  16. OUT PMIB_IPFORWARDROW pBestRoute
  17. );
  18. DWORD
  19. InitializeStaticRoutes(
  20. PICB pIcb,
  21. PRTR_INFO_BLOCK_HEADER pInfoHdr
  22. )
  23. /*++
  24. Routine Description:
  25. Adds static routes with RTM
  26. Arguments:
  27. pIcb The ICB of the interface for whom the routes are
  28. pInfoHdr Pointer to info block containing IP_ROUTE_INFO
  29. Return Value:
  30. NO_ERROR
  31. --*/
  32. {
  33. DWORD dwNumRoutes, dwResult;
  34. DWORD i, j;
  35. PRTR_TOC_ENTRY pToc;
  36. PINTERFACE_ROUTE_INFO pRoutes;
  37. BOOL bP2P;
  38. TraceEnter("IntializeStaticRoutes");
  39. //
  40. // If this is a client, only do the special client processing
  41. //
  42. if(pIcb->ritType is ROUTER_IF_TYPE_CLIENT)
  43. {
  44. CopyOutClientRoutes(pIcb,
  45. pInfoHdr);
  46. return NO_ERROR;
  47. }
  48. //
  49. // We first go through the init route table and add any route going
  50. // over that interface that is
  51. // (i) not a local net route
  52. // (ii) not a subnet/net broadcast route
  53. // (iii) not a Loopback route,
  54. // (iv) not a CLASS D or E route and not a 255.255.255.255 destination
  55. // (vi) a PROTO_IP_LOCAL or PROTO_IP_NETMGMT route
  56. //
  57. CheckBindingConsistency(pIcb);
  58. bP2P = IsIfP2P(pIcb->ritType);
  59. pToc = GetPointerToTocEntry(IP_ROUTE_INFO,
  60. pInfoHdr);
  61. if((pToc is NULL) or
  62. (pToc->InfoSize is 0))
  63. {
  64. Trace0(ROUTE,"IntializeStaticRoutes: No Routes found");
  65. TraceLeave("IntializeStaticRoutes");
  66. return NO_ERROR;
  67. }
  68. pRoutes = GetInfoFromTocEntry(pInfoHdr,
  69. pToc);
  70. if(pRoutes is NULL)
  71. {
  72. Trace0(ROUTE,"IntializeStaticRoutes: No Routes found");
  73. TraceLeave("IntializeStaticRoutes");
  74. return NO_ERROR;
  75. }
  76. dwNumRoutes = pToc->Count;
  77. for (i=0; i< dwNumRoutes; i++)
  78. {
  79. DWORD dwMask;
  80. dwMask = GetBestNextHopMaskGivenICB(pIcb,
  81. pRoutes[i].dwRtInfoNextHop);
  82. dwResult = AddSingleRoute(pIcb->dwIfIndex,
  83. (&pRoutes[i]),
  84. dwMask,
  85. 0, // RTM_ROUTE_INFO::Flags
  86. TRUE, // Valid route
  87. TRUE,
  88. bP2P,
  89. NULL); // Add the route to stack, if need be
  90. if(dwResult isnot NO_ERROR)
  91. {
  92. Trace3(ERR,
  93. "IntializeStaticRoutes: Error %d adding config route to %x over %S",
  94. dwResult,
  95. pRoutes[i].dwRtInfoDest,
  96. pIcb->pwszName);
  97. }
  98. }
  99. TraceLeave("IntializeStaticRoutes");
  100. return NO_ERROR;
  101. }
  102. DWORD
  103. CopyOutClientRoutes(
  104. PICB pIcb,
  105. PRTR_INFO_BLOCK_HEADER pInfoHdr
  106. )
  107. /*++
  108. Routine Description:
  109. Stores a copy of the client static routes
  110. Arguments:
  111. pIcb The ICB of the interface for whom the routes are
  112. pInfoHdr Pointer to info block containing IP_ROUTE_INFO
  113. Return Value:
  114. NO_ERROR
  115. --*/
  116. {
  117. PINTERFACE_ROUTE_INFO pRoutes;
  118. PINTERFACE_ROUTE_TABLE pStore;
  119. DWORD i, dwNumRoutes;
  120. PRTR_TOC_ENTRY pToc;
  121. pToc = GetPointerToTocEntry(IP_ROUTE_INFO,
  122. pInfoHdr);
  123. if((pToc is NULL) or
  124. (pToc->InfoSize is 0))
  125. {
  126. return NO_ERROR;
  127. }
  128. pRoutes = GetInfoFromTocEntry(pInfoHdr,
  129. pToc);
  130. if (pRoutes is NULL)
  131. {
  132. return NO_ERROR;
  133. }
  134. dwNumRoutes = pToc->Count;
  135. if(dwNumRoutes is 0)
  136. {
  137. return NO_ERROR;
  138. }
  139. pStore = HeapAlloc(IPRouterHeap,
  140. HEAP_ZERO_MEMORY,
  141. SIZEOF_IPFORWARDTABLE(dwNumRoutes));
  142. if(pStore is NULL)
  143. {
  144. return ERROR_NOT_ENOUGH_MEMORY;
  145. }
  146. pStore->dwNumEntries = dwNumRoutes;
  147. for(i = 0; i < dwNumRoutes; i++)
  148. {
  149. pStore->table[i] = pRoutes[i];
  150. }
  151. pIcb->pStoredRoutes = pStore;
  152. return NO_ERROR;
  153. }
  154. DWORD
  155. AddSingleRoute(
  156. DWORD dwIfIndex,
  157. PINTERFACE_ROUTE_INFO pRtInfo,
  158. DWORD dwNextHopMask,
  159. WORD wRtmFlags,
  160. BOOL bValid,
  161. BOOL bAddToStack,
  162. BOOL bP2P,
  163. HANDLE *phRtmRoute OPTIONAL
  164. )
  165. /*++
  166. Routine Description
  167. Adds a route with RTM
  168. Arguments
  169. pIcb The ICB of the interface for whom the route is
  170. pIpForw The route
  171. mask Mask for destination
  172. Return Value
  173. NO_ERROR or some code from RTM
  174. --*/
  175. {
  176. DWORD i, dwResult, dwRouteFlags;
  177. HANDLE hRtmHandle;
  178. DWORD dwOldIfIndex;
  179. TraceEnter("AddSingleRoute");
  180. TraceRoute2(ROUTE,
  181. "route to %d.%d.%d.%d/%d.%d.%d.%d",
  182. PRINT_IPADDR(pRtInfo->dwRtInfoDest),
  183. PRINT_IPADDR(pRtInfo->dwRtInfoMask));
  184. TraceRoute4(ROUTE,
  185. "Flags 0x%x Valid %d Stack %d P2P %d",
  186. wRtmFlags, bValid, bAddToStack, bP2P
  187. );
  188. hRtmHandle = NULL;
  189. for(i = 0;
  190. i < sizeof(g_rgRtmHandles)/sizeof(RTM_HANDLE_INFO);
  191. i++)
  192. {
  193. if(pRtInfo->dwRtInfoProto is g_rgRtmHandles[i].dwProtoId)
  194. {
  195. hRtmHandle = g_rgRtmHandles[i].hRouteHandle;
  196. break;
  197. }
  198. }
  199. if(hRtmHandle is NULL)
  200. {
  201. Trace1(ERR,
  202. "AddSingleRoute: Protocol %d not valid",
  203. pRtInfo->dwRtInfoProto);
  204. return ERROR_INVALID_PARAMETER;
  205. }
  206. if((pRtInfo->dwRtInfoDest & pRtInfo->dwRtInfoMask) isnot pRtInfo->dwRtInfoDest)
  207. {
  208. Trace2(ERR,
  209. "AddSingleRoute: Dest %d.%d.%d.%d and Mask %d.%d.%d.%d wrong",
  210. PRINT_IPADDR(pRtInfo->dwRtInfoDest),
  211. PRINT_IPADDR(pRtInfo->dwRtInfoMask));
  212. TraceLeave("AddSingleRoute");
  213. return ERROR_INVALID_PARAMETER;
  214. }
  215. if((((DWORD)(pRtInfo->dwRtInfoDest & 0x000000FF)) >= (DWORD)0x000000E0) and
  216. (pRtInfo->dwRtInfoDest isnot ALL_ONES_BROADCAST) and
  217. (pRtInfo->dwRtInfoDest isnot LOCAL_NET_MULTICAST))
  218. {
  219. //
  220. // This will catch the CLASS D/E
  221. //
  222. Trace1(ERR,
  223. "AddSingleRoute: Dest %d.%d.%d.%d is invalid",
  224. PRINT_IPADDR(pRtInfo->dwRtInfoDest));
  225. TraceLeave("AddSingleRoute");
  226. return ERROR_INVALID_PARAMETER;
  227. }
  228. // Special case to deal with weird utilities (legacy UI, etc):
  229. if (pRtInfo->dwRtInfoViewSet is 0)
  230. {
  231. pRtInfo->dwRtInfoViewSet = RTM_VIEW_MASK_UCAST | RTM_VIEW_MASK_MCAST;
  232. }
  233. #if 0
  234. // Removed this check since a metric of 0 is legal, for example for
  235. // routes to the loopback interface.
  236. if(pRtInfo->dwRtInfoMetric1 is 0)
  237. {
  238. Trace0(ERR,
  239. "AddSingleRoute: Metric1 cant be 0");
  240. TraceLeave("AddSingleRoute");
  241. return ERROR_INVALID_PARAMETER;
  242. }
  243. #endif
  244. if(bP2P)
  245. {
  246. dwNextHopMask = ALL_ONES_MASK;
  247. //pRtInfo->dwRtInfoNextHop = 0;
  248. }
  249. //
  250. // The route might not have the right index since config routes dont know
  251. // their interface id
  252. //
  253. dwOldIfIndex = pRtInfo->dwRtInfoIfIndex;
  254. pRtInfo->dwRtInfoIfIndex = dwIfIndex;
  255. //
  256. // Set the appropritate route flags
  257. //
  258. dwRouteFlags = 0;
  259. if(bValid)
  260. {
  261. dwRouteFlags |= IP_VALID_ROUTE;
  262. }
  263. if(bAddToStack)
  264. {
  265. dwRouteFlags |= IP_STACK_ROUTE;
  266. }
  267. if(bP2P)
  268. {
  269. dwRouteFlags |= IP_P2P_ROUTE;
  270. }
  271. // these flags correspond to RTM_ROUTE_INFO::Flags
  272. dwRouteFlags |= (wRtmFlags << 16);
  273. //
  274. // Add the forward route with RTM
  275. //
  276. dwResult = AddRtmRoute(hRtmHandle,
  277. pRtInfo,
  278. dwRouteFlags,
  279. dwNextHopMask,
  280. INFINITE,
  281. phRtmRoute);
  282. if (dwResult isnot NO_ERROR)
  283. {
  284. Trace1(ERR, "AddSingleRoute: Could not add route to: %x",
  285. pRtInfo->dwRtInfoDest) ;
  286. }
  287. pRtInfo->dwRtInfoIfIndex = dwOldIfIndex;
  288. TraceLeave("AddSingleRoute");
  289. return dwResult;
  290. }
  291. DWORD
  292. DeleteSingleRoute(
  293. DWORD dwIfIndex,
  294. DWORD dwDestAddr,
  295. DWORD dwDestMask,
  296. DWORD dwNexthop,
  297. DWORD dwProtoId,
  298. BOOL bP2P
  299. )
  300. /*++
  301. Routine Description:
  302. Deletes a single route from RTM
  303. Arguments:
  304. InterfaceID Index of the interface
  305. dest Destination address
  306. nexthop Next hop address
  307. Return Value:
  308. NO_ERROR or some code from RTM
  309. --*/
  310. {
  311. DWORD i, dwResult;
  312. HANDLE hRtmHandle;
  313. INTERFACE_ROUTE_INFO RtInfo;
  314. TraceEnter("DeleteSingleRoute");
  315. TraceRoute2(
  316. ROUTE, "DeleteSingleRoute: %d.%d.%d.%d/%d.%d.%d.%d",
  317. PRINT_IPADDR( dwDestAddr ),
  318. PRINT_IPADDR( dwDestMask )
  319. );
  320. hRtmHandle = NULL;
  321. for(i = 0;
  322. i < sizeof(g_rgRtmHandles)/sizeof(RTM_HANDLE_INFO);
  323. i++)
  324. {
  325. if(dwProtoId is g_rgRtmHandles[i].dwProtoId)
  326. {
  327. hRtmHandle = g_rgRtmHandles[i].hRouteHandle;
  328. break;
  329. }
  330. }
  331. if(hRtmHandle is NULL)
  332. {
  333. Trace1(ERR,
  334. "DeleteSingleRoute: Protocol %d not valid",
  335. dwProtoId);
  336. return ERROR_INVALID_PARAMETER;
  337. }
  338. RtInfo.dwRtInfoNextHop = dwNexthop;
  339. /*
  340. if(bP2P)
  341. {
  342. RtInfo.dwRtInfoNextHop = 0;
  343. }
  344. else
  345. {
  346. RtInfo.dwRtInfoNextHop = dwNexthop;
  347. }
  348. */
  349. RtInfo.dwRtInfoDest = dwDestAddr;
  350. RtInfo.dwRtInfoMask = dwDestMask;
  351. RtInfo.dwRtInfoIfIndex = dwIfIndex;
  352. RtInfo.dwRtInfoProto = dwProtoId;
  353. //
  354. // Delete this forward route from RTM
  355. //
  356. dwResult = DeleteRtmRoute(hRtmHandle,
  357. &RtInfo);
  358. if(dwResult isnot NO_ERROR)
  359. {
  360. Trace1(ERR,
  361. "DeleteSingleRoute: Error %d deleting route in RTM.",
  362. dwResult);
  363. }
  364. TraceLeave("DeleteSingleRoute");
  365. return dwResult;
  366. }
  367. DWORD
  368. DeleteAllRoutes(
  369. IN DWORD dwIfIndex,
  370. IN BOOL bStaticOnly
  371. )
  372. /*++
  373. Routine Description
  374. Deletes all the routes (owned by IP Router Manager) on the interface
  375. Arguments
  376. dwIfIndex
  377. bStaticOnly
  378. Return Value
  379. Error returned from RTM
  380. --*/
  381. {
  382. DWORD i, dwResult = NO_ERROR;
  383. TraceEnter("DeleteAllRoutes");
  384. for(i = 0;
  385. i < sizeof(g_rgRtmHandles)/sizeof(RTM_HANDLE_INFO);
  386. i++)
  387. {
  388. if(bStaticOnly && !g_rgRtmHandles[i].bStatic)
  389. {
  390. continue;
  391. }
  392. dwResult = DeleteRtmRoutesOnInterface(g_rgRtmHandles[i].hRouteHandle,
  393. dwIfIndex);
  394. if(dwResult isnot NO_ERROR)
  395. {
  396. Trace2(ERR,
  397. "DeleteAllRoutes: BlockDeleteRoutes returned %d for %d",
  398. dwResult,
  399. g_rgRtmHandles[i].dwProtoId);
  400. continue;
  401. }
  402. dwResult = DeleteRtmNexthopsOnInterface(g_rgRtmHandles[i].hRouteHandle,
  403. dwIfIndex);
  404. if(dwResult isnot NO_ERROR)
  405. {
  406. Trace2(ERR,
  407. "DeleteAllRoutes: BlockDeleteNextHops returned %d for %d",
  408. dwResult,
  409. g_rgRtmHandles[i].dwProtoId);
  410. continue;
  411. }
  412. }
  413. TraceLeave("DeleteAllRoutes");
  414. return dwResult;
  415. }
  416. VOID
  417. DeleteAllClientRoutes(
  418. PICB pIcb,
  419. DWORD dwServerIfIndex
  420. )
  421. /*++
  422. Routine Description
  423. Deletes all routes going to a client. Only needed for removal from
  424. RTM, stack removes them since the link has been deleted
  425. Arguments
  426. pIcb
  427. dwServerIfIndex - ServerInterface's ifIndex
  428. Return Value
  429. --*/
  430. {
  431. ULONG i;
  432. TraceEnter("DeleteAllClientRoutes");
  433. IpRtAssert(pIcb->ritType is ROUTER_IF_TYPE_CLIENT);
  434. if((pIcb->pStoredRoutes is NULL) or
  435. (pIcb->pibBindings is NULL))
  436. {
  437. return;
  438. }
  439. for(i = 0 ; i < pIcb->pStoredRoutes->dwNumEntries; i++)
  440. {
  441. DeleteSingleRoute(dwServerIfIndex,
  442. pIcb->pStoredRoutes->table[i].dwRtInfoDest,
  443. pIcb->pStoredRoutes->table[i].dwRtInfoMask,
  444. pIcb->pibBindings[0].dwAddress,
  445. PROTO_IP_NT_STATIC_NON_DOD,
  446. FALSE);
  447. }
  448. }
  449. VOID
  450. AddAllClientRoutes(
  451. PICB pIcb,
  452. DWORD dwServerIfIndex
  453. )
  454. /*++
  455. Routine Description
  456. Adds the stored routes over the server interface
  457. Arguments
  458. pIcb
  459. dwServerIfIndex - ServerInterface's ifIndex
  460. Return Value
  461. --*/
  462. {
  463. ULONG i;
  464. TraceEnter("AddAllClientRoutes");
  465. IpRtAssert(pIcb->ritType is ROUTER_IF_TYPE_CLIENT);
  466. if((pIcb->pStoredRoutes is NULL) or
  467. (pIcb->pibBindings is NULL))
  468. {
  469. return;
  470. }
  471. for(i = 0; i < pIcb->pStoredRoutes->dwNumEntries; i++)
  472. {
  473. //
  474. // Fix the next hop since that is not known
  475. // Also fix someother fields which we know are not being set
  476. // correctly for client routes
  477. //
  478. pIcb->pStoredRoutes->table[i].dwRtInfoNextHop =
  479. pIcb->pibBindings[0].dwAddress;
  480. pIcb->pStoredRoutes->table[i].dwRtInfoProto =
  481. PROTO_IP_NT_STATIC_NON_DOD;
  482. pIcb->pStoredRoutes->table[i].dwRtInfoMetric2 = 0;
  483. pIcb->pStoredRoutes->table[i].dwRtInfoMetric3 = 0;
  484. pIcb->pStoredRoutes->table[i].dwRtInfoPreference =
  485. ComputeRouteMetric(MIB_IPPROTO_LOCAL);
  486. pIcb->pStoredRoutes->table[i].dwRtInfoViewSet =
  487. RTM_VIEW_MASK_UCAST | RTM_VIEW_MASK_MCAST;
  488. AddSingleRoute(dwServerIfIndex,
  489. &(pIcb->pStoredRoutes->table[i]),
  490. pIcb->pibBindings[0].dwMask,
  491. 0, // RTM_ROUTE_INFO::Flags
  492. TRUE,
  493. TRUE,
  494. FALSE,
  495. NULL);
  496. }
  497. }
  498. DWORD
  499. GetNumStaticRoutes(
  500. PICB pIcb
  501. )
  502. /*++
  503. Routine Description
  504. Figure out the number of static routes associated with an interface
  505. Arguments
  506. pIcb The ICB of the interface whose route count is needed
  507. Return Value
  508. Number of routes associated with an interface
  509. --*/
  510. {
  511. HANDLE hRtmHandle;
  512. HANDLE hRtmEnum;
  513. PHANDLE hRoutes;
  514. DWORD dwHandles;
  515. DWORD dwNumRoutes;
  516. DWORD i, j;
  517. DWORD dwResult;
  518. hRoutes = HeapAlloc(
  519. IPRouterHeap,
  520. 0,
  521. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  522. );
  523. if (hRoutes == NULL)
  524. {
  525. Trace1(ERR,
  526. "GetNumStaticRoutes: Error allocating %d bytes for "
  527. "handles\n",
  528. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  529. );
  530. return 0;
  531. }
  532. dwNumRoutes = 0;
  533. for(i = 0;
  534. i < sizeof(g_rgRtmHandles)/sizeof(RTM_HANDLE_INFO);
  535. i++)
  536. {
  537. if(!g_rgRtmHandles[i].bStatic)
  538. {
  539. continue;
  540. }
  541. hRtmHandle = g_rgRtmHandles[i].hRouteHandle;
  542. dwResult = RtmCreateRouteEnum(hRtmHandle,
  543. NULL,
  544. RTM_VIEW_MASK_UCAST|RTM_VIEW_MASK_MCAST,
  545. RTM_ENUM_OWN_ROUTES,
  546. NULL,
  547. RTM_MATCH_INTERFACE,
  548. NULL,
  549. pIcb->dwIfIndex,
  550. &hRtmEnum);
  551. if(dwResult isnot NO_ERROR)
  552. {
  553. Trace2(ERR,
  554. "GetNumStaticRoutes: Error %d creating handle for %d\n",
  555. dwResult,
  556. g_rgRtmHandles[i].dwProtoId);
  557. continue;
  558. }
  559. do
  560. {
  561. dwHandles = g_rtmProfile.MaxHandlesInEnum;
  562. dwResult = RtmGetEnumRoutes(hRtmHandle,
  563. hRtmEnum,
  564. &dwHandles,
  565. hRoutes);
  566. dwNumRoutes += dwHandles;
  567. RtmReleaseRoutes(hRtmHandle, dwHandles, hRoutes);
  568. }
  569. while (dwResult is NO_ERROR);
  570. RtmDeleteEnumHandle(hRtmHandle, hRtmEnum);
  571. }
  572. HeapFree(IPRouterHeap, 0, hRoutes);
  573. return dwNumRoutes;
  574. }
  575. DWORD
  576. GetInterfaceRouteInfo(
  577. IN PICB pIcb,
  578. IN PRTR_TOC_ENTRY pToc,
  579. IN PBYTE pbDataPtr,
  580. IN OUT PRTR_INFO_BLOCK_HEADER pInfoHdr,
  581. IN OUT PDWORD pdwInfoSize
  582. )
  583. /*++
  584. Routine Description
  585. Gets the route info (static routes) associated with an interface
  586. Arguments
  587. pIcb The ICB of the interface for whom the info is requested
  588. pToc Pointer to TOC for the total inforamtion
  589. pbDataPtr Pointer to free space where info can be written
  590. pInfoHdr Pointer to Info Hdr
  591. pdwInfoSize Size of free space
  592. Return Value
  593. NO_ERROR or some code from RTM
  594. --*/
  595. {
  596. DWORD dwNumRoutes;
  597. PINTERFACE_ROUTE_INFO pRoutes = (PINTERFACE_ROUTE_INFO) pbDataPtr ;
  598. DWORD dwMaxRoutes;
  599. TraceEnter("GetInterfaceRouteInfo");
  600. dwNumRoutes = GetNumStaticRoutes(pIcb);
  601. dwMaxRoutes = MAX_ROUTES_IN_BUFFER(*pdwInfoSize);
  602. if(dwNumRoutes > dwMaxRoutes)
  603. {
  604. *pdwInfoSize = SIZEOF_ROUTEINFO(dwNumRoutes);
  605. return ERROR_INSUFFICIENT_BUFFER;
  606. }
  607. dwNumRoutes = ReadAllStaticRoutesIntoBuffer(pIcb,
  608. pRoutes,
  609. dwMaxRoutes);
  610. *pdwInfoSize = SIZEOF_ROUTEINFO(dwNumRoutes);
  611. //pToc->InfoVersion = sizeof(INTERFACE_ROUTE_INFO);
  612. pToc->InfoSize = sizeof(INTERFACE_ROUTE_INFO);
  613. pToc->InfoType = IP_ROUTE_INFO ;
  614. pToc->Count = dwNumRoutes;
  615. pToc->Offset = (ULONG)(pbDataPtr - (PBYTE) pInfoHdr) ;
  616. TraceLeave("GetInterfaceRouteInfo");
  617. return NO_ERROR;
  618. }
  619. DWORD
  620. ReadAllStaticRoutesIntoBuffer(
  621. PICB pIcb,
  622. PINTERFACE_ROUTE_INFO pRoutes,
  623. DWORD dwMaxRoutes
  624. )
  625. /*++
  626. Routine Description
  627. Reads out static routes from RTM
  628. Arguments
  629. pIcb The ICB of the interface for whom the route is
  630. routptr Pointer to where info has to be written out
  631. dwMaxRoutes Max routes the buffer can hold
  632. Return Value
  633. Count of routes written out
  634. --*/
  635. {
  636. HANDLE hRtmHandle;
  637. HANDLE hRtmEnum;
  638. PHANDLE hRoutes;
  639. PRTM_NET_ADDRESS pDestAddr;
  640. PRTM_ROUTE_INFO pRoute;
  641. RTM_NEXTHOP_INFO nhiInfo;
  642. RTM_ENTITY_INFO entityInfo;
  643. DWORD dwNumRoutes;
  644. DWORD dwHandles;
  645. DWORD i, j;
  646. DWORD dwResult;
  647. pRoute = HeapAlloc(
  648. IPRouterHeap,
  649. 0,
  650. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  651. );
  652. if (pRoute == NULL)
  653. {
  654. return 0;
  655. }
  656. hRoutes = HeapAlloc(
  657. IPRouterHeap,
  658. 0,
  659. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  660. );
  661. if (hRoutes == NULL)
  662. {
  663. HeapFree(IPRouterHeap, 0, pRoute);
  664. return 0;
  665. }
  666. pDestAddr = HeapAlloc(
  667. IPRouterHeap,
  668. 0,
  669. sizeof(RTM_NET_ADDRESS)
  670. );
  671. if (pDestAddr == NULL)
  672. {
  673. HeapFree(IPRouterHeap, 0, pRoute);
  674. HeapFree(IPRouterHeap, 0, hRoutes);
  675. return 0;
  676. }
  677. dwNumRoutes = 0;
  678. for(i = 0;
  679. (i < sizeof(g_rgRtmHandles)/sizeof(RTM_HANDLE_INFO)) and
  680. (dwNumRoutes < dwMaxRoutes);
  681. i++)
  682. {
  683. if(!g_rgRtmHandles[i].bStatic)
  684. {
  685. continue;
  686. }
  687. hRtmHandle = g_rgRtmHandles[i].hRouteHandle;
  688. dwResult = RtmCreateRouteEnum(hRtmHandle,
  689. NULL,
  690. RTM_VIEW_MASK_UCAST|RTM_VIEW_MASK_MCAST,
  691. RTM_ENUM_OWN_ROUTES,
  692. NULL,
  693. RTM_MATCH_INTERFACE,
  694. NULL,
  695. pIcb->dwIfIndex,
  696. &hRtmEnum);
  697. if(dwResult isnot NO_ERROR)
  698. {
  699. Trace2(ERR,
  700. "ReadAllStaticRoutesIntoBuffer: Error %d creating handle for %d\n",
  701. dwResult,
  702. g_rgRtmHandles[i].dwProtoId);
  703. continue;
  704. }
  705. do
  706. {
  707. dwHandles = g_rtmProfile.MaxHandlesInEnum;
  708. dwResult = RtmGetEnumRoutes(hRtmHandle,
  709. hRtmEnum,
  710. &dwHandles,
  711. hRoutes);
  712. //
  713. // We pick up all that we can in the buffer. If things
  714. // change between the time the size of the buffer was
  715. // calculated and now,we discard the additional routes
  716. //
  717. // TBD: * Log an event if the buffer was too small *
  718. //
  719. for (j = 0; (j < dwHandles) && (dwNumRoutes < dwMaxRoutes); j++)
  720. {
  721. // Get the route info corr. to this handle
  722. if (RtmGetRouteInfo(hRtmHandle,
  723. hRoutes[j],
  724. pRoute,
  725. pDestAddr) is NO_ERROR)
  726. {
  727. if (RtmGetEntityInfo(hRtmHandle,
  728. pRoute->RouteOwner,
  729. &entityInfo) is NO_ERROR)
  730. {
  731. if (RtmGetNextHopInfo(hRtmHandle,
  732. pRoute->NextHopsList.NextHops[0],
  733. &nhiInfo) is NO_ERROR)
  734. {
  735. // We assume that static routes have only 1 nexthop
  736. ConvertRtmToRouteInfo(entityInfo.EntityId.EntityProtocolId,
  737. pDestAddr,
  738. pRoute,
  739. &nhiInfo,
  740. &(pRoutes[dwNumRoutes++]));
  741. RtmReleaseNextHopInfo(hRtmHandle, &nhiInfo);
  742. }
  743. }
  744. RtmReleaseRouteInfo(hRtmHandle, pRoute);
  745. }
  746. }
  747. RtmReleaseRoutes(hRtmHandle, dwHandles, hRoutes);
  748. }
  749. while ((dwResult is NO_ERROR) && (dwNumRoutes < dwMaxRoutes));
  750. RtmDeleteEnumHandle(hRtmHandle, hRtmEnum);
  751. }
  752. HeapFree(IPRouterHeap, 0, pRoute);
  753. HeapFree(IPRouterHeap, 0, hRoutes);
  754. HeapFree(IPRouterHeap, 0, pDestAddr);
  755. return dwNumRoutes;
  756. }
  757. DWORD
  758. SetRouteInfo(
  759. PICB pIcb,
  760. PRTR_INFO_BLOCK_HEADER pInfoHdr
  761. )
  762. /*++
  763. Routine Description
  764. Sets the route info associated with an interface
  765. First we add the routes present in the route info. Then we enumerate
  766. the routes and delete those that we dont find in the route info
  767. Arguments
  768. pIcb The ICB of the interface for whom the route info is
  769. Return Value
  770. NO_ERROR
  771. --*/
  772. {
  773. PINTERFACE_ROUTE_INFO pRoutes;
  774. PRTR_TOC_ENTRY pToc;
  775. BOOL bP2P;
  776. HANDLE hRtmHandle;
  777. HANDLE hRtmEnum;
  778. PHANDLE hAddedRoutes;
  779. DWORD dwNumRoutes;
  780. PHANDLE hRoutes;
  781. DWORD dwHandles;
  782. DWORD i, j, k;
  783. DWORD dwFlags, dwResult;
  784. TraceEnter("SetRouteInfo");
  785. if(pIcb->dwOperationalState is UNREACHABLE)
  786. {
  787. Trace1(ROUTE,
  788. "SetRouteInfo: %S is unreachable, not setting routes",
  789. pIcb->pwszName);
  790. return NO_ERROR;
  791. }
  792. pToc = GetPointerToTocEntry(IP_ROUTE_INFO, pInfoHdr);
  793. if(pToc is NULL)
  794. {
  795. //
  796. // No TOC means no change
  797. //
  798. TraceLeave("SetRouteInfo");
  799. return NO_ERROR;
  800. }
  801. pRoutes = (PINTERFACE_ROUTE_INFO)GetInfoFromTocEntry(pInfoHdr,
  802. pToc);
  803. if((pToc->InfoSize is 0) or (pRoutes is NULL))
  804. {
  805. //
  806. // Delete all the static routes
  807. //
  808. DeleteAllRoutes(pIcb->dwIfIndex,
  809. TRUE);
  810. TraceLeave("SetRouteInfo");
  811. return NO_ERROR;
  812. }
  813. dwResult = NO_ERROR;
  814. dwNumRoutes = pToc->Count;
  815. // Handles to routes added are stored here
  816. hAddedRoutes = HeapAlloc(
  817. IPRouterHeap,
  818. 0,
  819. dwNumRoutes * sizeof(HANDLE)
  820. );
  821. if (hAddedRoutes == NULL)
  822. {
  823. Trace1(ERR,
  824. "SetRouteInfo: Error allocating %d bytes for addded "
  825. "route handles",
  826. dwNumRoutes * sizeof(HANDLE));
  827. TraceLeave("SetRouteInfo");
  828. return ERROR_NOT_ENOUGH_MEMORY;
  829. }
  830. hRoutes = HeapAlloc(
  831. IPRouterHeap,
  832. 0,
  833. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  834. );
  835. if (hRoutes == NULL)
  836. {
  837. Trace1(ERR,
  838. "SetRouteInfo: Error allocating %d bytes for route "
  839. "handles",
  840. dwNumRoutes * sizeof(HANDLE));
  841. HeapFree(IPRouterHeap, 0, hAddedRoutes);
  842. TraceLeave("SetRouteInfo");
  843. return ERROR_NOT_ENOUGH_MEMORY;
  844. }
  845. //
  846. // The route info is set in two phases. First, all the routes specified
  847. // are added, and then, the ones present, but not in the info are deleted
  848. //
  849. bP2P = IsIfP2P(pIcb->ritType);
  850. for(i = j = 0; i < dwNumRoutes; i++)
  851. {
  852. DWORD dwMask;
  853. //
  854. // If this will be a point to point interface,
  855. // ignore the next hop
  856. //
  857. if((pIcb->dwOperationalState is DISCONNECTED) and
  858. (pRoutes[i].dwRtInfoProto is PROTO_IP_NT_STATIC_NON_DOD))
  859. {
  860. continue;
  861. }
  862. if(bP2P)
  863. {
  864. pRoutes[i].dwRtInfoNextHop = pIcb->dwRemoteAddress;
  865. dwMask = ALL_ONES_MASK;
  866. }
  867. else
  868. {
  869. dwMask = GetBestNextHopMaskGivenIndex(pIcb->dwIfIndex,
  870. pRoutes[i].dwRtInfoNextHop);
  871. }
  872. if (AddSingleRoute(pIcb->dwIfIndex,
  873. &(pRoutes[i]),
  874. dwMask,
  875. 0, // RTM_ROUTE_INFO::Flags
  876. TRUE, // Valid route
  877. TRUE,
  878. bP2P,
  879. &hAddedRoutes[j]) is NO_ERROR)
  880. {
  881. j++;
  882. }
  883. }
  884. dwNumRoutes = j;
  885. //
  886. // Now enumerate the static routes, deleting the routes that are
  887. // not in the new list.
  888. //
  889. for(i = 0;
  890. i < sizeof(g_rgRtmHandles)/sizeof(RTM_HANDLE_INFO);
  891. i++)
  892. {
  893. if(!g_rgRtmHandles[i].bStatic)
  894. {
  895. continue;
  896. }
  897. hRtmHandle = g_rgRtmHandles[i].hRouteHandle;
  898. dwResult = RtmCreateRouteEnum(hRtmHandle,
  899. NULL,
  900. RTM_VIEW_MASK_UCAST | RTM_VIEW_MASK_MCAST,
  901. RTM_ENUM_OWN_ROUTES,
  902. NULL,
  903. RTM_MATCH_INTERFACE,
  904. NULL,
  905. pIcb->dwIfIndex,
  906. &hRtmEnum);
  907. if(dwResult isnot NO_ERROR)
  908. {
  909. Trace2(ERR,
  910. "SetRouteInfo: Error %d creating enum handle for %d",
  911. dwResult,
  912. g_rgRtmHandles[i].dwProtoId);
  913. continue;
  914. }
  915. do
  916. {
  917. dwHandles = g_rtmProfile.MaxHandlesInEnum;
  918. dwResult = RtmGetEnumRoutes(hRtmHandle,
  919. hRtmEnum,
  920. &dwHandles,
  921. hRoutes);
  922. for (j = 0; j < dwHandles; j++)
  923. {
  924. BOOL bFound = FALSE;
  925. for (k = 0; k < dwNumRoutes; k++)
  926. {
  927. if (hRoutes[j] == hAddedRoutes[k])
  928. {
  929. bFound = TRUE;
  930. break;
  931. }
  932. }
  933. if(!bFound)
  934. {
  935. if (RtmDeleteRouteToDest(g_rgRtmHandles[i].hRouteHandle,
  936. hRoutes[j],
  937. &dwFlags) is NO_ERROR)
  938. {
  939. continue;
  940. }
  941. }
  942. RtmReleaseRoutes(g_rgRtmHandles[i].hRouteHandle,
  943. 1,
  944. &hRoutes[j]);
  945. }
  946. }
  947. while (dwResult is NO_ERROR);
  948. RtmDeleteEnumHandle(hRtmHandle, hRtmEnum);
  949. }
  950. // Release the array of handles for routes added
  951. RtmReleaseRoutes(g_hLocalRoute, dwNumRoutes, hAddedRoutes);
  952. HeapFree(IPRouterHeap, 0, hAddedRoutes);
  953. HeapFree(IPRouterHeap, 0, hRoutes);
  954. TraceLeave("SetRouteInfo");
  955. return NO_ERROR;
  956. }
  957. #if 0
  958. DWORD
  959. EnableAllStaticRoutes (
  960. DWORD dwInterfaceIndex,
  961. BOOL fenable
  962. )
  963. /*++
  964. Routine Description
  965. Enables or disables Static Routes for an interface
  966. Locks
  967. Called with ICB_LIST lock held as READER
  968. Arguments
  969. pIcb The ICB of the interface
  970. fenable TRUE if enable
  971. Return Value
  972. NO_ERROR
  973. --*/
  974. {
  975. RTM_IP_ROUTE route ;
  976. TraceEnter("EnableAllStaticRoutes");
  977. Trace1(ROUTE, "EnableAllStaticRoutes entered with fenable = %d\n",
  978. fenable) ;
  979. route.RR_InterfaceID = dwInterfaceIndex;
  980. route.RR_RoutingProtocol = PROTO_IP_LOCAL;
  981. RtmBlockSetRouteEnable(g_hRtmHandle,
  982. RTM_ONLY_THIS_INTERFACE | RTM_ONLY_THIS_PROTOCOL,
  983. &route,
  984. fenable);
  985. route.RR_InterfaceID = dwInterfaceIndex;
  986. route.RR_RoutingProtocol = PROTO_IP_NT_AUTOSTATIC;
  987. RtmBlockSetRouteEnable(g_hAutoStaticHandle,
  988. RTM_ONLY_THIS_INTERFACE | RTM_ONLY_THIS_PROTOCOL,
  989. &route,
  990. fenable);
  991. TraceLeave("EnableAllStaticRoutes");
  992. return NO_ERROR;
  993. }
  994. #endif
  995. DWORD
  996. ConvertRoutesToAutoStatic(
  997. DWORD dwProtocolId,
  998. DWORD dwIfIndex
  999. )
  1000. /*++
  1001. Routine Description
  1002. Called to convert routes from a protocol's ownership (IP_RIP) to static
  1003. (PROTO_IP_NT_AUTOSTATIC)
  1004. Used for autostatic updates etc.
  1005. Arguments
  1006. protocolid Id of protocol whose routes are to be converted
  1007. interfaceindex Index of the interface whose routes are to be converted
  1008. Return Value
  1009. --*/
  1010. {
  1011. DWORD dwResult, dwFlags;
  1012. TraceEnter("ConvertRoutesToAutoStatic");
  1013. #if 0
  1014. //
  1015. // We now do the delete before calling the protocols update
  1016. // route
  1017. //
  1018. dwResult = DeleteRtmRoutesOnInterface(g_hAutoStaticHandle,
  1019. dwIfIndex);
  1020. if((dwResult isnot ERROR_NO_ROUTES) and
  1021. (dwResult isnot NO_ERROR))
  1022. {
  1023. Trace1(ERR,
  1024. "ConvertRoutesToAutoStatic: Error %d block deleting routes",
  1025. dwResult);
  1026. }
  1027. #endif
  1028. if(((dwResult = BlockConvertRoutesToStatic(g_hAutoStaticRoute,
  1029. dwIfIndex,
  1030. dwProtocolId)) isnot NO_ERROR))
  1031. {
  1032. dwResult = GetLastError();
  1033. Trace1(ROUTE,
  1034. "ConvertRoutesToAutoStatic: Rtm returned error: %d",
  1035. dwResult);
  1036. }
  1037. TraceLeave("ConvertRoutesToAutoStatic");
  1038. return dwResult;
  1039. }
  1040. VOID
  1041. ChangeAdapterIndexForDodRoutes (
  1042. DWORD dwInterfaceIndex
  1043. )
  1044. /*++
  1045. Routine Description
  1046. Changes the adapter index for static routes associated with an
  1047. interface. The adapter index can go from being valid (the index of a
  1048. net card known to the stack) to INVALID_INDEX. This happens when an
  1049. interface gets unmapped (say on disconnection). The stack special
  1050. cases the routes with index = 0xffffffff (invalid_index) and does demand
  1051. dial call out for packets destined on such adapters.
  1052. We only enumerate best routes, because this function short circuits
  1053. the normal metric comparison of RTM. If we ran this on all the routes,
  1054. we would be adding some routes to stack which were not meant to be there.
  1055. Arguments
  1056. pIcb The ICB of the interface
  1057. Return Value
  1058. None
  1059. --*/
  1060. {
  1061. HANDLE hRtmHandles[2];
  1062. HANDLE hRtmHandle;
  1063. HANDLE hRtmEnum;
  1064. PHANDLE hRoutes;
  1065. PRTM_NET_ADDRESS pDestAddr;
  1066. PRTM_ROUTE_INFO pRoute;
  1067. RTM_VIEW_SET fBestInViews;
  1068. DWORD dwHandles;
  1069. DWORD i, j;
  1070. DWORD dwResult;
  1071. pRoute = HeapAlloc(
  1072. IPRouterHeap,
  1073. 0,
  1074. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  1075. );
  1076. if (pRoute == NULL)
  1077. {
  1078. Trace1(
  1079. ERR, "ChangeAdapterIndexForDodRoutes : Error allocating %d "
  1080. " bytes for route info",
  1081. RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute)
  1082. );
  1083. return;
  1084. }
  1085. hRoutes = HeapAlloc(
  1086. IPRouterHeap,
  1087. 0,
  1088. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  1089. );
  1090. if (hRoutes == NULL)
  1091. {
  1092. Trace1(
  1093. ERR, "ChangeAdapterIndexForDodRoutes : Error allocating %d "
  1094. " bytes for route handles",
  1095. g_rtmProfile.MaxHandlesInEnum * sizeof(HANDLE)
  1096. );
  1097. HeapFree(IPRouterHeap, 0, pRoute);
  1098. return;
  1099. }
  1100. pDestAddr = HeapAlloc(
  1101. IPRouterHeap,
  1102. 0,
  1103. sizeof(RTM_NET_ADDRESS)
  1104. );
  1105. if (pDestAddr == NULL)
  1106. {
  1107. Trace1(
  1108. ERR, "ChangeAdapterIndexForDodRoutes : Error allocating %d "
  1109. " bytes for dest. address",
  1110. sizeof(RTM_NET_ADDRESS)
  1111. );
  1112. HeapFree(IPRouterHeap, 0, pRoute);
  1113. HeapFree(IPRouterHeap, 0, hRoutes);
  1114. return;
  1115. }
  1116. hRtmHandles[0] = g_hStaticRoute; // For all static (dod) routes..
  1117. hRtmHandles[1] = g_hAutoStaticRoute; // For all autostatic routes....
  1118. for (i = 0; i < 2; i++)
  1119. {
  1120. hRtmHandle = hRtmHandles[i];
  1121. dwResult = RtmCreateRouteEnum(hRtmHandle,
  1122. NULL,
  1123. RTM_VIEW_MASK_UCAST,
  1124. RTM_ENUM_OWN_ROUTES,
  1125. NULL,
  1126. RTM_MATCH_INTERFACE,
  1127. NULL,
  1128. dwInterfaceIndex,
  1129. &hRtmEnum);
  1130. if(dwResult isnot NO_ERROR)
  1131. {
  1132. Trace2(ERR,
  1133. "ChangeAdapterIndexForDodRoutes: Error %d creating enum handle for %s routes",
  1134. dwResult,
  1135. (i == 0) ? "static" : "autostatic");
  1136. }
  1137. else
  1138. {
  1139. do
  1140. {
  1141. dwHandles = g_rtmProfile.MaxHandlesInEnum;
  1142. dwResult = RtmGetEnumRoutes(hRtmHandle,
  1143. hRtmEnum,
  1144. &dwHandles,
  1145. hRoutes);
  1146. for (j = 0; j < dwHandles; j++)
  1147. {
  1148. // Is this the best route in unicast view
  1149. dwResult = RtmIsBestRoute(hRtmHandle,
  1150. hRoutes[j],
  1151. &fBestInViews);
  1152. if ((dwResult isnot NO_ERROR) or
  1153. (!(fBestInViews & RTM_VIEW_MASK_UCAST)))
  1154. {
  1155. continue;
  1156. }
  1157. // Get the route info corr. to this handle
  1158. if (RtmGetRouteInfo(hRtmHandle,
  1159. hRoutes[j],
  1160. pRoute,
  1161. pDestAddr) is NO_ERROR)
  1162. {
  1163. //
  1164. // This call adds the same route with the forwarder - with
  1165. // the current adapter index
  1166. //
  1167. /*
  1168. pRoute->RR_FamilySpecificData.FSD_Metric +=
  1169. g_ulDisconnectedMetricIncrement;
  1170. RtmAddRoute(g_hStaticRoute,
  1171. pRoute,
  1172. INFINITE,
  1173. &fFlags,
  1174. NULL,
  1175. NULL);
  1176. */
  1177. ChangeRouteWithForwarder(pDestAddr,
  1178. pRoute,
  1179. TRUE,
  1180. TRUE);
  1181. RtmReleaseRouteInfo(hRtmHandle, pRoute);
  1182. }
  1183. }
  1184. RtmReleaseRoutes(hRtmHandle, dwHandles, hRoutes);
  1185. }
  1186. while (dwResult is NO_ERROR);
  1187. RtmDeleteEnumHandle(hRtmHandle, hRtmEnum);
  1188. }
  1189. }
  1190. HeapFree(IPRouterHeap, 0, pRoute);
  1191. HeapFree(IPRouterHeap, 0, hRoutes);
  1192. HeapFree(IPRouterHeap, 0, pDestAddr);
  1193. return;
  1194. }
  1195. #if 0
  1196. DWORD
  1197. GetMaskForClientSubnet(
  1198. DWORD dwInternalAddress
  1199. )
  1200. /*++
  1201. Routine Description
  1202. Arguments
  1203. Return Value
  1204. --*/
  1205. {
  1206. HANDLE hEnum;
  1207. RTM_IP_ROUTE route;
  1208. TraceEnter("IsRoutePresent");
  1209. route.RR_RoutingProtocol = PROTO_IP_LOCAL;
  1210. hEnum = RtmCreateEnumerationHandle(RTM_PROTOCOL_FAMILY_IP,
  1211. RTM_ONLY_THIS_PROTOCOL,
  1212. &route);
  1213. if(hEnum is NULL)
  1214. {
  1215. return GetClassMask(dwInternalAddress);
  1216. }
  1217. while(RtmEnumerateGetNextRoute(hEnum, &route) isnot ERROR_NO_MORE_ROUTES)
  1218. {
  1219. if(route.RR_Network.N_NetMask is 0x00000000)
  1220. {
  1221. //
  1222. // Dont match default route
  1223. //
  1224. continue;
  1225. }
  1226. if((dwInternalAddress & route.RR_Network.N_NetMask) is route.RR_Network.N_NetNumber)
  1227. {
  1228. RtmCloseEnumerationHandle(hEnum);
  1229. TraceLeave("IsRoutePresent");
  1230. return route.RR_Network.N_NetMask;
  1231. }
  1232. }
  1233. RtmCloseEnumerationHandle(hEnum);
  1234. TraceLeave("IsRoutePresent");
  1235. return GetClassMask(dwInternalAddress);
  1236. }
  1237. #endif
  1238. VOID
  1239. AddAutomaticRoutes(
  1240. PICB pIcb,
  1241. DWORD dwAddress,
  1242. DWORD dwMask
  1243. )
  1244. /*++
  1245. Routine Description
  1246. This function adds the routes that are otherwise generated by the
  1247. stack. This is mainly done for consistency between RTM and kernel tables
  1248. The routes added are:
  1249. (i) local loopback
  1250. (ii) local multicast
  1251. (iii) local subnet -> if the dwMask is not 255.255.255.255
  1252. (iv) all subnets broadcast -> if the ClassMask and Mask are different
  1253. (v) all 1's broadcast
  1254. Since some of the routes are added to the stack the interface to adapter
  1255. index map must already be set before this function is called
  1256. VERY IMPORTANT:
  1257. One MUST add the local route before binding the interface because this
  1258. route is not going to be added to stack. However it has higher
  1259. priority than say an OSPF route. Now if we first bind the interface
  1260. to OSPF, it will add a network route for this interface (which will
  1261. get added to the stack since only Router Manager can add non
  1262. stack routes). Now when we add the local route to RTM, we will find
  1263. our route better because we are higher priority. So RTM will tell
  1264. us to delete the OSPF route (which we will since its a stack route).
  1265. Then he will tell us to add our route to the stack. But we wont
  1266. do this since its a non stack route. So we basically end up deleting
  1267. network route from the routing table
  1268. Locks
  1269. Arguments
  1270. Return Value
  1271. --*/
  1272. {
  1273. DWORD dwClassMask, dwResult;
  1274. INTERFACE_ROUTE_INFO RtInfo;
  1275. BOOL bP2P;
  1276. IpRtAssert(pIcb->bBound);
  1277. IpRtAssert(dwAddress isnot INVALID_IP_ADDRESS);
  1278. return;
  1279. bP2P = IsIfP2P(pIcb->ritType);
  1280. if(dwMask isnot ALL_ONES_MASK)
  1281. {
  1282. BOOL bStack, bDontAdd;
  1283. RTM_NET_ADDRESS DestAddr;
  1284. PRTM_DEST_INFO pDestInfo;
  1285. DWORD dwLen;
  1286. //
  1287. // We now add the subnet route to stack so that if race condition
  1288. // had deleted the route on stopping, the restarting
  1289. // fixes the problem
  1290. //
  1291. //
  1292. // NOTE: For the RAS Server Interface we need to add the route to the
  1293. // routing table only if such a route doesnt exist. We need to add it
  1294. // because we want the pool advertised by the routing protocols
  1295. // However, adding to the stack will fail since we dont have a valid
  1296. // next hop (which is needed for p2mp)
  1297. //
  1298. bDontAdd = FALSE;
  1299. if(pIcb->ritType is ROUTER_IF_TYPE_INTERNAL)
  1300. {
  1301. //
  1302. // If a route to this virtual net exists, dont add it
  1303. //
  1304. __try
  1305. {
  1306. pDestInfo =
  1307. _alloca(RTM_SIZE_OF_DEST_INFO(g_rtmProfile.NumberOfViews));
  1308. }
  1309. __except(EXCEPTION_EXECUTE_HANDLER)
  1310. {
  1311. IpRtAssert(FALSE);
  1312. }
  1313. RTM_IPV4_LEN_FROM_MASK(dwLen, dwMask);
  1314. RTM_IPV4_MAKE_NET_ADDRESS(&DestAddr, (dwAddress & dwMask), dwLen);
  1315. if (RtmGetExactMatchDestination(g_hLocalRoute,
  1316. &DestAddr,
  1317. RTM_BEST_PROTOCOL,
  1318. RTM_VIEW_MASK_UCAST,
  1319. pDestInfo) is NO_ERROR)
  1320. {
  1321. RtmReleaseDestInfo(g_hLocalRoute, pDestInfo);
  1322. Trace1(IF,
  1323. "AddAutomaticRoutes: Route to virtual LAN %d.%d.%d.%d already exists",
  1324. PRINT_IPADDR(dwAddress));
  1325. bDontAdd = TRUE;
  1326. }
  1327. }
  1328. if(!bDontAdd)
  1329. {
  1330. //
  1331. // Add the network route
  1332. //
  1333. RtInfo.dwRtInfoDest = (dwAddress & dwMask);
  1334. RtInfo.dwRtInfoMask = dwMask;
  1335. RtInfo.dwRtInfoNextHop = dwAddress;
  1336. RtInfo.dwRtInfoIfIndex = pIcb->dwIfIndex;
  1337. RtInfo.dwRtInfoMetric1 = 1;
  1338. RtInfo.dwRtInfoMetric2 = 1;
  1339. RtInfo.dwRtInfoMetric3 = 1;
  1340. RtInfo.dwRtInfoPreference = ComputeRouteMetric(MIB_IPPROTO_LOCAL);
  1341. RtInfo.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  1342. RTM_VIEW_MASK_MCAST; // XXX config
  1343. RtInfo.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  1344. RtInfo.dwRtInfoProto = MIB_IPPROTO_LOCAL;
  1345. RtInfo.dwRtInfoAge = INFINITE;
  1346. RtInfo.dwRtInfoNextHopAS = 0;
  1347. RtInfo.dwRtInfoPolicy = 0;
  1348. bStack = TRUE;
  1349. IpRtAssert(bP2P is FALSE);
  1350. dwResult = AddSingleRoute(pIcb->dwIfIndex,
  1351. &RtInfo,
  1352. dwMask,
  1353. // RTM_ROUTE_INFO::Flags
  1354. RTM_ROUTE_FLAGS_LOCAL,
  1355. TRUE, // Valid route
  1356. bStack,
  1357. bP2P,
  1358. NULL);
  1359. if(dwResult isnot NO_ERROR)
  1360. {
  1361. Trace1(ERR,
  1362. "AddAutoRoutes: Can't add subnet route for %d.%d.%d.%d",
  1363. PRINT_IPADDR(dwAddress));
  1364. }
  1365. }
  1366. }
  1367. if(g_pLoopbackInterfaceCb)
  1368. {
  1369. RtInfo.dwRtInfoDest = dwAddress;
  1370. RtInfo.dwRtInfoMask = HOST_ROUTE_MASK;
  1371. RtInfo.dwRtInfoNextHop = IP_LOOPBACK_ADDRESS;
  1372. RtInfo.dwRtInfoIfIndex = g_pLoopbackInterfaceCb->dwIfIndex;
  1373. RtInfo.dwRtInfoMetric1 = 1;
  1374. RtInfo.dwRtInfoMetric2 = 1;
  1375. RtInfo.dwRtInfoMetric3 = 1;
  1376. RtInfo.dwRtInfoPreference= ComputeRouteMetric(MIB_IPPROTO_LOCAL);
  1377. RtInfo.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  1378. RTM_VIEW_MASK_MCAST;
  1379. RtInfo.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  1380. RtInfo.dwRtInfoProto = MIB_IPPROTO_LOCAL;
  1381. RtInfo.dwRtInfoAge = INFINITE;
  1382. RtInfo.dwRtInfoNextHopAS = 0;
  1383. RtInfo.dwRtInfoPolicy = 0;
  1384. dwResult = AddSingleRoute(g_pLoopbackInterfaceCb->dwIfIndex,
  1385. &RtInfo,
  1386. dwMask,
  1387. // RTM_ROUTE_INFO::Flags
  1388. RTM_ROUTE_FLAGS_MYSELF,
  1389. TRUE,
  1390. FALSE,
  1391. FALSE,
  1392. NULL);
  1393. if(dwResult isnot NO_ERROR)
  1394. {
  1395. Trace1(ERR,
  1396. "AddAutoRoutes: Cant add 127.0.0.1 route for %d.%d.%d.%d",
  1397. PRINT_IPADDR(dwAddress));
  1398. }
  1399. }
  1400. RtInfo.dwRtInfoDest = LOCAL_NET_MULTICAST;
  1401. RtInfo.dwRtInfoMask = LOCAL_NET_MULTICAST_MASK;
  1402. RtInfo.dwRtInfoNextHop = dwAddress;
  1403. RtInfo.dwRtInfoIfIndex = pIcb->dwIfIndex;
  1404. RtInfo.dwRtInfoMetric1 = 1;
  1405. RtInfo.dwRtInfoMetric2 = 1;
  1406. RtInfo.dwRtInfoMetric3 = 1;
  1407. RtInfo.dwRtInfoPreference = ComputeRouteMetric(MIB_IPPROTO_LOCAL);
  1408. RtInfo.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST;
  1409. RtInfo.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  1410. RtInfo.dwRtInfoProto = MIB_IPPROTO_LOCAL;
  1411. RtInfo.dwRtInfoAge = INFINITE;
  1412. RtInfo.dwRtInfoNextHopAS = 0;
  1413. RtInfo.dwRtInfoPolicy = 0;
  1414. dwResult = AddSingleRoute(pIcb->dwIfIndex,
  1415. &RtInfo,
  1416. dwMask,
  1417. 0, // RTM_ROUTE_INFO::Flags
  1418. FALSE, // Protocols dont like a mcast route
  1419. FALSE, // No need to add to stack
  1420. bP2P,
  1421. NULL);
  1422. if(dwResult isnot NO_ERROR)
  1423. {
  1424. Trace1(ERR,
  1425. "AddAutoRoutes: Couldnt add 224.0.0.0 route for %d.%d.%d.%d",
  1426. PRINT_IPADDR(dwAddress));
  1427. }
  1428. //
  1429. // We add the All 1's Bcast route to all interfaces. This is
  1430. // actually a BUG since we should see if the medium allows
  1431. // broadcast (X.25 would be an example of one that didnt)
  1432. //
  1433. RtInfo.dwRtInfoDest = ALL_ONES_BROADCAST;
  1434. RtInfo.dwRtInfoMask = HOST_ROUTE_MASK;
  1435. RtInfo.dwRtInfoNextHop = dwAddress;
  1436. RtInfo.dwRtInfoIfIndex = pIcb->dwIfIndex;
  1437. RtInfo.dwRtInfoMetric1 = 1;
  1438. RtInfo.dwRtInfoMetric2 = 1;
  1439. RtInfo.dwRtInfoMetric3 = 1;
  1440. RtInfo.dwRtInfoPreference = ComputeRouteMetric(MIB_IPPROTO_LOCAL);
  1441. RtInfo.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST;
  1442. RtInfo.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  1443. RtInfo.dwRtInfoProto = MIB_IPPROTO_LOCAL;
  1444. RtInfo.dwRtInfoAge = INFINITE;
  1445. RtInfo.dwRtInfoNextHopAS = 0;
  1446. RtInfo.dwRtInfoPolicy = 0;
  1447. dwResult = AddSingleRoute(pIcb->dwIfIndex,
  1448. &RtInfo,
  1449. dwMask,
  1450. 0, // RTM_ROUTE_INFO::Flags
  1451. FALSE, // Protocols dont like a bcast route
  1452. FALSE, // No need to add to stack
  1453. bP2P,
  1454. NULL);
  1455. if(dwResult isnot NO_ERROR)
  1456. {
  1457. Trace1(ERR,
  1458. "AddAutRoutes: Couldnt add all 1's bcast route for %d.%d.%d.%d",
  1459. PRINT_IPADDR(dwAddress));
  1460. }
  1461. //
  1462. // We add the All Subnets Broadcast route if the class mask is different
  1463. // from the subnet mask
  1464. //
  1465. dwClassMask = GetClassMask(dwAddress);
  1466. if(dwClassMask isnot dwMask)
  1467. {
  1468. RtInfo.dwRtInfoDest = (dwAddress | ~dwClassMask);
  1469. RtInfo.dwRtInfoMask = HOST_ROUTE_MASK;
  1470. RtInfo.dwRtInfoNextHop = dwAddress;
  1471. RtInfo.dwRtInfoIfIndex = pIcb->dwIfIndex;
  1472. RtInfo.dwRtInfoMetric1 = 1;
  1473. RtInfo.dwRtInfoMetric2 = 1;
  1474. RtInfo.dwRtInfoMetric3 = 1;
  1475. RtInfo.dwRtInfoPreference= ComputeRouteMetric(MIB_IPPROTO_LOCAL);
  1476. RtInfo.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  1477. RTM_VIEW_MASK_MCAST; // XXX configurable
  1478. RtInfo.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  1479. RtInfo.dwRtInfoProto = MIB_IPPROTO_LOCAL;
  1480. RtInfo.dwRtInfoAge = INFINITE;
  1481. RtInfo.dwRtInfoNextHopAS = 0;
  1482. RtInfo.dwRtInfoPolicy = 0;
  1483. dwResult = AddSingleRoute(pIcb->dwIfIndex,
  1484. &RtInfo,
  1485. dwMask,
  1486. 0, // RTM_ROUTE_INFO::Flags
  1487. FALSE, // Protocols dont like a bcast route
  1488. FALSE, // No need to add to stack
  1489. bP2P,
  1490. NULL);
  1491. if(dwResult isnot NO_ERROR)
  1492. {
  1493. Trace1(ERR,
  1494. "AddAutoRoutes: Couldnt add all nets bcast route for %d.%d.%d.%d",
  1495. PRINT_IPADDR(dwAddress));
  1496. }
  1497. }
  1498. }
  1499. VOID
  1500. DeleteAutomaticRoutes(
  1501. PICB pIcb,
  1502. DWORD dwAddress,
  1503. DWORD dwMask
  1504. )
  1505. /*++
  1506. Routine Description
  1507. Locks
  1508. Arguments
  1509. Return Value
  1510. --*/
  1511. {
  1512. DWORD dwClassMask, dwResult;
  1513. BOOL bP2P;
  1514. if(dwAddress is INVALID_IP_ADDRESS)
  1515. {
  1516. IpRtAssert(FALSE);
  1517. }
  1518. return;
  1519. bP2P = IsIfP2P(pIcb->ritType);
  1520. //
  1521. // Delete the loopback route we added
  1522. //
  1523. if(g_pLoopbackInterfaceCb)
  1524. {
  1525. dwResult = DeleteSingleRoute(g_pLoopbackInterfaceCb->dwIfIndex,
  1526. dwAddress,
  1527. HOST_ROUTE_MASK,
  1528. IP_LOOPBACK_ADDRESS,
  1529. PROTO_IP_LOCAL,
  1530. FALSE);
  1531. if(dwResult isnot NO_ERROR)
  1532. {
  1533. Trace2(ERR,
  1534. "DeleteAutoRoutes: Error %d deleting loopback route on %d.%d.%d.%d",
  1535. dwResult,
  1536. PRINT_IPADDR(dwAddress));
  1537. }
  1538. }
  1539. //
  1540. // Delete the multicast route
  1541. //
  1542. dwResult = DeleteSingleRoute(pIcb->dwIfIndex,
  1543. LOCAL_NET_MULTICAST,
  1544. LOCAL_NET_MULTICAST_MASK,
  1545. dwAddress,
  1546. PROTO_IP_LOCAL,
  1547. bP2P);
  1548. if(dwResult isnot NO_ERROR)
  1549. {
  1550. Trace2(ERR,
  1551. "DeleteAutoRoutes: Error %d deleting 224.0.0.0 route on %d.%d.%d.%d",
  1552. dwResult,
  1553. PRINT_IPADDR(dwAddress));
  1554. }
  1555. if(dwMask isnot ALL_ONES_MASK)
  1556. {
  1557. //
  1558. // Delete the network route we added
  1559. //
  1560. IpRtAssert(bP2P is FALSE);
  1561. dwResult = DeleteSingleRoute(pIcb->dwIfIndex,
  1562. (dwAddress & dwMask),
  1563. dwMask,
  1564. dwAddress,
  1565. PROTO_IP_LOCAL,
  1566. bP2P);
  1567. if(dwResult isnot NO_ERROR)
  1568. {
  1569. Trace2(ERR,
  1570. "DeleteAutoRoutes: Error %d deleting subnet route for %d.%d.%d.%d",
  1571. dwResult,
  1572. PRINT_IPADDR(dwAddress));
  1573. }
  1574. }
  1575. //
  1576. // Delete the all nets bcast route
  1577. //
  1578. dwClassMask = GetClassMask(dwAddress);
  1579. if(dwClassMask isnot dwMask)
  1580. {
  1581. dwResult = DeleteSingleRoute(pIcb->dwIfIndex,
  1582. (dwAddress | ~dwClassMask),
  1583. HOST_ROUTE_MASK,
  1584. dwAddress,
  1585. PROTO_IP_LOCAL,
  1586. bP2P);
  1587. if(dwResult isnot NO_ERROR)
  1588. {
  1589. Trace2(ERR,
  1590. "DeleteAutoRoutes: Error %d deleting subnet bcast route on %x",
  1591. dwResult,
  1592. dwAddress);
  1593. }
  1594. //
  1595. // Delete the all 1's bcast route
  1596. //
  1597. }
  1598. dwResult = DeleteSingleRoute(pIcb->dwIfIndex,
  1599. ALL_ONES_BROADCAST,
  1600. HOST_ROUTE_MASK,
  1601. dwAddress,
  1602. PROTO_IP_LOCAL,
  1603. bP2P);
  1604. if(dwResult isnot NO_ERROR)
  1605. {
  1606. Trace2(ERR,
  1607. "DeleteAutoRoutes: Error %d deleting all 1's bcast route on %d.%d.%d.%d",
  1608. dwResult,
  1609. PRINT_IPADDR(dwAddress));
  1610. }
  1611. }
  1612. VOID
  1613. ChangeDefaultRouteMetrics(
  1614. IN BOOL bIncrement
  1615. )
  1616. /*++
  1617. Routine Description
  1618. Increments or decrements the default route(s) metrics.
  1619. For increment, it should be called BEFORE the default route for the
  1620. dial out interface is added, and for decrement it should be called AFTER
  1621. the dial out interface has been deleted
  1622. Locks
  1623. Called with the ICB lock held. This ensures that two such operations
  1624. are not being executed simultaneously (which would do the nasties to our
  1625. route table)
  1626. Arguments
  1627. bIncrement TRUE if we need to increment the metric
  1628. Return Value
  1629. None
  1630. --*/
  1631. {
  1632. ULONG i;
  1633. DWORD dwErr;
  1634. RTM_NET_ADDRESS NetAddress;
  1635. PRTM_ROUTE_HANDLE phRoutes;
  1636. PRTM_ROUTE_INFO pRouteInfo;
  1637. RTM_DEST_INFO DestInfo;
  1638. RTM_ENUM_HANDLE hEnum;
  1639. ZeroMemory(&NetAddress,
  1640. sizeof(NetAddress));
  1641. __try
  1642. {
  1643. phRoutes =
  1644. _alloca(sizeof(RTM_ROUTE_HANDLE) * g_rtmProfile.MaxHandlesInEnum);
  1645. pRouteInfo =
  1646. _alloca(RTM_SIZE_OF_ROUTE_INFO(g_rtmProfile.MaxNextHopsInRoute));
  1647. }
  1648. __except(EXCEPTION_EXECUTE_HANDLER)
  1649. {
  1650. return;
  1651. }
  1652. //
  1653. // Use any handle
  1654. //
  1655. dwErr = RtmGetExactMatchDestination(g_hLocalRoute,
  1656. &NetAddress,
  1657. RTM_BEST_PROTOCOL, // rather any
  1658. RTM_VIEW_ID_UCAST,
  1659. &DestInfo);
  1660. if(dwErr isnot NO_ERROR)
  1661. {
  1662. return;
  1663. }
  1664. hEnum = NULL;
  1665. dwErr = RtmCreateRouteEnum(g_hLocalRoute,
  1666. DestInfo.DestHandle,
  1667. RTM_VIEW_ID_UCAST,
  1668. RTM_ENUM_ALL_ROUTES,
  1669. NULL,
  1670. RTM_MATCH_NONE,
  1671. NULL,
  1672. 0,
  1673. &hEnum);
  1674. if(dwErr isnot NO_ERROR)
  1675. {
  1676. RtmReleaseDestInfo(g_hLocalRoute,
  1677. &DestInfo);
  1678. return;
  1679. }
  1680. do
  1681. {
  1682. RTM_ENTITY_HANDLE hRtmHandle;
  1683. ULONG j, ulCount;
  1684. ulCount = g_rtmProfile.MaxHandlesInEnum;
  1685. dwErr = RtmGetEnumRoutes(g_hLocalRoute,
  1686. hEnum,
  1687. &ulCount,
  1688. phRoutes);
  1689. if(ulCount < 1)
  1690. {
  1691. break;
  1692. }
  1693. for(i = 0 ; i < ulCount; i++)
  1694. {
  1695. PRTM_ROUTE_INFO pRtmRoute;
  1696. DWORD dwFlags;
  1697. dwErr = RtmGetRouteInfo(g_hLocalRoute,
  1698. phRoutes[i],
  1699. pRouteInfo,
  1700. NULL);
  1701. if(dwErr isnot NO_ERROR)
  1702. {
  1703. continue;
  1704. }
  1705. //
  1706. // See if we are the owner of this route
  1707. //
  1708. hRtmHandle = NULL;
  1709. for(j = 0;
  1710. j < sizeof(g_rgRtmHandles)/sizeof(RTM_HANDLE_INFO);
  1711. j++)
  1712. {
  1713. if(pRouteInfo->RouteOwner is g_rgRtmHandles[j].hRouteHandle)
  1714. {
  1715. hRtmHandle = g_rgRtmHandles[j].hRouteHandle;
  1716. break;
  1717. }
  1718. }
  1719. RtmReleaseRouteInfo(g_hLocalRoute,
  1720. pRouteInfo);
  1721. if(hRtmHandle is NULL)
  1722. {
  1723. continue;
  1724. }
  1725. //
  1726. // Lock the route (and re-read the info)
  1727. //
  1728. dwErr = RtmLockRoute(hRtmHandle,
  1729. phRoutes[i],
  1730. TRUE,
  1731. TRUE,
  1732. &pRtmRoute);
  1733. if(dwErr isnot NO_ERROR)
  1734. {
  1735. continue;
  1736. }
  1737. //
  1738. // If we have to decrease the metric and it is already 1,
  1739. // let it be
  1740. //
  1741. if(!bIncrement)
  1742. {
  1743. if(pRtmRoute->PrefInfo.Metric <= 1)
  1744. {
  1745. RtmLockRoute(hRtmHandle,
  1746. phRoutes[i],
  1747. TRUE,
  1748. FALSE,
  1749. NULL);
  1750. continue;
  1751. }
  1752. }
  1753. //
  1754. // Now update the route
  1755. //
  1756. if(bIncrement)
  1757. {
  1758. pRtmRoute->PrefInfo.Metric++;
  1759. }
  1760. else
  1761. {
  1762. pRtmRoute->PrefInfo.Metric--;
  1763. }
  1764. dwFlags = 0;
  1765. dwErr = RtmUpdateAndUnlockRoute(hRtmHandle,
  1766. phRoutes[i],
  1767. INFINITE,
  1768. NULL,
  1769. 0,
  1770. NULL,
  1771. &dwFlags);
  1772. if(dwErr isnot NO_ERROR)
  1773. {
  1774. RtmLockRoute(hRtmHandle,
  1775. phRoutes[i],
  1776. TRUE,
  1777. FALSE,
  1778. NULL);
  1779. }
  1780. }
  1781. RtmReleaseRoutes(g_hLocalRoute,
  1782. ulCount,
  1783. phRoutes);
  1784. }while(TRUE);
  1785. RtmDeleteEnumHandle(g_hLocalRoute,
  1786. hEnum);
  1787. RtmReleaseDestInfo(g_hLocalRoute,
  1788. &DestInfo);
  1789. return;
  1790. }
  1791. VOID
  1792. AddAllStackRoutes(
  1793. PICB pIcb
  1794. )
  1795. /*++
  1796. Routine Description:
  1797. This function picks up the default gateway and persistent routes
  1798. that the stack may have added under the covers for this interface
  1799. and adds them to RTM
  1800. Locks:
  1801. ICB_LIST lock must be held as WRITER
  1802. Arguments:
  1803. dwIfIndex Interface index
  1804. Return Value:
  1805. none
  1806. --*/
  1807. {
  1808. DWORD dwErr, dwMask, i;
  1809. BOOL bStack;
  1810. PMIB_IPFORWARDTABLE pRouteTable;
  1811. TraceEnter("AddAllStackRoutes");
  1812. IpRtAssert(!IsIfP2P(pIcb->ritType));
  1813. dwErr = AllocateAndGetIpForwardTableFromStack(&pRouteTable,
  1814. FALSE,
  1815. IPRouterHeap,
  1816. 0);
  1817. if(dwErr isnot NO_ERROR)
  1818. {
  1819. Trace1(ERR,
  1820. "AddAllStackRoutes: Couldnt get initial routes. Error %d",
  1821. dwErr);
  1822. return;
  1823. }
  1824. for(i = 0; i < pRouteTable->dwNumEntries; i++)
  1825. {
  1826. if(pRouteTable->table[i].dwForwardIfIndex isnot pIcb->dwIfIndex)
  1827. {
  1828. //
  1829. // Not going out over this interface
  1830. //
  1831. continue;
  1832. }
  1833. #if 1
  1834. //
  1835. // Pick up only PROTO_IP_LOCAL and PROTO_IP_NETMGMT routes
  1836. // from the IP stack
  1837. //
  1838. if((pRouteTable->table[i].dwForwardProto isnot PROTO_IP_LOCAL) and
  1839. (pRouteTable->table[i].dwForwardProto isnot PROTO_IP_NETMGMT))
  1840. {
  1841. continue;
  1842. }
  1843. #else
  1844. if((pRouteTable->table[i].dwForwardProto isnot PROTO_IP_NT_STATIC_NON_DOD) and
  1845. (pRouteTable->table[i].dwForwardDest isnot 0))
  1846. {
  1847. //
  1848. // Only pick up default gateways and persistent routes
  1849. //
  1850. continue;
  1851. }
  1852. #endif
  1853. dwMask = GetBestNextHopMaskGivenICB(pIcb,
  1854. pRouteTable->table[i].dwForwardDest);
  1855. bStack = TRUE;
  1856. if((pRouteTable->table[i].dwForwardProto is PROTO_IP_NETMGMT) &&
  1857. (pRouteTable->table[i].dwForwardMask is HOST_ROUTE_MASK))
  1858. {
  1859. bStack = FALSE;
  1860. }
  1861. if(pRouteTable->table[i].dwForwardProto is PROTO_IP_LOCAL)
  1862. {
  1863. if((pRouteTable->table[i].dwForwardMask is HOST_ROUTE_MASK)
  1864. or
  1865. ((pRouteTable->table[i].dwForwardDest &
  1866. ((DWORD) 0x000000FF)) >= ((DWORD) 0x000000E0))
  1867. or
  1868. (pRouteTable->table[i].dwForwardDest ==
  1869. (pRouteTable->table[i].dwForwardDest |
  1870. ~pRouteTable->table[i].dwForwardMask)))
  1871. {
  1872. bStack = FALSE;
  1873. }
  1874. }
  1875. dwErr = AddSingleRoute(pIcb->dwIfIndex,
  1876. ConvertMibRouteToRouteInfo(&(pRouteTable->table[i])),
  1877. dwMask,
  1878. 0, // RTM_ROUTE_INFO::Flags
  1879. TRUE, // Valid route
  1880. bStack, // Do not add back to stack
  1881. FALSE, // Only called for non P2P i/fs
  1882. NULL);
  1883. }
  1884. TraceLeave("AddAllStackRoutes");
  1885. return;
  1886. }
  1887. VOID
  1888. UpdateDefaultRoutes(
  1889. VOID
  1890. )
  1891. {
  1892. DWORD dwErr, dwMask, i, j;
  1893. BOOL bFound;
  1894. PMIB_IPFORWARDTABLE pRouteTable;
  1895. PINTERFACE_ROUTE_INFO pRtInfo;
  1896. TraceEnter("UpdateDefaultRoutes");
  1897. //
  1898. // Get the routes in an ordered table
  1899. //
  1900. dwErr = AllocateAndGetIpForwardTableFromStack(&pRouteTable,
  1901. TRUE,
  1902. IPRouterHeap,
  1903. 0);
  1904. if(dwErr isnot NO_ERROR)
  1905. {
  1906. Trace1(ERR,
  1907. "UpdateDefaultRoutes: Couldnt get routes. Error %d",
  1908. dwErr);
  1909. return;
  1910. }
  1911. //
  1912. // Now add the dgs not already present
  1913. //
  1914. for(i = 0; i < pRouteTable->dwNumEntries; i++)
  1915. {
  1916. PICB pIcb;
  1917. TraceRoute2(
  1918. ROUTE, "%d.%d.%d.%d/%d.%d.%d.%d",
  1919. PRINT_IPADDR( pRouteTable-> table[i].dwForwardDest ),
  1920. PRINT_IPADDR( pRouteTable-> table[i].dwForwardMask )
  1921. );
  1922. //
  1923. // Once we get past the default routes, we are done
  1924. //
  1925. if(pRouteTable->table[i].dwForwardDest isnot 0)
  1926. {
  1927. #if TRACE_DBG
  1928. continue;
  1929. #else
  1930. break;
  1931. #endif
  1932. }
  1933. if(pRouteTable->table[i].dwForwardIfIndex is INVALID_IF_INDEX)
  1934. {
  1935. continue;
  1936. }
  1937. if(pRouteTable->table[i].dwForwardProto isnot PROTO_IP_NETMGMT)
  1938. {
  1939. continue;
  1940. }
  1941. pIcb = InterfaceLookupByIfIndex(pRouteTable->table[i].dwForwardIfIndex);
  1942. if(pIcb is NULL)
  1943. {
  1944. Trace1(ERR,
  1945. "UpdateDefaultRoutes: Couldnt get icb for %x",
  1946. pRouteTable->table[i].dwForwardIfIndex);
  1947. continue;
  1948. }
  1949. //
  1950. // Dont need to do this for p2p interfaces
  1951. //
  1952. if(IsIfP2P(pIcb->ritType))
  1953. {
  1954. continue;
  1955. }
  1956. dwMask = GetBestNextHopMaskGivenICB(pIcb,
  1957. pRouteTable->table[i].dwForwardDest);
  1958. Trace1(ROUTE,
  1959. "UpdateDefaultRoutes: Adding default route over %S",
  1960. pIcb->pwszName);
  1961. dwErr = AddSingleRoute(pIcb->dwIfIndex,
  1962. ConvertMibRouteToRouteInfo(&(pRouteTable->table[i])),
  1963. dwMask,
  1964. 0, // RTM_ROUTE_INFO::Flags
  1965. TRUE, // Valid route
  1966. TRUE, // Add the route to stack
  1967. FALSE, // Only called for non P2P i/fs
  1968. NULL);
  1969. if(dwErr isnot NO_ERROR)
  1970. {
  1971. Trace3(ERR,
  1972. "UpdateDefaultRoutes: Error %d adding dg to %d.%d.%d.%d over %x",
  1973. dwErr,
  1974. PRINT_IPADDR(pRouteTable->table[i].dwForwardNextHop),
  1975. pRouteTable->table[i].dwForwardIfIndex);
  1976. }
  1977. #if 0
  1978. else
  1979. {
  1980. if(g_ulGatewayCount < g_ulGatewayMaxCount)
  1981. {
  1982. g_pGateways[g_ulGatewayCount].dwAddress =
  1983. pRouteTable->table[i].dwForwardNextHop;
  1984. g_pGateways[g_ulGatewayCount].dwMetric =
  1985. pRouteTable->table[i].dwForwardMetric1;
  1986. g_pGateways[g_ulGatewayCount].dwIfIndex =
  1987. pRouteTable->table[i].dwForwardIfIndex;
  1988. g_ulGatewayCount++;
  1989. }
  1990. else
  1991. {
  1992. PGATEWAY_INFO pNewGw;
  1993. IpRtAssert(g_ulGatewayCount == g_ulGatewayMaxCount);
  1994. pNewGw = HeapAlloc(IPRouterHeap,
  1995. HEAP_ZERO_MEMORY,
  1996. (g_ulGatewayMaxCount + 5) * sizeof(GATEWAY_INFO));
  1997. if(pNewGw isnot NULL)
  1998. {
  1999. g_ulGatewayMaxCount = g_ulGatewayMaxCount + 5;
  2000. for(j = 0; j < g_ulGatewayCount; j++)
  2001. {
  2002. pNewGw[j] = g_pGateways[j];
  2003. }
  2004. if(g_pGateways isnot NULL)
  2005. {
  2006. HeapFree(IPRouterHeap,
  2007. 0,
  2008. g_pGateways);
  2009. }
  2010. g_pGateways = pNewGw;
  2011. g_pGateways[g_ulGatewayCount].dwAddress =
  2012. pRouteTable->table[i].dwForwardNextHop;
  2013. g_pGateways[g_ulGatewayCount].dwMetric =
  2014. pRouteTable->table[i].dwForwardMetric1;
  2015. g_pGateways[g_ulGatewayCount].dwIfIndex =
  2016. pRouteTable->table[i].dwForwardIfIndex;
  2017. g_ulGatewayCount++;
  2018. }
  2019. }
  2020. }
  2021. #endif
  2022. }
  2023. HeapFree(IPRouterHeap,
  2024. 0,
  2025. pRouteTable);
  2026. TraceLeave("UpdateDefaultRoutes");
  2027. return;
  2028. }
  2029. NTSTATUS
  2030. PostIoctlForRouteChangeNotification(
  2031. DWORD ulIndex
  2032. )
  2033. /*++
  2034. Routine Description:
  2035. This routine posts an IOCTL with the TCP/IP driver for route change
  2036. notifications caused by addition of routes to the stack by entities
  2037. other than Router Manager
  2038. Arguments:
  2039. ulIndex - Index into array of notifications indicating which one
  2040. needs to be posted
  2041. Return Value
  2042. STATUS_SUCCESS - Success
  2043. NTSTATUS code - Otherwise
  2044. Environment:
  2045. --*/
  2046. {
  2047. NTSTATUS status;
  2048. status = NtDeviceIoControlFile(
  2049. g_hIpRouteChangeDevice,
  2050. g_hRouteChangeEvents[ulIndex],
  2051. NULL,
  2052. NULL,
  2053. &g_rgIpRouteNotifyOutput[ulIndex].ioStatus,
  2054. IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX,
  2055. &g_IpNotifyData,
  2056. sizeof(IPNotifyData),
  2057. &g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput,
  2058. sizeof(IPRouteNotifyOutput)
  2059. );
  2060. if ((status isnot STATUS_SUCCESS) and
  2061. (status isnot STATUS_PENDING))
  2062. {
  2063. Trace2(
  2064. ERR,
  2065. "Error 0x%x posting route change notification[%d]",
  2066. status, ulIndex
  2067. );
  2068. }
  2069. return status;
  2070. }
  2071. DWORD
  2072. HandleRouteChangeNotification(
  2073. ULONG ulIndex
  2074. )
  2075. /*++
  2076. --*/
  2077. {
  2078. DWORD dwResult = NO_ERROR, dwFlags, dwClassMask;
  2079. BOOL bValid, bStack = FALSE;
  2080. WORD wRouteFlags = 0;
  2081. INTERFACE_ROUTE_INFO RtInfo;
  2082. PICB pIcb;
  2083. TraceEnter("HandleRouteChangeNotification");
  2084. TraceRoute2(
  2085. ROUTE, "Change for route to %d.%d.%d.%d/%d.%d.%d.%d",
  2086. PRINT_IPADDR(g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_dest),
  2087. PRINT_IPADDR(g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_mask)
  2088. );
  2089. TraceRoute3(
  2090. ROUTE, "Proto : %d, via i/f 0x%x, nexthop %d.%d.%d.%d",
  2091. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_proto,
  2092. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_ifindex,
  2093. PRINT_IPADDR(g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_nexthop)
  2094. );
  2095. TraceRoute2(
  2096. ROUTE, "Metric : %d, Change : 0x%x",
  2097. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_metric,
  2098. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_flags
  2099. );
  2100. //
  2101. // Update RTM route table as per route change indication
  2102. //
  2103. ENTER_READER(ICB_LIST);
  2104. do
  2105. {
  2106. pIcb = InterfaceLookupByIfIndex(
  2107. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_ifindex
  2108. );
  2109. if (pIcb == NULL)
  2110. {
  2111. //
  2112. // if there is no interface with the specified index in
  2113. // router manager, skip this route
  2114. //
  2115. Trace3(
  2116. ERR,
  2117. "Failed to add route to %d.%d.%d.%d/%d.%d.%d.%d."
  2118. "Interface index %d not present with router manager",
  2119. PRINT_IPADDR(g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_dest),
  2120. PRINT_IPADDR(g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_mask),
  2121. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_ifindex
  2122. );
  2123. break;
  2124. }
  2125. //
  2126. // if route had been added to stack, add it to RTM
  2127. //
  2128. dwFlags =
  2129. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_flags;
  2130. ConvertRouteNotifyOutputToRouteInfo(
  2131. &g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput,
  2132. &RtInfo
  2133. );
  2134. if ((dwFlags is 0) or (dwFlags & IRNO_FLAG_ADD))
  2135. {
  2136. bValid = TRUE;
  2137. if (RtInfo.dwRtInfoProto == PROTO_IP_LOCAL)
  2138. {
  2139. //
  2140. // Set appropriate RTM flags for local routes
  2141. //
  2142. if (RtInfo.dwRtInfoNextHop == IP_LOOPBACK_ADDRESS)
  2143. {
  2144. //
  2145. // Route over loopback. Set MYSELF flag
  2146. //
  2147. wRouteFlags = RTM_ROUTE_FLAGS_MYSELF;
  2148. }
  2149. else if ((RtInfo.dwRtInfoMask != HOST_ROUTE_MASK ) &&
  2150. ((RtInfo.dwRtInfoDest & RtInfo.dwRtInfoMask) <
  2151. ((DWORD) 0x000000E0)))
  2152. {
  2153. //
  2154. // RTM_ROUTE_FLAGS_LOCAL is set only for subnet
  2155. // routes. Not sure why this is so. I am only
  2156. // preserving the semantics from AddAutomaticRoutes
  2157. // Either way the consequences are not drastic since
  2158. // this does not affect the IP forwarding table in
  2159. // the stack.
  2160. // - VRaman
  2161. //
  2162. //
  2163. // We arrive at the fact that this is a subnet route
  2164. // in a roundabout fashion by eliminating
  2165. // PROTO_IP_LOCAL routes that are host routes and
  2166. // by eliminating any broadcast routes
  2167. //
  2168. // Since the host route check eliminates all routes
  2169. // with an all 1's mask, subnet/net broadcast routes
  2170. // are also eliminated.
  2171. //
  2172. wRouteFlags = RTM_ROUTE_FLAGS_LOCAL;
  2173. }
  2174. //
  2175. // mark mcast/bcast route as invalid so the protocols
  2176. // do not advertize them
  2177. //
  2178. dwClassMask = GetClassMask(RtInfo.dwRtInfoDest);
  2179. if ((RtInfo.dwRtInfoDest & (DWORD) 0x000000FF) >=
  2180. ((DWORD) 0x000000E0) ||
  2181. (RtInfo.dwRtInfoDest ==
  2182. (RtInfo.dwRtInfoDest | ~dwClassMask)))
  2183. {
  2184. bValid = FALSE;
  2185. }
  2186. else
  2187. {
  2188. //
  2189. // For PROTO_IP_LOCAL we do not add them back to
  2190. // the stack since these are managed by the stack
  2191. // We add them to RTM only to keep the user mode
  2192. // route table synchronized with the stack
  2193. //
  2194. // On second thoughts, we do need to add them
  2195. // back to the stack. More accurately, we need to
  2196. // try and add them back to the stack. This
  2197. // operation should fail, but as a side effect of
  2198. // this existing non PROTO_IP_LOCAL in the stack
  2199. // will be deleted.
  2200. // This is required in case of local subnet
  2201. // routes. It is possible that before an
  2202. // interface is enabled with IP, a route to the
  2203. // connected subnet may have been learnt over
  2204. // another interface via a routing protocol and
  2205. // added to the stack. When an interface is
  2206. // enabled all previously added routes to the
  2207. // local subnet should be deleted if the
  2208. // PROTO_IP_LOCAL route is the best route (which
  2209. // it should be unless you have a really wierd set
  2210. // of protocol preferences).
  2211. // Otherwise we run the risk of having non-best
  2212. // routes in the IP stack that are never deleted
  2213. // when the user mode route corresponding to it is
  2214. // deleted since you do not get a route change
  2215. // notification for non-best routes. The result is
  2216. // that you end up with state routes in the stack
  2217. //
  2218. if (RtInfo.dwRtInfoMask != HOST_ROUTE_MASK)
  2219. {
  2220. bStack = TRUE;
  2221. }
  2222. }
  2223. }
  2224. //
  2225. // Routes learn't from the stack are normally not
  2226. // added back to the stack. Hence the bStack is
  2227. // initialized to FALSE.
  2228. //
  2229. // PROTO_IP_NETMGT are not managed by the stack. They
  2230. // can be added/deleted/updated by user mode processes.
  2231. // As consequence a NETMGT route learned from the stack
  2232. // may be superseded by a route with a different protocol
  2233. // ID e.g. static. When the superseding route is deleted
  2234. // the NETMGMT routes need to be restored to the stack.
  2235. // Hence for NETMGMT routes we set bStack = true.
  2236. //
  2237. // An exception the processing of NETMGMT routes are HOST routes
  2238. // It is assumed by host routes added directly to the
  2239. // stack are managed by the process adding/deleting them
  2240. // e.g.RASIPCP
  2241. // They are added to RTM for sync. with the stack route table
  2242. // only. So for these we set bStack = FALSE
  2243. //
  2244. //
  2245. if ((RtInfo.dwRtInfoProto is PROTO_IP_NETMGMT) &&
  2246. (RtInfo.dwRtInfoMask isnot HOST_ROUTE_MASK))
  2247. {
  2248. bStack = TRUE;
  2249. }
  2250. TraceRoute5(
  2251. ROUTE, "NHOP mask %d.%d.%d.%d, Flag 0x%x, Valid %d, "
  2252. "Stack %d, P2P %d",
  2253. PRINT_IPADDR(GetBestNextHopMaskGivenICB(
  2254. pIcb, RtInfo.dwRtInfoNextHop)),
  2255. wRouteFlags,
  2256. bValid,
  2257. bStack,
  2258. IsIfP2P(pIcb->ritType)
  2259. );
  2260. dwResult = AddSingleRoute(
  2261. RtInfo.dwRtInfoIfIndex,
  2262. &RtInfo,
  2263. GetBestNextHopMaskGivenICB(
  2264. pIcb, RtInfo.dwRtInfoNextHop
  2265. ),
  2266. wRouteFlags,
  2267. bValid,
  2268. bStack,
  2269. IsIfP2P(pIcb->ritType),
  2270. NULL
  2271. );
  2272. if (dwResult != NO_ERROR)
  2273. {
  2274. Trace2(
  2275. ERR, "HandleRouteChangeNotification: Failed to add "
  2276. "route %d.%d.%d.%d, error %d",
  2277. PRINT_IPADDR(RtInfo.dwRtInfoDest),
  2278. dwResult
  2279. );
  2280. break;
  2281. }
  2282. }
  2283. else if (dwFlags & IRNO_FLAG_DELETE)
  2284. {
  2285. dwResult = DeleteSingleRoute(
  2286. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_ifindex,
  2287. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_dest,
  2288. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_mask,
  2289. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_nexthop,
  2290. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_proto,
  2291. IsIfP2P(pIcb->ritType)
  2292. );
  2293. if (dwResult != NO_ERROR)
  2294. {
  2295. Trace2(
  2296. ERR, "HandleRouteChangeNotification: Failed to"
  2297. "delete route %d.%d.%d.%d, error %d",
  2298. PRINT_IPADDR(
  2299. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_dest),
  2300. dwResult
  2301. );
  2302. break;
  2303. }
  2304. }
  2305. else
  2306. {
  2307. Trace1(
  2308. ERR, "HandleRouteChangeNotification: Invalid flags "
  2309. "0x%x",
  2310. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_flags
  2311. );
  2312. break;
  2313. }
  2314. if (RtInfo.dwRtInfoProto is PROTO_IP_NETMGMT)
  2315. {
  2316. UpdateStackRoutesToRestoreList(
  2317. ConvertRouteInfoToMibRoute( &RtInfo ),
  2318. dwFlags
  2319. );
  2320. }
  2321. } while (FALSE);
  2322. EXIT_LOCK(ICB_LIST);
  2323. PostIoctlForRouteChangeNotification(ulIndex);
  2324. TraceLeave("HandleRouteChangeNotification");
  2325. return dwResult;
  2326. }
  2327. VOID
  2328. AddLoopbackRoute(
  2329. DWORD dwIfAddress,
  2330. DWORD dwIfMask
  2331. )
  2332. {
  2333. DWORD dwResult;
  2334. INTERFACE_ROUTE_INFO rifRoute;
  2335. MIB_IPFORWARDROW mibRoute;
  2336. rifRoute.dwRtInfoMask = HOST_ROUTE_MASK;
  2337. rifRoute.dwRtInfoNextHop = IP_LOOPBACK_ADDRESS;
  2338. rifRoute.dwRtInfoDest = dwIfAddress;
  2339. rifRoute.dwRtInfoIfIndex = g_pLoopbackInterfaceCb->dwIfIndex;
  2340. rifRoute.dwRtInfoMetric2 = 0;
  2341. rifRoute.dwRtInfoMetric3 = 0;
  2342. rifRoute.dwRtInfoPreference = ComputeRouteMetric(MIB_IPPROTO_LOCAL);
  2343. rifRoute.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  2344. RTM_VIEW_MASK_MCAST; // XXX config
  2345. rifRoute.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  2346. rifRoute.dwRtInfoProto = MIB_IPPROTO_LOCAL;
  2347. rifRoute.dwRtInfoAge = 0;
  2348. rifRoute.dwRtInfoNextHopAS = 0;
  2349. rifRoute.dwRtInfoPolicy = 0;
  2350. //
  2351. // Query IP stack to verify for loopback route
  2352. // corresponding to this binding
  2353. //
  2354. dwResult = GetBestRoute(
  2355. dwIfAddress,
  2356. 0,
  2357. &mibRoute
  2358. );
  2359. if(dwResult isnot NO_ERROR)
  2360. {
  2361. Trace2(
  2362. ERR,
  2363. "InitLoopIf: Stack query for loopback route"
  2364. " associated with %d.%d.%d.%d failed, error %d",
  2365. PRINT_IPADDR(dwIfAddress),
  2366. dwResult
  2367. );
  2368. return;
  2369. }
  2370. if (mibRoute.dwForwardIfIndex !=
  2371. g_pLoopbackInterfaceCb->dwIfIndex)
  2372. {
  2373. //
  2374. // There appears to be no loopback address
  2375. // very strange
  2376. //
  2377. Trace1(
  2378. ERR,
  2379. "InitLoopIf: No loopback route for %d.%d.%d.%d"
  2380. "in stack",
  2381. PRINT_IPADDR(dwIfAddress)
  2382. );
  2383. return;
  2384. }
  2385. //
  2386. // Use metric returned from stack.
  2387. //
  2388. rifRoute.dwRtInfoMetric1 = mibRoute.dwForwardMetric1;
  2389. dwResult = AddSingleRoute(g_pLoopbackInterfaceCb->dwIfIndex,
  2390. &rifRoute,
  2391. dwIfMask,
  2392. 0, // RTM_ROUTE_INFO::Flags
  2393. TRUE,
  2394. FALSE,
  2395. FALSE,
  2396. NULL);
  2397. if(dwResult isnot NO_ERROR)
  2398. {
  2399. Trace1(ERR,
  2400. "InitLoopIf: Couldnt add 127.0.0.1 route associated with %x",
  2401. dwIfAddress);
  2402. }
  2403. return;
  2404. }
  2405. VOID
  2406. UpdateStackRoutesToRestoreList(
  2407. IN PMIB_IPFORWARDROW pmibRoute,
  2408. IN DWORD dwFlags
  2409. )
  2410. /*++
  2411. Routine Description:
  2412. This routine adds/deletes PROTO_IP_NETMGMT routes to/from the global
  2413. list g_leStackRoutesToRestore. This list is used by IP router
  2414. manager to restore routes these routes to the TCP/IP stack when it
  2415. is shutting down
  2416. Parameters
  2417. pirf - Route to be added or deleted
  2418. dwFlags - Specifies whether the operation is add or delete
  2419. Return Value
  2420. None
  2421. Context:
  2422. Invoked from
  2423. HandleRouteChangeNotification
  2424. [Set/Delete]IpForwardRow
  2425. --*/
  2426. {
  2427. BOOL bFound;
  2428. PROUTE_LIST_ENTRY prl, prlNew;
  2429. TraceEnter("UpdateStackRoutes");
  2430. TraceRoute5(
  2431. ROUTE,
  2432. "UpdateStackRoutes : Route "
  2433. "%d.%d.%d.%d/%d.%d.%d.%d via i/f 0x%x "
  2434. "nexthop %d.%d.%d.%d is being 0x%x "
  2435. "user mode",
  2436. PRINT_IPADDR(pmibRoute->dwForwardDest),
  2437. PRINT_IPADDR(pmibRoute->dwForwardMask),
  2438. pmibRoute->dwForwardIfIndex,
  2439. PRINT_IPADDR(pmibRoute->dwForwardNextHop),
  2440. dwFlags
  2441. );
  2442. ENTER_WRITER(STACK_ROUTE_LIST);
  2443. //
  2444. // Locate route in list
  2445. //
  2446. bFound = LookupStackRoutesToRestoreList(
  2447. pmibRoute,
  2448. &prl
  2449. );
  2450. do
  2451. {
  2452. //
  2453. // Is this a route update or add
  2454. //
  2455. if ((dwFlags is 0) or (dwFlags & IRNO_FLAG_ADD))
  2456. {
  2457. //
  2458. // if route is not found, add it
  2459. //
  2460. if (!bFound)
  2461. {
  2462. if (dwFlags is 0)
  2463. {
  2464. //
  2465. // Strange that route is not around in
  2466. // user mode though it is present in the
  2467. // stack (update case).
  2468. //
  2469. // Print a trace to note this and add it
  2470. // anyway
  2471. //
  2472. Trace4(
  2473. ERR,
  2474. "UpdateStackRoutes : Route "
  2475. "%d.%d.%d.%d/%d.%d.%d.%d via i/f 0x%x "
  2476. "nexthop %d.%d.%d.%d not found in "
  2477. "user mode",
  2478. PRINT_IPADDR(pmibRoute->dwForwardDest),
  2479. PRINT_IPADDR(pmibRoute->dwForwardMask),
  2480. pmibRoute->dwForwardIfIndex,
  2481. PRINT_IPADDR(pmibRoute->dwForwardNextHop),
  2482. );
  2483. }
  2484. //
  2485. // Allocate and store route in a linked list
  2486. //
  2487. prlNew = HeapAlloc(
  2488. IPRouterHeap, HEAP_ZERO_MEMORY,
  2489. sizeof(ROUTE_LIST_ENTRY)
  2490. );
  2491. if (prlNew is NULL)
  2492. {
  2493. Trace2(
  2494. ERR,
  2495. "UpdateStackRoutes : error %d allocating %d"
  2496. " bytes for stack route entry",
  2497. ERROR_NOT_ENOUGH_MEMORY,
  2498. sizeof(ROUTE_LIST_ENTRY)
  2499. );
  2500. break;
  2501. }
  2502. InitializeListHead( &prlNew->leRouteList );
  2503. prlNew->mibRoute = *pmibRoute;
  2504. InsertTailList(
  2505. (prl is NULL) ?
  2506. &g_leStackRoutesToRestore :
  2507. &prl->leRouteList,
  2508. &prlNew->leRouteList
  2509. );
  2510. break;
  2511. }
  2512. //
  2513. // route is found, update it
  2514. //
  2515. prl->mibRoute = *pmibRoute;
  2516. break;
  2517. }
  2518. //
  2519. // Is this a route delete
  2520. //
  2521. if (dwFlags & IRNO_FLAG_DELETE)
  2522. {
  2523. if (bFound)
  2524. {
  2525. RemoveEntryList( &prl->leRouteList );
  2526. HeapFree(IPRouterHeap, 0, prl);
  2527. }
  2528. }
  2529. } while( FALSE );
  2530. EXIT_LOCK(STACK_ROUTE_LIST);
  2531. TraceLeave("UpdateStackRoutes");
  2532. }
  2533. BOOL
  2534. LookupStackRoutesToRestoreList(
  2535. IN PMIB_IPFORWARDROW pmibRoute,
  2536. OUT PROUTE_LIST_ENTRY *pRoute
  2537. )
  2538. /*++
  2539. Routine Description:
  2540. This routine searches g_leStackRoutesToRestore to determine if the
  2541. route specified by pmibRoute is present. If it is it returns TRUE
  2542. and a pointer to the specified route in pRoute. If is not present
  2543. FALSE is returned along with a pointer to the next route in list.
  2544. If there are no routes, pRoute is NULL
  2545. Parameters
  2546. pmibRoute - Route to locate in g_leStackRoutesToRestore
  2547. pRoute - Pointer to the route entry if present
  2548. - Pointer to the next route entry if not present
  2549. (save additional lookups in case of route entry
  2550. additions)
  2551. - NULL if list is empty
  2552. Return Value:
  2553. TRUE - if route found
  2554. FALSE - otherwise
  2555. Context:
  2556. Should be called with the lock for g_leStackRoutesToRestore
  2557. --*/
  2558. {
  2559. INT iCmp;
  2560. BOOL bFound = FALSE;
  2561. PLIST_ENTRY ple;
  2562. PROUTE_LIST_ENTRY prl;
  2563. *pRoute = NULL;
  2564. if (IsListEmpty(&g_leStackRoutesToRestore))
  2565. {
  2566. return bFound;
  2567. }
  2568. for (ple = g_leStackRoutesToRestore.Flink;
  2569. ple != &g_leStackRoutesToRestore;
  2570. ple = ple->Flink)
  2571. {
  2572. prl = CONTAINING_RECORD(
  2573. ple, ROUTE_LIST_ENTRY, leRouteList
  2574. );
  2575. if (INET_CMP(
  2576. prl->mibRoute.dwForwardDest &
  2577. prl->mibRoute.dwForwardMask,
  2578. pmibRoute->dwForwardDest &
  2579. pmibRoute->dwForwardMask,
  2580. iCmp
  2581. ) < 0 )
  2582. {
  2583. continue;
  2584. }
  2585. else if (iCmp > 0)
  2586. {
  2587. //
  2588. // we have gone past the possible location
  2589. // of the specified route
  2590. //
  2591. break;
  2592. }
  2593. //
  2594. // found a matching dest, check if the i/f is
  2595. // the same.
  2596. //
  2597. if ((prl->mibRoute.dwForwardIfIndex is
  2598. pmibRoute->dwForwardIfIndex ) and
  2599. (prl->mibRoute.dwForwardNextHop is
  2600. pmibRoute->dwForwardNextHop))
  2601. {
  2602. bFound = TRUE;
  2603. break;
  2604. }
  2605. }
  2606. if (ple == &g_leStackRoutesToRestore)
  2607. {
  2608. *pRoute = (PROUTE_LIST_ENTRY)NULL;
  2609. }
  2610. else
  2611. {
  2612. *pRoute = prl;
  2613. }
  2614. return bFound;
  2615. }