Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

987 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(((pBinding->dwRemoteAddress isnot 0) and
  283. (pRouteEntry->ire_dest is pBinding->dwRemoteAddress)) or
  284. (pRouteEntry->ire_dest is nexthop))
  285. {
  286. type = IRE_TYPE_DIRECT;
  287. }
  288. else
  289. {
  290. type = IRE_TYPE_INDIRECT;
  291. }
  292. }
  293. else
  294. {
  295. //
  296. // A route over a non P2P link or a bay style p2p link which
  297. // has a /30 mask
  298. //
  299. bValidNHop = FALSE;
  300. type = IRE_TYPE_INDIRECT;
  301. for(i = 0; i < pBinding->dwNumAddresses; i++)
  302. {
  303. dwLocalMask = pBinding->rgibBinding[i].dwMask;
  304. dwLocalNet = pBinding->rgibBinding[i].dwAddress & dwLocalMask;
  305. if((dwLocalNet is (pRouteEntry->ire_dest & dwLocalMask)) or
  306. (nexthop is IP_LOOPBACK_ADDRESS) or
  307. (nexthop is pBinding->rgibBinding[i].dwAddress))
  308. {
  309. //
  310. // Route to local net or over loopback
  311. //
  312. type = IRE_TYPE_DIRECT;
  313. }
  314. if(((nexthop & dwLocalMask) is dwLocalNet) or
  315. ((nexthop is IP_LOOPBACK_ADDRESS)))
  316. {
  317. //
  318. // Next hop is on local net or loopback
  319. // That is good
  320. //
  321. bValidNHop = TRUE;
  322. break;
  323. }
  324. }
  325. if(!bValidNHop and
  326. (pBinding->dwNumAddresses isnot 0) and
  327. (pBinding->ritType isnot ROUTER_IF_TYPE_INTERNAL))
  328. {
  329. Trace0(ERR,
  330. "ERROR - Nexthop not on same network");
  331. for(i = 0; i < pBinding->dwNumAddresses; i ++)
  332. {
  333. Trace3(ROUTE,"AdapterId: %d, %d.%d.%d.%d/%d.%d.%d.%d",
  334. pBinding->dwIfIndex,
  335. PRINT_IPADDR(pBinding->rgibBinding[i].dwAddress),
  336. PRINT_IPADDR(pBinding->rgibBinding[i].dwMask));
  337. }
  338. EXIT_LOCK(BINDING_LIST);
  339. // PrintRoute(ERR, ipRoute);
  340. continue;
  341. }
  342. }
  343. }
  344. EXIT_LOCK(BINDING_LIST);
  345. #if 0
  346. // DGT workaround for bug where stack won't accept
  347. // nexthop of 0.0.0.0. Until Chait fixes this, we'll
  348. // set nexthop to the ifindex.
  349. if (!nexthop)
  350. {
  351. nexthop = ifindex;
  352. }
  353. #endif
  354. //
  355. // Fill the current nexthop info into the route
  356. //
  357. if (numnexthops)
  358. {
  359. // Copy to the next posn in the route
  360. pNexthopEntry =
  361. &pMultiRouteEntry->imre_morenexthops[numnexthops - 1];
  362. pNexthopEntry->ine_iretype = type;
  363. pNexthopEntry->ine_ifindex = ifindex;
  364. pNexthopEntry->ine_nexthop = nexthop;
  365. pNexthopEntry->ine_context = context;
  366. }
  367. else
  368. {
  369. // Copy to the first posn in the route
  370. pRouteEntry->ire_type = type;
  371. pRouteEntry->ire_index = ifindex;
  372. pRouteEntry->ire_nexthop = nexthop;
  373. pRouteEntry->ire_context = context;
  374. }
  375. numnexthops++;
  376. }
  377. pMultiRouteEntry->imre_numnexthops = numnexthops;
  378. pMultiRouteEntry->imre_flags = bDelOld ? IMRE_FLAG_DELETE_DEST : 0;
  379. if (numnexthops > 0)
  380. {
  381. dwResult = SetIpMultihopRouteEntryToStack(pMultiRouteEntry);
  382. if(dwResult isnot NO_ERROR)
  383. {
  384. if(pRouteEntry->ire_nexthop != IP_LOOPBACK_ADDRESS)
  385. {
  386. Trace1(ERR,
  387. "Route addition failed with %x for", dwResult);
  388. PrintRoute(ERR, pMultiRouteEntry);
  389. }
  390. Trace1(ERR,
  391. "Route addition failed with %x for local route", dwResult);
  392. TraceLeave("ChangeRouteWithForwarder");
  393. return dwResult;
  394. }
  395. else
  396. {
  397. Trace0(ROUTE,
  398. "Route addition succeeded for");
  399. PrintRoute(ROUTE, pMultiRouteEntry);
  400. }
  401. }
  402. else
  403. {
  404. Trace0(ERR, "Route not added since there are no next hops" );
  405. PrintRoute(ROUTE, pMultiRouteEntry);
  406. }
  407. TraceLeave("ChangeRouteWithForwarder");
  408. return NO_ERROR;
  409. }
  410. DWORD
  411. WINAPI
  412. ValidateRouteForProtocol(
  413. IN DWORD dwProtoId,
  414. IN PVOID pRouteInfo,
  415. IN PVOID pDestAddr OPTIONAL
  416. )
  417. /*++
  418. Routine Description:
  419. This function is called by the router Manger (and indirectly by routing
  420. protocols) to validate the route info. We set the preference and the
  421. type of the route
  422. Locks:
  423. Acquires the binding lock
  424. This function CAN NOT acquire the ICB lock
  425. Arguments:
  426. dwProtoId Protocols Id
  427. pRoute
  428. Return Value:
  429. NO_ERROR
  430. RtmError code
  431. --*/
  432. {
  433. RTM_DEST_INFO destInfo;
  434. PRTM_ROUTE_INFO pRoute;
  435. RTM_NEXTHOP_INFO nextHop;
  436. PADAPTER_INFO pBinding;
  437. HANDLE hNextHop;
  438. BOOL bValidNHop;
  439. DWORD dwIfIndex;
  440. DWORD dwLocalNet;
  441. DWORD dwLocalMask;
  442. DWORD destAddr;
  443. DWORD destMask;
  444. DWORD nexthop;
  445. DWORD nhopMask;
  446. DWORD dwType;
  447. DWORD dwResult;
  448. UINT i, j;
  449. pRoute = (PRTM_ROUTE_INFO)pRouteInfo;
  450. if (pRoute->PrefInfo.Preference is 0)
  451. {
  452. //
  453. // Map the metric weight based on the weight assigned by admin
  454. //
  455. pRoute->PrefInfo.Preference = ComputeRouteMetric(dwProtoId);
  456. }
  457. //
  458. // This validation applies to the unicast routes only.
  459. // [ This does not apply to INACTIVE routes and such ]
  460. //
  461. if (!(pRoute->BelongsToViews & RTM_VIEW_MASK_UCAST))
  462. {
  463. return NO_ERROR;
  464. }
  465. //
  466. // Get the destination address if it is not specified
  467. //
  468. if (!ARGUMENT_PRESENT(pDestAddr))
  469. {
  470. //
  471. // Get the destination information from the route
  472. //
  473. dwResult = RtmGetDestInfo(g_hLocalRoute,
  474. pRoute->DestHandle,
  475. RTM_BEST_PROTOCOL,
  476. RTM_VIEW_MASK_UCAST,
  477. &destInfo);
  478. if (dwResult != NO_ERROR)
  479. {
  480. Trace0(ERR,
  481. "**ERROR:ValidateRoute: Invalid destination");
  482. return dwResult;
  483. }
  484. pDestAddr = &destInfo.DestAddress;
  485. RtmReleaseDestInfo(g_hLocalRoute, &destInfo);
  486. }
  487. RTM_IPV4_GET_ADDR_AND_MASK(destAddr,
  488. destMask,
  489. (PRTM_NET_ADDRESS)pDestAddr);
  490. //
  491. // If the dest&Mask != dest then the stack will not set this route
  492. // Hence lets do the check here
  493. //
  494. if((destAddr & destMask) isnot destAddr)
  495. {
  496. #if TRACE_DBG
  497. Trace2(ROUTE,
  498. "**ERROR:ValidateRoute: called with Dest %d.%d.%d.%d and Mask %d.%d.%d.%d - This will fail**",
  499. PRINT_IPADDR(destAddr),
  500. PRINT_IPADDR(destMask));
  501. #endif // TRACE_DBG
  502. return ERROR_INVALID_PARAMETER;
  503. }
  504. if((((DWORD)(destAddr & 0x000000FF)) >= (DWORD)0x000000E0) and
  505. (destAddr isnot ALL_ONES_BROADCAST) and
  506. (destAddr isnot LOCAL_NET_MULTICAST))
  507. {
  508. //
  509. // This will catch the CLASS D/E but allow all 1's bcast
  510. //
  511. Trace1(ERR,
  512. "**ERROR:ValidateRoute: Dest %d.%d.%d.%d is invalid",
  513. PRINT_IPADDR(destAddr));
  514. return ERROR_INVALID_PARAMETER;
  515. }
  516. #if 0
  517. // Removed this since metric=0 is legal for routes to the loopback
  518. // interface.
  519. if(pRoute->PrefInfo.Metric is 0)
  520. {
  521. Trace0(ERR,
  522. "**ERROR:ValidateRoute: Metric cant be 0");
  523. return ERROR_INVALID_PARAMETER;
  524. }
  525. #endif
  526. if (pRoute->NextHopsList.NumNextHops == 0)
  527. {
  528. Trace0(ERR,
  529. "**ERROR:ValidateRoute: Zero next hops");
  530. return ERROR_INVALID_PARAMETER;
  531. }
  532. // Make sure each next hop on the route is a valid one
  533. for (i = 0; i < pRoute->NextHopsList.NumNextHops; i++)
  534. {
  535. hNextHop = pRoute->NextHopsList.NextHops[i];
  536. dwResult = RtmGetNextHopInfo(g_hLocalRoute,
  537. hNextHop,
  538. &nextHop);
  539. if (dwResult != NO_ERROR)
  540. {
  541. Trace0(ERR,
  542. "**ERROR:ValidateRoute: Invalid next hop");
  543. return dwResult;
  544. }
  545. dwIfIndex = nextHop.InterfaceIndex;
  546. RTM_IPV4_GET_ADDR_AND_MASK(nexthop,
  547. nhopMask,
  548. (PRTM_NET_ADDRESS)&nextHop.NextHopAddress);
  549. RtmReleaseNextHopInfo(g_hLocalRoute, &nextHop);
  550. // *** Exclusion Begin ***
  551. ENTER_READER(BINDING_LIST);
  552. //
  553. // find the interface given the interface id
  554. //
  555. pBinding = GetInterfaceBinding(dwIfIndex);
  556. if(!pBinding)
  557. {
  558. EXIT_LOCK(BINDING_LIST);
  559. #if TRACE_DBG
  560. Trace0(ERR,
  561. "**ERROR:ValidateRoute: Interface block doesnt exist");
  562. #endif // TRACE_DBG
  563. return ERROR_INVALID_PARAMETER;
  564. }
  565. //
  566. // Set whether the route is P2P
  567. //
  568. if(IsIfP2P(pBinding->ritType))
  569. {
  570. // Note that in the multihop case, we just overwrite value
  571. SetRouteP2P(pRoute);
  572. /*
  573. ipRoute->RR_NextHopAddress.N_NetNumber =
  574. RtlUlongByteSwap(pBinding->dwIfIndex);
  575. ipRoute->RR_NextHopAddress.N_NetMask = ALL_ONES_MASK;
  576. */
  577. }
  578. /*
  579. //
  580. // If the next hop mask is not set, we need to do so now. Normally
  581. // this shouldnt happen
  582. //
  583. #if ROUTE_DBG
  584. if(!(ipRoute->RR_NextHopAddress.N_NetMask))
  585. {
  586. Trace0(ERR,
  587. "**WARNING:Route doesnt seem to have any next hop mask**");
  588. }
  589. #endif // ROUTE_DBG
  590. */
  591. //
  592. // Now we figure out if the route is a direct route or indirect routes
  593. // Routes over unconnected demand dial routes are marked OTHER
  594. //
  595. //
  596. // For connected WAN interfaces (P2P with mask of 255.255.255.255) we
  597. // do two checks:
  598. // The next hop should be local address or remote address.
  599. // AR: We used to do the above check but removed it because when
  600. // we set a route over a disconnected interface, we dont
  601. // know the address of the remote endpoint
  602. // If the dest is remote address, then the MASK must be all ONES
  603. // We mark all valid routes as DIRECT
  604. //
  605. //
  606. // For LAN interfaces and WAN with non all ones mask, we check the
  607. // following:
  608. // A direct route to a host to must have the Destination as the NextHop
  609. // A direct route to a network to must have the the NextHop as one of the
  610. // local interfaces
  611. // The next hop must be on the same subnet as one of the bindings
  612. //
  613. dwType = IRE_TYPE_OTHER;
  614. if(pBinding->bBound and IsRouteValid(pRoute))
  615. {
  616. //
  617. // Comment this block out - as we validate this
  618. // next hop for the LAN case below, and dont care
  619. // what it is in the WAN case as we set it to 0.
  620. //
  621. /*
  622. //
  623. // So outgoing interface has a valid address
  624. // and next hop should have been plumbed in
  625. //
  626. if(nexthop && (destAddr is nexthop))
  627. {
  628. //
  629. // A direct host route
  630. //
  631. if(destMask isnot HOST_ROUTE_MASK)
  632. {
  633. EXIT_LOCK(BINDING_LIST);
  634. Trace0(ERR,
  635. "ValidateRoute: Host route with wrong mask");
  636. return ERROR_INVALID_PARAMETER;
  637. }
  638. dwType = IRE_TYPE_DIRECT;
  639. }
  640. */
  641. if((pBinding->dwNumAddresses is 1) and
  642. (pBinding->rgibBinding[0].dwMask is ALL_ONES_MASK))
  643. {
  644. //
  645. // route over P2P link.
  646. // Set it to indirect and mark it as a P2P route
  647. //
  648. dwType = IRE_TYPE_DIRECT;
  649. //IpRtAssert(IsRouteP2P(pRoute));
  650. }
  651. else
  652. {
  653. //
  654. // A route over a non P2P link possibly unnumbered
  655. //
  656. bValidNHop = FALSE;
  657. dwType = IRE_TYPE_INDIRECT;
  658. for(j = 0; j < pBinding->dwNumAddresses; j++)
  659. {
  660. dwLocalMask = pBinding->rgibBinding[j].dwMask;
  661. dwLocalNet = pBinding->rgibBinding[j].dwAddress & dwLocalMask;
  662. if((dwLocalNet is (destAddr & dwLocalMask)) or
  663. (nexthop is IP_LOOPBACK_ADDRESS) or
  664. //(nexthop is dwLocalNet) or
  665. (nexthop is pBinding->rgibBinding[i].dwAddress))
  666. {
  667. //
  668. // Route to local net or over loopback
  669. //
  670. dwType = IRE_TYPE_DIRECT;
  671. }
  672. if(((nexthop & dwLocalMask) is dwLocalNet) or
  673. ((nexthop is IP_LOOPBACK_ADDRESS)))
  674. {
  675. //
  676. // Next hop is on local net or loopback
  677. // That is good
  678. //
  679. bValidNHop = TRUE;
  680. break;
  681. }
  682. }
  683. if(!bValidNHop and
  684. pBinding->dwNumAddresses and
  685. (pBinding->ritType isnot ROUTER_IF_TYPE_INTERNAL))
  686. {
  687. Trace1(ERR,
  688. "ValidateRoute: Nexthop %d.%d.%d.%d not on network",
  689. PRINT_IPADDR(nexthop));
  690. for(j = 0; j < pBinding->dwNumAddresses; j++)
  691. {
  692. Trace3(ROUTE,"AdapterId: %d, %d.%d.%d.%d/%d.%d.%d.%d",
  693. pBinding->dwIfIndex,
  694. PRINT_IPADDR(pBinding->rgibBinding[j].dwAddress),
  695. PRINT_IPADDR(pBinding->rgibBinding[j].dwMask));
  696. }
  697. EXIT_LOCK(BINDING_LIST);
  698. return ERROR_INVALID_PARAMETER;
  699. }
  700. }
  701. }
  702. /*
  703. #if ROUTE_DBG
  704. if(ipRoute->RR_NextHopAddress.N_NetMask isnot dwLocalMask)
  705. {
  706. Trace0(ERR,
  707. "**WARNING:Route doesnt seem to have the right next hop mask**");
  708. PrintRoute(ERR,ipRoute);
  709. ipRoute->RR_NextHopAddress.N_NetMask = dwLocalMask;
  710. }
  711. #endif // ROUTE_DBG
  712. */
  713. // *** Exclusion End ***
  714. EXIT_LOCK(BINDING_LIST);
  715. }
  716. //
  717. // Set the appropriate route flags in the route - stack flag etc.
  718. //
  719. // pRoute->Flags1 |= IP_STACK_ROUTE;
  720. g_LastUpdateTable[IPFORWARDCACHE] = 0;
  721. return NO_ERROR;
  722. }
  723. DWORD
  724. WINAPI
  725. ValidateRouteForProtocolEx(
  726. IN DWORD dwProtoId,
  727. IN PVOID pRouteInfo,
  728. IN PVOID pDestAddr OPTIONAL
  729. )
  730. /*++
  731. Routine Description:
  732. This function is called by the router Manger (and indirectly by routing
  733. protocols) to validate the route info. We set the preference and the
  734. type of the route
  735. Locks:
  736. Acquires the binding lock
  737. This function CAN NOT acquire the ICB lock
  738. Arguments:
  739. dwProtoId Protocols Id
  740. pRoute
  741. Return Value:
  742. NO_ERROR
  743. RtmError code
  744. --*/
  745. {
  746. DWORD dwResult;
  747. dwResult = ValidateRouteForProtocol(
  748. dwProtoId,
  749. pRouteInfo,
  750. pDestAddr
  751. );
  752. if (dwResult is NO_ERROR)
  753. {
  754. ((PRTM_ROUTE_INFO)pRouteInfo)->Flags1 |= IP_STACK_ROUTE;
  755. }
  756. return dwResult;
  757. }