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.

918 lines
26 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. routing\ip\rtrmgr\init.c
  5. Abstract:
  6. IP Router Manager code
  7. Revision History:
  8. Gurdeep Singh Pall 6/14/95 Created
  9. --*/
  10. #include "allinc.h"
  11. // ChangeRouteWithForwarder()
  12. //
  13. // Function: If addroute is TRUE this function adds an IP route. If addroute is FALSE
  14. // this function deletes the given route with the forwarder.
  15. //
  16. // Returns: Nothing
  17. //
  18. //
  19. DWORD
  20. ChangeRouteWithForwarder(
  21. PRTM_NET_ADDRESS pDestAddr,
  22. PRTM_ROUTE_INFO pRoute,
  23. BOOL bAddRoute,
  24. BOOL bDelOld
  25. )
  26. {
  27. IPMultihopRouteEntry *pMultiRouteEntry;
  28. IPRouteEntry *pRouteEntry;
  29. IPRouteNextHopEntry *pNexthopEntry;
  30. RTM_ENTITY_INFO entityInfo;
  31. RTM_NEXTHOP_INFO nhiInfo;
  32. PADAPTER_INFO pBinding;
  33. UINT numnexthops, i;
  34. ULONG numbytes;
  35. DWORD dwAddr, dwMask;
  36. UINT dwLen;
  37. ULONG ifindex, nexthop, type;
  38. BOOL bValidNHop;
  39. DWORD context;
  40. DWORD dwLocalNet, dwLocalMask;
  41. DWORD dwResult;
  42. TraceEnter("ChangeRouteWithForwarder");
  43. if(!g_bSetRoutesToStack)
  44. {
  45. Trace0(ROUTE,
  46. "ChangeRouteWithForwarder: SetRoutesToStack is FALSE");
  47. TraceLeave("ChangeRouteWithForwarder");
  48. return NO_ERROR;
  49. }
  50. if (bAddRoute)
  51. {
  52. //
  53. // Ensure that the stack bit is set
  54. //
  55. if (!pRoute || !IsRouteStack(pRoute))
  56. {
  57. if (!pRoute )
  58. {
  59. Trace0(ROUTE,
  60. "Error adding route, route == NULL"
  61. );
  62. }
  63. else
  64. {
  65. Trace1(ROUTE,
  66. "Error adding route, Stack bit == %d",
  67. IsRouteStack(pRoute)
  68. );
  69. }
  70. TraceLeave("ChangeRouteWithForwarder");
  71. return ERROR_INVALID_PARAMETER;
  72. }
  73. // We should have atleast one nexthop
  74. numnexthops = pRoute->NextHopsList.NumNextHops;
  75. if (numnexthops == 0)
  76. {
  77. Trace0(ROUTE,
  78. "Error adding route, no nexthops");
  79. TraceLeave("ChangeRouteWithForwarder");
  80. return ERROR_INVALID_PARAMETER;
  81. }
  82. numbytes = sizeof(IPMultihopRouteEntry) +
  83. (numnexthops - 1) *
  84. sizeof(IPRouteNextHopEntry);
  85. }
  86. else
  87. {
  88. //
  89. // for routes to be deleted, they should be stack
  90. // routes
  91. //
  92. // We do not have any next hops here
  93. numbytes = sizeof(IPMultihopRouteEntry);
  94. }
  95. __try
  96. {
  97. pMultiRouteEntry = _alloca(numbytes);
  98. }
  99. __except(EXCEPTION_EXECUTE_HANDLER)
  100. {
  101. return ERROR_NOT_ENOUGH_MEMORY;
  102. }
  103. pRouteEntry = &pMultiRouteEntry->imre_routeinfo;
  104. //
  105. // Fill the dest and mask for the current route
  106. //
  107. RTM_IPV4_GET_ADDR_AND_LEN(pRouteEntry->ire_dest,
  108. dwLen,
  109. pDestAddr);
  110. pRouteEntry->ire_mask = RTM_IPV4_MASK_FROM_LEN(dwLen);
  111. TraceRoute2(ROUTE,
  112. "route to %d.%d.%d.%d/%d.%d.%d.%d",
  113. PRINT_IPADDR(pRouteEntry->ire_dest),
  114. PRINT_IPADDR(pRouteEntry->ire_mask));
  115. if (!bAddRoute)
  116. {
  117. //
  118. // Prepare to delete old information on dest
  119. //
  120. pRouteEntry->ire_type = IRE_TYPE_INVALID;
  121. pMultiRouteEntry->imre_numnexthops = 0;
  122. Trace2(ROUTE,
  123. "ChangeRouteWithForwarder: Deleting all " \
  124. "routes to %d.%d.%d.%d/%d.%d.%d.%d",
  125. PRINT_IPADDR(pRouteEntry->ire_dest),
  126. PRINT_IPADDR(pRouteEntry->ire_mask));
  127. dwResult = SetIpMultihopRouteEntryToStack(pMultiRouteEntry);
  128. TraceLeave("ChangeRouteWithForwarder");
  129. return dwResult;
  130. }
  131. //
  132. // Get the routing protocol of the route's owner
  133. //
  134. dwResult = RtmGetEntityInfo(g_hLocalRoute,
  135. pRoute->RouteOwner,
  136. &entityInfo);
  137. if (dwResult isnot NO_ERROR)
  138. {
  139. Trace1(ROUTE,
  140. "Error %d retrieving entity info from RTM",
  141. dwResult);
  142. TraceLeave("ChangeRouteWithForwarder");
  143. return dwResult;
  144. }
  145. //
  146. // Prepare to add a multihop route on this dest
  147. //
  148. // Prepare information common to all nexthops
  149. pRouteEntry->ire_proto = entityInfo.EntityId.EntityProtocolId;
  150. pRouteEntry->ire_metric1 = pRoute->PrefInfo.Metric;
  151. pRouteEntry->ire_metric2 = IRE_METRIC_UNUSED;
  152. pRouteEntry->ire_metric3 = IRE_METRIC_UNUSED;
  153. pRouteEntry->ire_metric4 = IRE_METRIC_UNUSED;
  154. pRouteEntry->ire_metric5 = IRE_METRIC_UNUSED;
  155. pRouteEntry->ire_age = 0;
  156. numnexthops = 0;
  157. for (i = 0; i < pRoute->NextHopsList.NumNextHops; i++)
  158. {
  159. // Get and release next hop info as we got a copy
  160. dwResult = RtmGetNextHopInfo(g_hLocalRoute,
  161. pRoute->NextHopsList.NextHops[i],
  162. &nhiInfo);
  163. if (dwResult isnot NO_ERROR)
  164. {
  165. Trace1(ROUTE,
  166. "Error %d retrieving next hop info from RTM",
  167. dwResult);
  168. continue;
  169. }
  170. RtmReleaseNextHopInfo(g_hLocalRoute, &nhiInfo);
  171. // Get the next hop address from the nexthop info
  172. RTM_IPV4_GET_ADDR_AND_LEN(nexthop,
  173. dwLen,
  174. &nhiInfo.NextHopAddress);
  175. TraceRoute3(
  176. ROUTE, "Next Hop %d.%d.%d.%d, If 0x%x, handle is 0x%x",
  177. PRINT_IPADDR(nexthop),
  178. nhiInfo.InterfaceIndex,
  179. pRoute->NextHopsList.NextHops[i]
  180. );
  181. ENTER_READER(BINDING_LIST);
  182. //
  183. // find the binding given the interface id
  184. //
  185. pBinding = GetInterfaceBinding(nhiInfo.InterfaceIndex);
  186. if(!(pBinding))
  187. {
  188. //
  189. // The interface was deleted so lets just get out
  190. //
  191. EXIT_LOCK(BINDING_LIST);
  192. TraceRoute2(ERR,
  193. "**Warning** tried to %s route with interface %d which "
  194. "is no longer present",
  195. bAddRoute?"add":"delete",
  196. nhiInfo.InterfaceIndex);
  197. continue;
  198. }
  199. //
  200. // set adapter index - this is 0xffffffff
  201. // if the nexthop interface is not MAPPED
  202. //
  203. ifindex = pBinding->bBound ? pBinding->dwIfIndex : INVALID_IF_INDEX;
  204. if(((pRouteEntry->ire_proto is PROTO_IP_NT_STATIC) or
  205. (pRouteEntry->ire_proto is PROTO_IP_NT_AUTOSTATIC)) and
  206. (pBinding->ritType is ROUTER_IF_TYPE_FULL_ROUTER))
  207. {
  208. context = pBinding->dwSeqNumber;
  209. TraceRoute1(ROUTE,
  210. "route context : ICB == %d\n\n",
  211. pBinding->dwSeqNumber);
  212. }
  213. else
  214. {
  215. context = 0;
  216. if(ifindex is INVALID_IF_INDEX)
  217. {
  218. Trace3(ERR,
  219. "**Error** Tried to %s route to %d.%d.%d.%d over %d as DOD\n",
  220. bAddRoute?"add":"delete",
  221. PRINT_IPADDR(pRouteEntry->ire_dest),
  222. pBinding->dwIfIndex);
  223. EXIT_LOCK(BINDING_LIST);
  224. continue;
  225. }
  226. }
  227. //
  228. // First we figure out the correct nexthop for p2p links
  229. // For all other links, we take the whatever is given to us
  230. //
  231. if(IsIfP2P(pBinding->ritType))
  232. {
  233. if(pBinding->bBound)
  234. {
  235. TraceRoute2(
  236. ROUTE, "Next Hop %d.%d.%d.%d, remote address %d.%d.%d.%d, "
  237. "bound p2p",
  238. PRINT_IPADDR(nexthop),
  239. PRINT_IPADDR(pBinding->dwRemoteAddress)
  240. );
  241. if (nexthop is 0)
  242. {
  243. nexthop = pBinding->dwRemoteAddress;
  244. }
  245. }
  246. else
  247. {
  248. nexthop = 0;
  249. }
  250. }
  251. //
  252. // Now we figure out if the route is a direct route or indirect routes
  253. // Routes over unconnected demand dial routes are marked OTHER
  254. //
  255. //
  256. // For connected WAN interfaces (P2P with mask of 255.255.255.255) we
  257. // do two checks:
  258. // The next hop should be local address or remote address.
  259. // AR: We used to do the above check but removed it because when
  260. // we set a route over a disconnected interface, we dont
  261. // know the address of the remote endpoint
  262. // If the dest is remote address, then the MASK must be all ONES
  263. // We mark all valid routes as DIRECT
  264. //
  265. //
  266. // For LAN interfaces and WAN with non all ones mask, we check the
  267. // following:
  268. // A direct route to a host must have the Destination as the NextHop
  269. // A direct route to a network must have the the NextHop as one of the
  270. // local interfaces
  271. // The next hop must be on the same subnet as one of the bindings
  272. //
  273. type = IRE_TYPE_OTHER;
  274. if(pBinding->bBound)
  275. {
  276. if((pBinding->dwNumAddresses is 1) and
  277. (pBinding->rgibBinding[0].dwMask is ALL_ONES_MASK))
  278. {
  279. //
  280. // route over P2P link or P2MP link, possibly unnumbered.
  281. //
  282. if(
  283. //
  284. // if this is a route to the remote end of the P2P
  285. // connection
  286. //
  287. ((pBinding->dwRemoteAddress isnot 0) and
  288. (pRouteEntry->ire_dest is pBinding->dwRemoteAddress)) or
  289. //
  290. // OR
  291. // if the destination of the connection is the nexthop
  292. //
  293. (pRouteEntry->ire_dest is nexthop) or
  294. //
  295. // OR
  296. // if the nexthop is the local address of the P2P connection
  297. //
  298. (pBinding->rgibBinding[0].dwAddress is nexthop)
  299. )
  300. {
  301. //
  302. // This is a direct route as per the TCP/IP stack
  303. //
  304. type = IRE_TYPE_DIRECT;
  305. }
  306. else
  307. {
  308. type = IRE_TYPE_INDIRECT;
  309. }
  310. }
  311. else
  312. {
  313. //
  314. // A route over a non P2P link or a bay style p2p link which
  315. // has a /30 mask
  316. //
  317. bValidNHop = FALSE;
  318. type = IRE_TYPE_INDIRECT;
  319. for(i = 0; i < pBinding->dwNumAddresses; i++)
  320. {
  321. dwLocalMask = pBinding->rgibBinding[i].dwMask;
  322. dwLocalNet = pBinding->rgibBinding[i].dwAddress & dwLocalMask;
  323. if((dwLocalNet is (pRouteEntry->ire_dest & dwLocalMask)) or
  324. (nexthop is IP_LOOPBACK_ADDRESS) or
  325. (nexthop is pBinding->rgibBinding[i].dwAddress))
  326. {
  327. //
  328. // Route to local net or over loopback
  329. //
  330. type = IRE_TYPE_DIRECT;
  331. }
  332. if(((nexthop & dwLocalMask) is dwLocalNet) or
  333. ((nexthop is IP_LOOPBACK_ADDRESS)))
  334. {
  335. //
  336. // Next hop is on local net or loopback
  337. // That is good
  338. //
  339. bValidNHop = TRUE;
  340. break;
  341. }
  342. }
  343. if(!bValidNHop and
  344. (pBinding->dwNumAddresses isnot 0) and
  345. (pBinding->ritType isnot ROUTER_IF_TYPE_INTERNAL))
  346. {
  347. Trace0(ERR,
  348. "ERROR - Nexthop not on same network");
  349. for(i = 0; i < pBinding->dwNumAddresses; i ++)
  350. {
  351. Trace3(ROUTE,"AdapterId: %d, %d.%d.%d.%d/%d.%d.%d.%d",
  352. pBinding->dwIfIndex,
  353. PRINT_IPADDR(pBinding->rgibBinding[i].dwAddress),
  354. PRINT_IPADDR(pBinding->rgibBinding[i].dwMask));
  355. }
  356. EXIT_LOCK(BINDING_LIST);
  357. // PrintRoute(ERR, ipRoute);
  358. continue;
  359. }
  360. }
  361. }
  362. EXIT_LOCK(BINDING_LIST);
  363. #if 0
  364. // DGT workaround for bug where stack won't accept
  365. // nexthop of 0.0.0.0. Until Chait fixes this, we'll
  366. // set nexthop to the ifindex.
  367. if (!nexthop)
  368. {
  369. nexthop = ifindex;
  370. }
  371. #endif
  372. //
  373. // Fill the current nexthop info into the route
  374. //
  375. if (numnexthops)
  376. {
  377. // Copy to the next posn in the route
  378. pNexthopEntry =
  379. &pMultiRouteEntry->imre_morenexthops[numnexthops - 1];
  380. pNexthopEntry->ine_iretype = type;
  381. pNexthopEntry->ine_ifindex = ifindex;
  382. pNexthopEntry->ine_nexthop = nexthop;
  383. pNexthopEntry->ine_context = context;
  384. }
  385. else
  386. {
  387. // Copy to the first posn in the route
  388. pRouteEntry->ire_type = type;
  389. pRouteEntry->ire_index = ifindex;
  390. pRouteEntry->ire_nexthop = nexthop;
  391. pRouteEntry->ire_context = context;
  392. }
  393. numnexthops++;
  394. }
  395. pMultiRouteEntry->imre_numnexthops = numnexthops;
  396. pMultiRouteEntry->imre_flags = bDelOld ? IMRE_FLAG_DELETE_DEST : 0;
  397. if (numnexthops > 0)
  398. {
  399. dwResult = SetIpMultihopRouteEntryToStack(pMultiRouteEntry);
  400. if(dwResult isnot NO_ERROR)
  401. {
  402. if(pRouteEntry->ire_nexthop != IP_LOOPBACK_ADDRESS)
  403. {
  404. Trace1(ERR,
  405. "Route addition failed with %x for", dwResult);
  406. PrintRoute(ERR, pMultiRouteEntry);
  407. }
  408. Trace1(ERR,
  409. "Route addition failed with %x for local route", dwResult);
  410. TraceLeave("ChangeRouteWithForwarder");
  411. return dwResult;
  412. }
  413. else
  414. {
  415. Trace0(ROUTE,
  416. "Route addition succeeded for");
  417. PrintRoute(ROUTE, pMultiRouteEntry);
  418. }
  419. }
  420. else
  421. {
  422. Trace0(ERR, "Route not added since there are no next hops" );
  423. PrintRoute(ROUTE, pMultiRouteEntry);
  424. }
  425. TraceLeave("ChangeRouteWithForwarder");
  426. return NO_ERROR;
  427. }
  428. DWORD
  429. WINAPI
  430. ValidateRouteForProtocol(
  431. IN DWORD dwProtoId,
  432. IN PVOID pRouteInfo,
  433. IN PVOID pDestAddr OPTIONAL
  434. )
  435. /*++
  436. Routine Description:
  437. This function is called by the router Manger (and indirectly by routing
  438. protocols) to validate the route info. We set the preference and the
  439. type of the route
  440. Locks:
  441. Acquires the binding lock
  442. This function CAN NOT acquire the ICB lock
  443. Arguments:
  444. dwProtoId Protocols Id
  445. pRoute
  446. Return Value:
  447. NO_ERROR
  448. RtmError code
  449. --*/
  450. {
  451. RTM_DEST_INFO destInfo;
  452. PRTM_ROUTE_INFO pRoute;
  453. RTM_NEXTHOP_INFO nextHop;
  454. PADAPTER_INFO pBinding;
  455. HANDLE hNextHop;
  456. BOOL bValidNHop;
  457. DWORD dwIfIndex;
  458. DWORD dwLocalNet;
  459. DWORD dwLocalMask;
  460. DWORD destAddr;
  461. DWORD destMask;
  462. DWORD nexthop;
  463. DWORD nhopMask;
  464. DWORD dwType;
  465. DWORD dwResult;
  466. UINT i, j;
  467. pRoute = (PRTM_ROUTE_INFO)pRouteInfo;
  468. if (pRoute->PrefInfo.Preference is 0)
  469. {
  470. //
  471. // Map the metric weight based on the weight assigned by admin
  472. //
  473. pRoute->PrefInfo.Preference = ComputeRouteMetric(dwProtoId);
  474. }
  475. //
  476. // This validation applies to the unicast routes only.
  477. // [ This does not apply to INACTIVE routes and such ]
  478. //
  479. if (!(pRoute->BelongsToViews & RTM_VIEW_MASK_UCAST))
  480. {
  481. return NO_ERROR;
  482. }
  483. //
  484. // Get the destination address if it is not specified
  485. //
  486. if (!ARGUMENT_PRESENT(pDestAddr))
  487. {
  488. //
  489. // Get the destination information from the route
  490. //
  491. dwResult = RtmGetDestInfo(g_hLocalRoute,
  492. pRoute->DestHandle,
  493. RTM_BEST_PROTOCOL,
  494. RTM_VIEW_MASK_UCAST,
  495. &destInfo);
  496. if (dwResult != NO_ERROR)
  497. {
  498. Trace0(ERR,
  499. "**ERROR:ValidateRoute: Invalid destination");
  500. return dwResult;
  501. }
  502. pDestAddr = &destInfo.DestAddress;
  503. RtmReleaseDestInfo(g_hLocalRoute, &destInfo);
  504. }
  505. RTM_IPV4_GET_ADDR_AND_MASK(destAddr,
  506. destMask,
  507. (PRTM_NET_ADDRESS)pDestAddr);
  508. //
  509. // If the dest&Mask != dest then the stack will not set this route
  510. // Hence lets do the check here
  511. //
  512. if((destAddr & destMask) isnot destAddr)
  513. {
  514. TraceRoute2(ROUTE,
  515. "**ERROR:ValidateRoute: called with Dest %d.%d.%d.%d and "
  516. "Mask %d.%d.%d.%d - This will fail**",
  517. PRINT_IPADDR(destAddr),
  518. PRINT_IPADDR(destMask));
  519. return ERROR_INVALID_PARAMETER;
  520. }
  521. if((((DWORD)(destAddr & 0x000000FF)) >= (DWORD)0x000000E0) and
  522. (destAddr isnot ALL_ONES_BROADCAST) and
  523. (destAddr isnot LOCAL_NET_MULTICAST))
  524. {
  525. //
  526. // This will catch the CLASS D/E but allow all 1's bcast
  527. //
  528. Trace1(ERR,
  529. "**ERROR:ValidateRoute: Dest %d.%d.%d.%d is invalid",
  530. PRINT_IPADDR(destAddr));
  531. return ERROR_INVALID_PARAMETER;
  532. }
  533. if (pRoute->NextHopsList.NumNextHops == 0)
  534. {
  535. Trace0(ERR,
  536. "**ERROR:ValidateRoute: Zero next hops");
  537. return ERROR_INVALID_PARAMETER;
  538. }
  539. // Make sure each next hop on the route is a valid one
  540. for (i = 0; i < pRoute->NextHopsList.NumNextHops; i++)
  541. {
  542. hNextHop = pRoute->NextHopsList.NextHops[i];
  543. dwResult = RtmGetNextHopInfo(g_hLocalRoute,
  544. hNextHop,
  545. &nextHop);
  546. if (dwResult != NO_ERROR)
  547. {
  548. Trace0(ERR,
  549. "**ERROR:ValidateRoute: Invalid next hop");
  550. return dwResult;
  551. }
  552. dwIfIndex = nextHop.InterfaceIndex;
  553. RTM_IPV4_GET_ADDR_AND_MASK(nexthop,
  554. nhopMask,
  555. (PRTM_NET_ADDRESS)&nextHop.NextHopAddress);
  556. RtmReleaseNextHopInfo(g_hLocalRoute, &nextHop);
  557. // *** Exclusion Begin ***
  558. ENTER_READER(BINDING_LIST);
  559. //
  560. // find the interface given the interface id
  561. //
  562. pBinding = GetInterfaceBinding(dwIfIndex);
  563. if(!pBinding)
  564. {
  565. EXIT_LOCK(BINDING_LIST);
  566. Trace0(ERR,
  567. "**ERROR:ValidateRoute: Binding doesnt exist for "
  568. "interface");
  569. return ERROR_INVALID_PARAMETER;
  570. }
  571. //
  572. // Set whether the route is P2P
  573. //
  574. if(IsIfP2P(pBinding->ritType))
  575. {
  576. // Note that in the multihop case, we just overwrite value
  577. SetRouteP2P(pRoute);
  578. }
  579. //
  580. // Now we figure out if the route is a direct route or indirect routes
  581. // Routes over unconnected demand dial routes are marked OTHER
  582. //
  583. //
  584. // For connected WAN interfaces (P2P with mask of 255.255.255.255) we
  585. // do two checks:
  586. // The next hop should be local address or remote address.
  587. // AR: We used to do the above check but removed it because when
  588. // we set a route over a disconnected interface, we dont
  589. // know the address of the remote endpoint
  590. // If the dest is remote address, then the MASK must be all ONES
  591. // We mark all valid routes as DIRECT
  592. //
  593. //
  594. // For LAN interfaces and WAN with non all ones mask, we check the
  595. // following:
  596. // A direct route to a host to must have the Destination as the NextHop
  597. // A direct route to a network to must have the the NextHop as one of the
  598. // local interfaces
  599. // The next hop must be on the same subnet as one of the bindings
  600. //
  601. dwType = IRE_TYPE_OTHER;
  602. if(pBinding->bBound and IsRouteValid(pRoute))
  603. {
  604. if((pBinding->dwNumAddresses is 1) and
  605. (pBinding->rgibBinding[0].dwMask is ALL_ONES_MASK))
  606. {
  607. //
  608. // route over P2P link.
  609. // Set it to indirect and mark it as a P2P route
  610. //
  611. dwType = IRE_TYPE_DIRECT;
  612. //IpRtAssert(IsRouteP2P(pRoute));
  613. }
  614. else
  615. {
  616. //
  617. // A route over a non P2P link possibly unnumbered
  618. //
  619. bValidNHop = FALSE;
  620. dwType = IRE_TYPE_INDIRECT;
  621. for(j = 0; j < pBinding->dwNumAddresses; j++)
  622. {
  623. dwLocalMask = pBinding->rgibBinding[j].dwMask;
  624. dwLocalNet = pBinding->rgibBinding[j].dwAddress & dwLocalMask;
  625. if((dwLocalNet is (destAddr & dwLocalMask)) or
  626. (nexthop is IP_LOOPBACK_ADDRESS) or
  627. //(nexthop is dwLocalNet) or
  628. (nexthop is pBinding->rgibBinding[i].dwAddress))
  629. {
  630. //
  631. // Route to local net or over loopback
  632. //
  633. dwType = IRE_TYPE_DIRECT;
  634. }
  635. if(((nexthop & dwLocalMask) is dwLocalNet) or
  636. ((nexthop is IP_LOOPBACK_ADDRESS)))
  637. {
  638. //
  639. // Next hop is on local net or loopback
  640. // That is good
  641. //
  642. bValidNHop = TRUE;
  643. break;
  644. }
  645. }
  646. if(!bValidNHop and
  647. pBinding->dwNumAddresses and
  648. (pBinding->ritType isnot ROUTER_IF_TYPE_INTERNAL))
  649. {
  650. Trace1(ERR,
  651. "ValidateRoute: Nexthop %d.%d.%d.%d not on network",
  652. PRINT_IPADDR(nexthop));
  653. for(j = 0; j < pBinding->dwNumAddresses; j++)
  654. {
  655. Trace3(ROUTE,"AdapterId: %d, %d.%d.%d.%d/%d.%d.%d.%d",
  656. pBinding->dwIfIndex,
  657. PRINT_IPADDR(pBinding->rgibBinding[j].dwAddress),
  658. PRINT_IPADDR(pBinding->rgibBinding[j].dwMask));
  659. }
  660. EXIT_LOCK(BINDING_LIST);
  661. return ERROR_INVALID_PARAMETER;
  662. }
  663. }
  664. }
  665. // *** Exclusion End ***
  666. EXIT_LOCK(BINDING_LIST);
  667. }
  668. //
  669. // Set the appropriate route flags in the route - stack flag etc.
  670. //
  671. g_LastUpdateTable[IPFORWARDCACHE] = 0;
  672. return NO_ERROR;
  673. }
  674. DWORD
  675. WINAPI
  676. ValidateRouteForProtocolEx(
  677. IN DWORD dwProtoId,
  678. IN PVOID pRouteInfo,
  679. IN PVOID pDestAddr OPTIONAL
  680. )
  681. /*++
  682. Routine Description:
  683. This function is called by the router Manger (and indirectly by routing
  684. protocols) to validate the route info. We set the preference and the
  685. type of the route
  686. Locks:
  687. Acquires the binding lock
  688. This function CAN NOT acquire the ICB lock
  689. Arguments:
  690. dwProtoId Protocols Id
  691. pRoute
  692. Return Value:
  693. NO_ERROR
  694. RtmError code
  695. --*/
  696. {
  697. DWORD dwResult;
  698. dwResult = ValidateRouteForProtocol(
  699. dwProtoId,
  700. pRouteInfo,
  701. pDestAddr
  702. );
  703. if (dwResult is NO_ERROR)
  704. {
  705. ((PRTM_ROUTE_INFO)pRouteInfo)->Flags1 |= IP_STACK_ROUTE;
  706. }
  707. return dwResult;
  708. }