Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3485 lines
96 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. if((pIcb->dwOperationalState is DISCONNECTED) and
  854. (pRoutes[i].dwRtInfoProto is PROTO_IP_NT_STATIC_NON_DOD))
  855. {
  856. continue;
  857. }
  858. //
  859. // If this will be a point to point interface,
  860. // ignore the next hop
  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. TraceRoute4(ROUTE,
  1827. "route to %d.%d.%d.%d/%d.%d.%d.%d, If Index %d, proto %d",
  1828. PRINT_IPADDR(pRouteTable->table[i].dwForwardDest),
  1829. PRINT_IPADDR(pRouteTable->table[i].dwForwardMask),
  1830. pRouteTable->table[i].dwForwardIfIndex,
  1831. pRouteTable->table[i].dwForwardProto);
  1832. if(pRouteTable->table[i].dwForwardIfIndex isnot pIcb->dwIfIndex)
  1833. {
  1834. //
  1835. // Not going out over this interface
  1836. //
  1837. continue;
  1838. }
  1839. #if 1
  1840. //
  1841. // Pick up only PROTO_IP_LOCAL and PROTO_IP_NETMGMT routes
  1842. // from the IP stack
  1843. //
  1844. if((pRouteTable->table[i].dwForwardProto isnot PROTO_IP_LOCAL) and
  1845. (pRouteTable->table[i].dwForwardProto isnot PROTO_IP_NETMGMT))
  1846. {
  1847. continue;
  1848. }
  1849. #else
  1850. if((pRouteTable->table[i].dwForwardProto isnot PROTO_IP_NT_STATIC_NON_DOD) and
  1851. (pRouteTable->table[i].dwForwardDest isnot 0))
  1852. {
  1853. //
  1854. // Only pick up default gateways and persistent routes
  1855. //
  1856. continue;
  1857. }
  1858. #endif
  1859. dwMask = GetBestNextHopMaskGivenICB(pIcb,
  1860. pRouteTable->table[i].dwForwardDest);
  1861. //
  1862. // Routes learned from the stack should be added back to the stack if
  1863. // required. This can happen as follows:
  1864. //
  1865. // 1. Route R1 from stack is currently best route for destination D1.
  1866. // 2. Subsequently it is superseeded by route R2 as the best route for
  1867. // destination D1.
  1868. // R2 is added to the stack, deleting R1 as a side effect.
  1869. // 3. Eventually R2 is deleted and R1 is again the best route to D1
  1870. // 4. R1 now needs to be added back to the stack and can only be done
  1871. // if its stack bit is set.
  1872. //
  1873. bStack = TRUE;
  1874. //if((pRouteTable->table[i].dwForwardProto is PROTO_IP_NETMGMT) &&
  1875. // (pRouteTable->table[i].dwForwardMask is HOST_ROUTE_MASK))
  1876. //{
  1877. // bStack = FALSE;
  1878. //}
  1879. if(pRouteTable->table[i].dwForwardProto is PROTO_IP_LOCAL)
  1880. {
  1881. //
  1882. // PROTO_IP_LOCAL routes as a rule need not be added back
  1883. // as they are entirely managed by the stack.
  1884. //
  1885. // The one exception as routes to the local subnet.
  1886. // These need to added back to the stack so that any
  1887. // routes to the local subnet learned over other interfaces
  1888. // are deleted as a side effect.
  1889. //
  1890. // This is required as follows:
  1891. // 1. Interface I1 connected to network N1 is disabled.
  1892. // 2. Route R1 to network N1 is learnt over interface
  1893. // I2 connected to network N2 from a neighboring
  1894. // router running RIP.
  1895. // 3. So the best route to N1 is the RIP route R1.
  1896. // 4. Interface I1 is now enabled.
  1897. // 5. PROTO_IP_LOCAL route R2 to N1 is added by the stack.
  1898. // But the stack does not delete R1 automatically.
  1899. // 6. In RTMv2 in user-mode R2 is added as the best route.
  1900. // 7. If R2 does not have its stack bit set, it is not
  1901. // added back to the stack, allowing both R2 and R1 to
  1902. // remain in the stack.
  1903. // 8. Route R1 is deleted by RIP. Since it is not the
  1904. // best route in RTMv2 no changes are propagated to the
  1905. // stack even though R1 is present in the stack.
  1906. //
  1907. //
  1908. // As per above disable stack bit for PROTO_IP_LOCAL routes
  1909. // except route to the local subnet.
  1910. //
  1911. if(
  1912. //
  1913. // Do not add the loopback route back to the stack.
  1914. // PROTO_IP_LOCAL host route check catches the loopback route
  1915. //
  1916. (pRouteTable->table[i].dwForwardMask is HOST_ROUTE_MASK) or
  1917. //
  1918. // Do not add the multicast and all 1's broadcast route
  1919. //
  1920. ((pRouteTable->table[i].dwForwardDest &
  1921. ((DWORD) 0x000000FF)) >= ((DWORD) 0x000000E0)) or
  1922. //
  1923. // Do not add subnet broadcast route
  1924. //
  1925. (pRouteTable->table[i].dwForwardDest ==
  1926. (pRouteTable->table[i].dwForwardDest |
  1927. ~pRouteTable->table[i].dwForwardMask)))
  1928. {
  1929. bStack = FALSE;
  1930. }
  1931. //
  1932. // This should leave only the subnet route with its stack bit set
  1933. //
  1934. }
  1935. dwErr = AddSingleRoute(pIcb->dwIfIndex,
  1936. ConvertMibRouteToRouteInfo(&(pRouteTable->table[i])),
  1937. dwMask,
  1938. 0, // RTM_ROUTE_INFO::Flags
  1939. TRUE, // Valid route
  1940. bStack, // Do not add back to stack
  1941. FALSE, // Only called for non P2P i/fs
  1942. NULL);
  1943. }
  1944. TraceLeave("AddAllStackRoutes");
  1945. return;
  1946. }
  1947. VOID
  1948. UpdateDefaultRoutes(
  1949. VOID
  1950. )
  1951. {
  1952. DWORD dwErr, dwMask, i, j;
  1953. BOOL bFound;
  1954. PMIB_IPFORWARDTABLE pRouteTable;
  1955. PINTERFACE_ROUTE_INFO pRtInfo;
  1956. TraceEnter("UpdateDefaultRoutes");
  1957. //
  1958. // Get the routes in an ordered table
  1959. //
  1960. dwErr = AllocateAndGetIpForwardTableFromStack(&pRouteTable,
  1961. TRUE,
  1962. IPRouterHeap,
  1963. 0);
  1964. if(dwErr isnot NO_ERROR)
  1965. {
  1966. Trace1(ERR,
  1967. "UpdateDefaultRoutes: Couldnt get routes. Error %d",
  1968. dwErr);
  1969. return;
  1970. }
  1971. //
  1972. // Now add the dgs not already present
  1973. //
  1974. for(i = 0; i < pRouteTable->dwNumEntries; i++)
  1975. {
  1976. PICB pIcb;
  1977. TraceRoute2(
  1978. ROUTE, "%d.%d.%d.%d/%d.%d.%d.%d",
  1979. PRINT_IPADDR( pRouteTable-> table[i].dwForwardDest ),
  1980. PRINT_IPADDR( pRouteTable-> table[i].dwForwardMask )
  1981. );
  1982. //
  1983. // Once we get past the default routes, we are done
  1984. //
  1985. if(pRouteTable->table[i].dwForwardDest isnot 0)
  1986. {
  1987. #if TRACE_DBG
  1988. continue;
  1989. #else
  1990. break;
  1991. #endif
  1992. }
  1993. if(pRouteTable->table[i].dwForwardIfIndex is INVALID_IF_INDEX)
  1994. {
  1995. continue;
  1996. }
  1997. if(pRouteTable->table[i].dwForwardProto isnot PROTO_IP_NETMGMT)
  1998. {
  1999. continue;
  2000. }
  2001. pIcb = InterfaceLookupByIfIndex(pRouteTable->table[i].dwForwardIfIndex);
  2002. if(pIcb is NULL)
  2003. {
  2004. Trace1(ERR,
  2005. "UpdateDefaultRoutes: Couldnt get icb for %x",
  2006. pRouteTable->table[i].dwForwardIfIndex);
  2007. continue;
  2008. }
  2009. //
  2010. // Dont need to do this for p2p interfaces
  2011. //
  2012. if(IsIfP2P(pIcb->ritType))
  2013. {
  2014. continue;
  2015. }
  2016. dwMask = GetBestNextHopMaskGivenICB(pIcb,
  2017. pRouteTable->table[i].dwForwardDest);
  2018. Trace1(ROUTE,
  2019. "UpdateDefaultRoutes: Adding default route over %S",
  2020. pIcb->pwszName);
  2021. dwErr = AddSingleRoute(pIcb->dwIfIndex,
  2022. ConvertMibRouteToRouteInfo(&(pRouteTable->table[i])),
  2023. dwMask,
  2024. 0, // RTM_ROUTE_INFO::Flags
  2025. TRUE, // Valid route
  2026. TRUE, // Add the route to stack
  2027. FALSE, // Only called for non P2P i/fs
  2028. NULL);
  2029. if(dwErr isnot NO_ERROR)
  2030. {
  2031. Trace3(ERR,
  2032. "UpdateDefaultRoutes: Error %d adding dg to %d.%d.%d.%d over %x",
  2033. dwErr,
  2034. PRINT_IPADDR(pRouteTable->table[i].dwForwardNextHop),
  2035. pRouteTable->table[i].dwForwardIfIndex);
  2036. }
  2037. #if 0
  2038. else
  2039. {
  2040. if(g_ulGatewayCount < g_ulGatewayMaxCount)
  2041. {
  2042. g_pGateways[g_ulGatewayCount].dwAddress =
  2043. pRouteTable->table[i].dwForwardNextHop;
  2044. g_pGateways[g_ulGatewayCount].dwMetric =
  2045. pRouteTable->table[i].dwForwardMetric1;
  2046. g_pGateways[g_ulGatewayCount].dwIfIndex =
  2047. pRouteTable->table[i].dwForwardIfIndex;
  2048. g_ulGatewayCount++;
  2049. }
  2050. else
  2051. {
  2052. PGATEWAY_INFO pNewGw;
  2053. IpRtAssert(g_ulGatewayCount == g_ulGatewayMaxCount);
  2054. pNewGw = HeapAlloc(IPRouterHeap,
  2055. HEAP_ZERO_MEMORY,
  2056. (g_ulGatewayMaxCount + 5) * sizeof(GATEWAY_INFO));
  2057. if(pNewGw isnot NULL)
  2058. {
  2059. g_ulGatewayMaxCount = g_ulGatewayMaxCount + 5;
  2060. for(j = 0; j < g_ulGatewayCount; j++)
  2061. {
  2062. pNewGw[j] = g_pGateways[j];
  2063. }
  2064. if(g_pGateways isnot NULL)
  2065. {
  2066. HeapFree(IPRouterHeap,
  2067. 0,
  2068. g_pGateways);
  2069. }
  2070. g_pGateways = pNewGw;
  2071. g_pGateways[g_ulGatewayCount].dwAddress =
  2072. pRouteTable->table[i].dwForwardNextHop;
  2073. g_pGateways[g_ulGatewayCount].dwMetric =
  2074. pRouteTable->table[i].dwForwardMetric1;
  2075. g_pGateways[g_ulGatewayCount].dwIfIndex =
  2076. pRouteTable->table[i].dwForwardIfIndex;
  2077. g_ulGatewayCount++;
  2078. }
  2079. }
  2080. }
  2081. #endif
  2082. }
  2083. HeapFree(IPRouterHeap,
  2084. 0,
  2085. pRouteTable);
  2086. TraceLeave("UpdateDefaultRoutes");
  2087. return;
  2088. }
  2089. NTSTATUS
  2090. PostIoctlForRouteChangeNotification(
  2091. DWORD ulIndex
  2092. )
  2093. /*++
  2094. Routine Description:
  2095. This routine posts an IOCTL with the TCP/IP driver for route change
  2096. notifications caused by addition of routes to the stack by entities
  2097. other than Router Manager
  2098. Arguments:
  2099. ulIndex - Index into array of notifications indicating which one
  2100. needs to be posted
  2101. Return Value
  2102. STATUS_SUCCESS - Success
  2103. NTSTATUS code - Otherwise
  2104. Environment:
  2105. --*/
  2106. {
  2107. NTSTATUS status;
  2108. status = NtDeviceIoControlFile(
  2109. g_hIpRouteChangeDevice,
  2110. g_hRouteChangeEvents[ulIndex],
  2111. NULL,
  2112. NULL,
  2113. &g_rgIpRouteNotifyOutput[ulIndex].ioStatus,
  2114. IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX,
  2115. &g_IpNotifyData,
  2116. sizeof(IPNotifyData),
  2117. &g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput,
  2118. sizeof(IPRouteNotifyOutput)
  2119. );
  2120. if ((status isnot STATUS_SUCCESS) and
  2121. (status isnot STATUS_PENDING))
  2122. {
  2123. Trace2(
  2124. ERR,
  2125. "Error 0x%x posting route change notification[%d]",
  2126. status, ulIndex
  2127. );
  2128. }
  2129. return status;
  2130. }
  2131. DWORD
  2132. HandleRouteChangeNotification(
  2133. ULONG ulIndex
  2134. )
  2135. /*++
  2136. --*/
  2137. {
  2138. DWORD dwResult = NO_ERROR, dwFlags, dwClassMask;
  2139. BOOL bValid, bStack = FALSE;
  2140. WORD wRouteFlags = 0;
  2141. INTERFACE_ROUTE_INFO RtInfo;
  2142. PICB pIcb;
  2143. TraceEnter("HandleRouteChangeNotification");
  2144. TraceRoute2(
  2145. ROUTE, "Change for route to %d.%d.%d.%d/%d.%d.%d.%d",
  2146. PRINT_IPADDR(g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_dest),
  2147. PRINT_IPADDR(g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_mask)
  2148. );
  2149. TraceRoute3(
  2150. ROUTE, "Proto : %d, via i/f 0x%x, nexthop %d.%d.%d.%d",
  2151. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_proto,
  2152. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_ifindex,
  2153. PRINT_IPADDR(g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_nexthop)
  2154. );
  2155. TraceRoute2(
  2156. ROUTE, "Metric : %d, Change : 0x%x",
  2157. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_metric,
  2158. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_flags
  2159. );
  2160. //
  2161. // Update RTM route table as per route change indication
  2162. //
  2163. ENTER_READER(ICB_LIST);
  2164. do
  2165. {
  2166. pIcb = InterfaceLookupByIfIndex(
  2167. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_ifindex
  2168. );
  2169. if (pIcb == NULL)
  2170. {
  2171. //
  2172. // if there is no interface with the specified index in
  2173. // router manager, skip this route
  2174. //
  2175. Trace3(
  2176. ERR,
  2177. "Failed to add route to %d.%d.%d.%d/%d.%d.%d.%d."
  2178. "Interface index %d not present with router manager",
  2179. PRINT_IPADDR(g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_dest),
  2180. PRINT_IPADDR(g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_mask),
  2181. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_ifindex
  2182. );
  2183. break;
  2184. }
  2185. //
  2186. // if route had been added to stack, add it to RTM
  2187. //
  2188. dwFlags =
  2189. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_flags;
  2190. ConvertRouteNotifyOutputToRouteInfo(
  2191. &g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput,
  2192. &RtInfo
  2193. );
  2194. if ((dwFlags is 0) or (dwFlags & IRNO_FLAG_ADD))
  2195. {
  2196. bValid = TRUE;
  2197. if (RtInfo.dwRtInfoProto == PROTO_IP_LOCAL)
  2198. {
  2199. //
  2200. // Set appropriate RTM flags for local routes
  2201. //
  2202. if (RtInfo.dwRtInfoNextHop == IP_LOOPBACK_ADDRESS)
  2203. {
  2204. //
  2205. // Route over loopback. Set MYSELF flag
  2206. //
  2207. wRouteFlags = RTM_ROUTE_FLAGS_MYSELF;
  2208. }
  2209. else if ((RtInfo.dwRtInfoMask != HOST_ROUTE_MASK ) &&
  2210. ((RtInfo.dwRtInfoDest & RtInfo.dwRtInfoMask) <
  2211. ((DWORD) 0x000000E0)))
  2212. {
  2213. //
  2214. // RTM_ROUTE_FLAGS_LOCAL is set only for subnet
  2215. // routes. Not sure why this is so. I am only
  2216. // preserving the semantics from AddAutomaticRoutes
  2217. // Either way the consequences are not drastic since
  2218. // this does not affect the IP forwarding table in
  2219. // the stack.
  2220. // - VRaman
  2221. //
  2222. //
  2223. // We arrive at the fact that this is a subnet route
  2224. // in a roundabout fashion by eliminating
  2225. // PROTO_IP_LOCAL routes that are host routes and
  2226. // by eliminating any broadcast routes
  2227. //
  2228. // Since the host route check eliminates all routes
  2229. // with an all 1's mask, subnet/net broadcast routes
  2230. // are also eliminated.
  2231. //
  2232. wRouteFlags = RTM_ROUTE_FLAGS_LOCAL;
  2233. }
  2234. //
  2235. // mark mcast/bcast route as invalid so the protocols
  2236. // do not advertize them
  2237. //
  2238. dwClassMask = GetClassMask(RtInfo.dwRtInfoDest);
  2239. if ((RtInfo.dwRtInfoDest & (DWORD) 0x000000FF) >=
  2240. ((DWORD) 0x000000E0) ||
  2241. (RtInfo.dwRtInfoDest ==
  2242. (RtInfo.dwRtInfoDest | ~dwClassMask)))
  2243. {
  2244. bValid = FALSE;
  2245. }
  2246. else
  2247. {
  2248. //
  2249. // For PROTO_IP_LOCAL we do not add them back to
  2250. // the stack since these are managed by the stack
  2251. // We add them to RTM only to keep the user mode
  2252. // route table synchronized with the stack
  2253. //
  2254. // On second thoughts, we do need to add them
  2255. // back to the stack. More accurately, we need to
  2256. // try and add them back to the stack. This
  2257. // operation should fail, but as a side effect of
  2258. // this existing non PROTO_IP_LOCAL in the stack
  2259. // will be deleted.
  2260. // This is required in case of local subnet
  2261. // routes. It is possible that before an
  2262. // interface is enabled with IP, a route to the
  2263. // connected subnet may have been learnt over
  2264. // another interface via a routing protocol and
  2265. // added to the stack. When an interface is
  2266. // enabled all previously added routes to the
  2267. // local subnet should be deleted if the
  2268. // PROTO_IP_LOCAL route is the best route (which
  2269. // it should be unless you have a really wierd set
  2270. // of protocol preferences).
  2271. // Otherwise we run the risk of having non-best
  2272. // routes in the IP stack that are never deleted
  2273. // when the user mode route corresponding to it is
  2274. // deleted since you do not get a route change
  2275. // notification for non-best routes. The result is
  2276. // that you end up with state routes in the stack
  2277. //
  2278. if (RtInfo.dwRtInfoMask != HOST_ROUTE_MASK)
  2279. {
  2280. bStack = TRUE;
  2281. }
  2282. }
  2283. }
  2284. //
  2285. // Routes learn't from the stack are normally not
  2286. // added back to the stack. Hence the bStack is
  2287. // initialized to FALSE.
  2288. //
  2289. // PROTO_IP_NETMGT are not managed by the stack. They
  2290. // can be added/deleted/updated by user mode processes.
  2291. // As consequence a NETMGT route learned from the stack
  2292. // may be superseded by a route with a different protocol
  2293. // ID e.g. static. When the superseding route is deleted
  2294. // the NETMGMT routes need to be restored to the stack.
  2295. // Hence for NETMGMT routes we set bStack = true.
  2296. //
  2297. // An exception the processing of NETMGMT routes are HOST routes
  2298. // It is assumed by host routes added directly to the
  2299. // stack are managed by the process adding/deleting them
  2300. // e.g.RASIPCP
  2301. // They are added to RTM for sync. with the stack route table
  2302. // only. So for these we set bStack = FALSE
  2303. //
  2304. //
  2305. if ((RtInfo.dwRtInfoProto is PROTO_IP_NETMGMT) &&
  2306. (RtInfo.dwRtInfoMask isnot HOST_ROUTE_MASK))
  2307. {
  2308. bStack = TRUE;
  2309. }
  2310. TraceRoute5(
  2311. ROUTE, "NHOP mask %d.%d.%d.%d, Flag 0x%x, Valid %d, "
  2312. "Stack %d, P2P %d",
  2313. PRINT_IPADDR(GetBestNextHopMaskGivenICB(
  2314. pIcb, RtInfo.dwRtInfoNextHop)),
  2315. wRouteFlags,
  2316. bValid,
  2317. bStack,
  2318. IsIfP2P(pIcb->ritType)
  2319. );
  2320. dwResult = AddSingleRoute(
  2321. RtInfo.dwRtInfoIfIndex,
  2322. &RtInfo,
  2323. GetBestNextHopMaskGivenICB(
  2324. pIcb, RtInfo.dwRtInfoNextHop
  2325. ),
  2326. wRouteFlags,
  2327. bValid,
  2328. bStack,
  2329. IsIfP2P(pIcb->ritType),
  2330. NULL
  2331. );
  2332. if (dwResult != NO_ERROR)
  2333. {
  2334. Trace2(
  2335. ERR, "HandleRouteChangeNotification: Failed to add "
  2336. "route %d.%d.%d.%d, error %d",
  2337. PRINT_IPADDR(RtInfo.dwRtInfoDest),
  2338. dwResult
  2339. );
  2340. break;
  2341. }
  2342. }
  2343. else if (dwFlags & IRNO_FLAG_DELETE)
  2344. {
  2345. dwResult = DeleteSingleRoute(
  2346. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_ifindex,
  2347. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_dest,
  2348. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_mask,
  2349. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_nexthop,
  2350. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_proto,
  2351. IsIfP2P(pIcb->ritType)
  2352. );
  2353. if (dwResult != NO_ERROR)
  2354. {
  2355. Trace2(
  2356. ERR, "HandleRouteChangeNotification: Failed to"
  2357. "delete route %d.%d.%d.%d, error %d",
  2358. PRINT_IPADDR(
  2359. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_dest),
  2360. dwResult
  2361. );
  2362. break;
  2363. }
  2364. }
  2365. else
  2366. {
  2367. Trace1(
  2368. ERR, "HandleRouteChangeNotification: Invalid flags "
  2369. "0x%x",
  2370. g_rgIpRouteNotifyOutput[ulIndex].ipNotifyOutput.irno_flags
  2371. );
  2372. break;
  2373. }
  2374. if (RtInfo.dwRtInfoProto is PROTO_IP_NETMGMT)
  2375. {
  2376. UpdateStackRoutesToRestoreList(
  2377. ConvertRouteInfoToMibRoute( &RtInfo ),
  2378. dwFlags
  2379. );
  2380. }
  2381. } while (FALSE);
  2382. EXIT_LOCK(ICB_LIST);
  2383. PostIoctlForRouteChangeNotification(ulIndex);
  2384. TraceLeave("HandleRouteChangeNotification");
  2385. return dwResult;
  2386. }
  2387. VOID
  2388. AddLoopbackRoute(
  2389. DWORD dwIfAddress,
  2390. DWORD dwIfMask
  2391. )
  2392. {
  2393. DWORD dwResult;
  2394. INTERFACE_ROUTE_INFO rifRoute;
  2395. MIB_IPFORWARDROW mibRoute;
  2396. if(g_pLoopbackInterfaceCb is NULL)
  2397. {
  2398. Trace0(ERR, "AddLoopbackRoute: No loopback interface");
  2399. return;
  2400. }
  2401. rifRoute.dwRtInfoMask = HOST_ROUTE_MASK;
  2402. rifRoute.dwRtInfoNextHop = IP_LOOPBACK_ADDRESS;
  2403. rifRoute.dwRtInfoDest = dwIfAddress;
  2404. rifRoute.dwRtInfoIfIndex = g_pLoopbackInterfaceCb->dwIfIndex;
  2405. rifRoute.dwRtInfoMetric2 = 0;
  2406. rifRoute.dwRtInfoMetric3 = 0;
  2407. rifRoute.dwRtInfoPreference = ComputeRouteMetric(MIB_IPPROTO_LOCAL);
  2408. rifRoute.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST |
  2409. RTM_VIEW_MASK_MCAST; // XXX config
  2410. rifRoute.dwRtInfoType = MIB_IPROUTE_TYPE_DIRECT;
  2411. rifRoute.dwRtInfoProto = MIB_IPPROTO_LOCAL;
  2412. rifRoute.dwRtInfoAge = 0;
  2413. rifRoute.dwRtInfoNextHopAS = 0;
  2414. rifRoute.dwRtInfoPolicy = 0;
  2415. //
  2416. // Query IP stack to verify for loopback route
  2417. // corresponding to this binding
  2418. //
  2419. dwResult = GetBestRoute(
  2420. dwIfAddress,
  2421. 0,
  2422. &mibRoute
  2423. );
  2424. if(dwResult isnot NO_ERROR)
  2425. {
  2426. Trace2(
  2427. ERR,
  2428. "AddLoopbackRoute: Stack query for loopback route"
  2429. " associated with %d.%d.%d.%d failed, error %d",
  2430. PRINT_IPADDR(dwIfAddress),
  2431. dwResult
  2432. );
  2433. return;
  2434. }
  2435. if (mibRoute.dwForwardIfIndex !=
  2436. g_pLoopbackInterfaceCb->dwIfIndex)
  2437. {
  2438. //
  2439. // There appears to be no loopback address
  2440. // very strange
  2441. //
  2442. Trace1(
  2443. ERR,
  2444. "AddLoopbackRoute: No loopback route for %d.%d.%d.%d"
  2445. "in stack",
  2446. PRINT_IPADDR(dwIfAddress)
  2447. );
  2448. return;
  2449. }
  2450. //
  2451. // Use metric returned from stack.
  2452. //
  2453. rifRoute.dwRtInfoMetric1 = mibRoute.dwForwardMetric1;
  2454. dwResult = AddSingleRoute(g_pLoopbackInterfaceCb->dwIfIndex,
  2455. &rifRoute,
  2456. dwIfMask,
  2457. 0, // RTM_ROUTE_INFO::Flags
  2458. TRUE,
  2459. FALSE,
  2460. FALSE,
  2461. NULL);
  2462. if(dwResult isnot NO_ERROR)
  2463. {
  2464. Trace1(ERR,
  2465. "AddLoopbackRoute: Couldnt add 127.0.0.1 route associated with %x",
  2466. dwIfAddress);
  2467. }
  2468. return;
  2469. }
  2470. VOID
  2471. UpdateStackRoutesToRestoreList(
  2472. IN PMIB_IPFORWARDROW pmibRoute,
  2473. IN DWORD dwFlags
  2474. )
  2475. /*++
  2476. Routine Description:
  2477. This routine adds/deletes PROTO_IP_NETMGMT routes to/from the global
  2478. list g_leStackRoutesToRestore. This list is used by IP router
  2479. manager to restore routes these routes to the TCP/IP stack when it
  2480. is shutting down
  2481. Parameters
  2482. pirf - Route to be added or deleted
  2483. dwFlags - Specifies whether the operation is add or delete
  2484. Return Value
  2485. None
  2486. Context:
  2487. Invoked from
  2488. HandleRouteChangeNotification
  2489. [Set/Delete]IpForwardRow
  2490. --*/
  2491. {
  2492. BOOL bFound;
  2493. PROUTE_LIST_ENTRY prl, prlNew;
  2494. TraceEnter("UpdateStackRoutes");
  2495. TraceRoute5(
  2496. ROUTE,
  2497. "UpdateStackRoutes : Route "
  2498. "%d.%d.%d.%d/%d.%d.%d.%d via i/f 0x%x "
  2499. "nexthop %d.%d.%d.%d is being 0x%x "
  2500. "user mode",
  2501. PRINT_IPADDR(pmibRoute->dwForwardDest),
  2502. PRINT_IPADDR(pmibRoute->dwForwardMask),
  2503. pmibRoute->dwForwardIfIndex,
  2504. PRINT_IPADDR(pmibRoute->dwForwardNextHop),
  2505. dwFlags
  2506. );
  2507. ENTER_WRITER(STACK_ROUTE_LIST);
  2508. //
  2509. // Locate route in list
  2510. //
  2511. bFound = LookupStackRoutesToRestoreList(
  2512. pmibRoute,
  2513. &prl
  2514. );
  2515. do
  2516. {
  2517. //
  2518. // Is this a route update or add
  2519. //
  2520. if ((dwFlags is 0) or (dwFlags & IRNO_FLAG_ADD))
  2521. {
  2522. //
  2523. // if route is not found, add it
  2524. //
  2525. if (!bFound)
  2526. {
  2527. if (dwFlags is 0)
  2528. {
  2529. //
  2530. // Strange that route is not around in
  2531. // user mode though it is present in the
  2532. // stack (update case).
  2533. //
  2534. // Print a trace to note this and add it
  2535. // anyway
  2536. //
  2537. Trace4(
  2538. ERR,
  2539. "UpdateStackRoutes : Route "
  2540. "%d.%d.%d.%d/%d.%d.%d.%d via i/f 0x%x "
  2541. "nexthop %d.%d.%d.%d not found in "
  2542. "user mode",
  2543. PRINT_IPADDR(pmibRoute->dwForwardDest),
  2544. PRINT_IPADDR(pmibRoute->dwForwardMask),
  2545. pmibRoute->dwForwardIfIndex,
  2546. PRINT_IPADDR(pmibRoute->dwForwardNextHop)
  2547. );
  2548. }
  2549. //
  2550. // Allocate and store route in a linked list
  2551. //
  2552. prlNew = HeapAlloc(
  2553. IPRouterHeap, HEAP_ZERO_MEMORY,
  2554. sizeof(ROUTE_LIST_ENTRY)
  2555. );
  2556. if (prlNew is NULL)
  2557. {
  2558. Trace2(
  2559. ERR,
  2560. "UpdateStackRoutes : error %d allocating %d"
  2561. " bytes for stack route entry",
  2562. ERROR_NOT_ENOUGH_MEMORY,
  2563. sizeof(ROUTE_LIST_ENTRY)
  2564. );
  2565. break;
  2566. }
  2567. InitializeListHead( &prlNew->leRouteList );
  2568. prlNew->mibRoute = *pmibRoute;
  2569. InsertTailList(
  2570. (prl is NULL) ?
  2571. &g_leStackRoutesToRestore :
  2572. &prl->leRouteList,
  2573. &prlNew->leRouteList
  2574. );
  2575. break;
  2576. }
  2577. //
  2578. // route is found, update it
  2579. //
  2580. prl->mibRoute = *pmibRoute;
  2581. break;
  2582. }
  2583. //
  2584. // Is this a route delete
  2585. //
  2586. if (dwFlags & IRNO_FLAG_DELETE)
  2587. {
  2588. if (bFound)
  2589. {
  2590. RemoveEntryList( &prl->leRouteList );
  2591. HeapFree(IPRouterHeap, 0, prl);
  2592. }
  2593. }
  2594. } while( FALSE );
  2595. EXIT_LOCK(STACK_ROUTE_LIST);
  2596. TraceLeave("UpdateStackRoutes");
  2597. }
  2598. BOOL
  2599. LookupStackRoutesToRestoreList(
  2600. IN PMIB_IPFORWARDROW pmibRoute,
  2601. OUT PROUTE_LIST_ENTRY *pRoute
  2602. )
  2603. /*++
  2604. Routine Description:
  2605. This routine searches g_leStackRoutesToRestore to determine if the
  2606. route specified by pmibRoute is present. If it is it returns TRUE
  2607. and a pointer to the specified route in pRoute. If is not present
  2608. FALSE is returned along with a pointer to the next route in list.
  2609. If there are no routes, pRoute is NULL
  2610. Parameters
  2611. pmibRoute - Route to locate in g_leStackRoutesToRestore
  2612. pRoute - Pointer to the route entry if present
  2613. - Pointer to the next route entry if not present
  2614. (save additional lookups in case of route entry
  2615. additions)
  2616. - NULL if list is empty
  2617. Return Value:
  2618. TRUE - if route found
  2619. FALSE - otherwise
  2620. Context:
  2621. Should be called with the lock for g_leStackRoutesToRestore
  2622. --*/
  2623. {
  2624. INT iCmp;
  2625. BOOL bFound = FALSE;
  2626. PLIST_ENTRY ple;
  2627. PROUTE_LIST_ENTRY prl;
  2628. *pRoute = NULL;
  2629. if (IsListEmpty(&g_leStackRoutesToRestore))
  2630. {
  2631. return bFound;
  2632. }
  2633. for (ple = g_leStackRoutesToRestore.Flink;
  2634. ple != &g_leStackRoutesToRestore;
  2635. ple = ple->Flink)
  2636. {
  2637. prl = CONTAINING_RECORD(
  2638. ple, ROUTE_LIST_ENTRY, leRouteList
  2639. );
  2640. if (INET_CMP(
  2641. prl->mibRoute.dwForwardDest &
  2642. prl->mibRoute.dwForwardMask,
  2643. pmibRoute->dwForwardDest &
  2644. pmibRoute->dwForwardMask,
  2645. iCmp
  2646. ) < 0 )
  2647. {
  2648. continue;
  2649. }
  2650. else if (iCmp > 0)
  2651. {
  2652. //
  2653. // we have gone past the possible location
  2654. // of the specified route
  2655. //
  2656. break;
  2657. }
  2658. //
  2659. // found a matching dest, check if the i/f is
  2660. // the same.
  2661. //
  2662. if ((prl->mibRoute.dwForwardIfIndex is
  2663. pmibRoute->dwForwardIfIndex ) and
  2664. (prl->mibRoute.dwForwardNextHop is
  2665. pmibRoute->dwForwardNextHop))
  2666. {
  2667. bFound = TRUE;
  2668. break;
  2669. }
  2670. }
  2671. if (ple == &g_leStackRoutesToRestore)
  2672. {
  2673. *pRoute = (PROUTE_LIST_ENTRY)NULL;
  2674. }
  2675. else
  2676. {
  2677. *pRoute = prl;
  2678. }
  2679. return bFound;
  2680. }