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.

914 lines
17 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. rtmif.c
  5. Abstract:
  6. Static & local routes management functions
  7. Author:
  8. Stefan Solomon 03/13/1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. extern UCHAR bcastnode[6];
  14. INT
  15. NetNumCmpFunc(PDWORD Net1,
  16. PDWORD Net2);
  17. INT
  18. NextHopAddrCmpFunc(PRTM_IPX_ROUTE Route1p,
  19. PRTM_IPX_ROUTE Route2p);
  20. BOOL
  21. FamSpecDataCmpFunc(PRTM_IPX_ROUTE Route1p,
  22. PRTM_IPX_ROUTE Route2p);
  23. INT
  24. NetNumHashFunc(PDWORD Net);
  25. INT
  26. RouteMetricCmpFunc(PRTM_IPX_ROUTE Route1p,
  27. PRTM_IPX_ROUTE Route2p);
  28. DWORD
  29. RouteValidateFunc(PRTM_IPX_ROUTE Routep);
  30. RTM_PROTOCOL_FAMILY_CONFIG Config = {
  31. 0,
  32. 0,
  33. sizeof(RTM_IPX_ROUTE),
  34. NetNumCmpFunc,
  35. NextHopAddrCmpFunc,
  36. FamSpecDataCmpFunc,
  37. RouteMetricCmpFunc,
  38. NetNumHashFunc,
  39. RouteValidateFunc,
  40. FwUpdateRouteTable
  41. };
  42. USHORT
  43. tickcount(UINT linkspeed);
  44. /*++
  45. Function: CreateRouteTable
  46. Descr: Creates the IPX route table in RTM
  47. --*/
  48. DWORD
  49. CreateRouteTable(VOID)
  50. {
  51. DWORD rc;
  52. Config.RPFC_MaxTableSize = MaxRoutingTableSize;
  53. Config.RPFC_HashSize = RoutingTableHashSize;
  54. rc = RtmCreateRouteTable(
  55. RTM_PROTOCOL_FAMILY_IPX,
  56. &Config);
  57. return rc;
  58. }
  59. /*++
  60. Function: DeleteRouteTable
  61. Descr: Creates the IPX route table in RTM
  62. --*/
  63. DWORD
  64. DeleteRouteTable(VOID)
  65. {
  66. DWORD rc;
  67. rc = RtmDeleteRouteTable(RTM_PROTOCOL_FAMILY_IPX);
  68. return rc;
  69. }
  70. /*++
  71. Function: StaticToRtmRoute
  72. Descr: Creates a RTM IPX route entry out of an IPX_STATIC_ROUTE_INFO
  73. --*/
  74. VOID
  75. StaticToRtmRoute(PRTM_IPX_ROUTE RtmRoutep,
  76. ULONG IfIndex,
  77. PIPX_STATIC_ROUTE_INFO StaticRouteInfop)
  78. {
  79. RtmRoutep->R_Interface = IfIndex;
  80. RtmRoutep->R_Protocol = IPX_PROTOCOL_STATIC;
  81. GETLONG2ULONG(&RtmRoutep->R_Network, StaticRouteInfop->Network);
  82. RtmRoutep->R_TickCount = StaticRouteInfop->TickCount;
  83. RtmRoutep->R_HopCount = StaticRouteInfop->HopCount;
  84. memcpy(RtmRoutep->R_NextHopMacAddress,
  85. StaticRouteInfop->NextHopMacAddress,
  86. 6);
  87. RtmRoutep->R_Flags = 0;
  88. }
  89. VOID
  90. RtmToStaticRoute(PIPX_STATIC_ROUTE_INFO StaticRouteInfop,
  91. PRTM_IPX_ROUTE RtmRoutep)
  92. {
  93. PUTULONG2LONG(StaticRouteInfop->Network, RtmRoutep->R_Network);
  94. StaticRouteInfop->TickCount = (USHORT)(RtmRoutep->R_TickCount);
  95. StaticRouteInfop->HopCount = RtmRoutep->R_HopCount;
  96. memcpy(StaticRouteInfop->NextHopMacAddress,
  97. RtmRoutep->R_NextHopMacAddress,
  98. 6);
  99. }
  100. VOID
  101. RtmToIpxRoute(PIPX_ROUTE IpxRoutep,
  102. PRTM_IPX_ROUTE RtmRoutep)
  103. {
  104. IpxRoutep->InterfaceIndex = (ULONG)(RtmRoutep->R_Interface);
  105. IpxRoutep->Protocol = RtmRoutep->R_Protocol;
  106. PUTULONG2LONG(IpxRoutep->Network, RtmRoutep->R_Network);
  107. IpxRoutep->TickCount = (USHORT)(RtmRoutep->R_TickCount);
  108. IpxRoutep->HopCount = RtmRoutep->R_HopCount;
  109. memcpy(IpxRoutep->NextHopMacAddress,
  110. RtmRoutep->R_NextHopMacAddress,
  111. 6);
  112. IpxRoutep->Flags = RtmRoutep->R_Flags;
  113. }
  114. DWORD
  115. CreateStaticRoute(PICB icbp,
  116. PIPX_STATIC_ROUTE_INFO StaticRouteInfop)
  117. {
  118. DWORD rc, flags;
  119. RTM_IPX_ROUTE RtmRoute;
  120. StaticToRtmRoute(&RtmRoute, icbp->InterfaceIndex, StaticRouteInfop);
  121. if (icbp->AdminState==ADMIN_STATE_DISABLED)
  122. RtmRoute.R_Flags = DO_NOT_ADVERTISE_ROUTE;
  123. rc = RtmAddRoute(RtmStaticHandle,
  124. &RtmRoute,
  125. INFINITE,
  126. &flags,
  127. NULL,
  128. NULL);
  129. SS_ASSERT(rc == NO_ERROR);
  130. if (icbp->AdminState==ADMIN_STATE_DISABLED) {
  131. DisableStaticRoute (icbp->InterfaceIndex, StaticRouteInfop->Network);
  132. RtmRoute.R_Flags = 0;
  133. rc = RtmAddRoute(RtmStaticHandle,
  134. &RtmRoute,
  135. INFINITE,
  136. &flags,
  137. NULL,
  138. NULL);
  139. SS_ASSERT (rc == NO_ERROR);
  140. }
  141. return rc;
  142. }
  143. DWORD
  144. DeleteStaticRoute(ULONG IfIndex,
  145. PIPX_STATIC_ROUTE_INFO StaticRouteInfop)
  146. {
  147. DWORD rc;
  148. DWORD RtmFlags;
  149. RTM_IPX_ROUTE RtmRoute;
  150. StaticToRtmRoute(&RtmRoute, IfIndex, StaticRouteInfop);
  151. rc = RtmDeleteRoute(RtmStaticHandle,
  152. &RtmRoute,
  153. &RtmFlags,
  154. NULL
  155. );
  156. SS_ASSERT(rc == NO_ERROR);
  157. return rc;
  158. }
  159. VOID
  160. DeleteAllStaticRoutes(ULONG InterfaceIndex)
  161. {
  162. RTM_IPX_ROUTE RtmCriteriaRoute;
  163. Trace(ROUTE_TRACE, "DeleteAllStaticRoutes: Entered for if # %d\n", InterfaceIndex);
  164. memset(&RtmCriteriaRoute,
  165. 0,
  166. sizeof(RTM_IPX_ROUTE));
  167. RtmCriteriaRoute.R_Interface = InterfaceIndex;
  168. RtmCriteriaRoute.R_Protocol = IPX_PROTOCOL_STATIC;
  169. RtmBlockDeleteRoutes(RtmStaticHandle,
  170. RTM_ONLY_THIS_INTERFACE,
  171. &RtmCriteriaRoute);
  172. }
  173. VOID
  174. LocalToRtmRoute(PRTM_IPX_ROUTE RtmRoutep,
  175. PICB icbp)
  176. {
  177. RtmRoutep->R_Interface = icbp->InterfaceIndex;
  178. RtmRoutep->R_Protocol = IPX_PROTOCOL_LOCAL;
  179. GETLONG2ULONG(&RtmRoutep->R_Network, icbp->acbp->AdapterInfo.Network);
  180. RtmRoutep->R_TickCount = tickcount(icbp->acbp->AdapterInfo.LinkSpeed);
  181. RtmRoutep->R_HopCount = 1;
  182. memset(RtmRoutep->R_NextHopMacAddress,
  183. 0,
  184. 6);
  185. // if this is a local workstation dialout interface, then do not
  186. // advertise this route over any protocol
  187. if(icbp->MIBInterfaceType == IF_TYPE_ROUTER_WORKSTATION_DIALOUT) {
  188. RtmRoutep->R_Flags = DO_NOT_ADVERTISE_ROUTE;
  189. }
  190. else
  191. {
  192. RtmRoutep->R_Flags = 0;
  193. }
  194. }
  195. DWORD
  196. CreateLocalRoute(PICB icbp)
  197. {
  198. DWORD rc, flags;
  199. RTM_IPX_ROUTE RtmRoute;
  200. if(!memcmp(icbp->acbp->AdapterInfo.Network, nullnet, 4)) {
  201. Trace(ROUTE_TRACE, "CreateLocalRoute: Can't create local NULL route !\n");
  202. return NO_ERROR;
  203. }
  204. LocalToRtmRoute(&RtmRoute, icbp);
  205. rc = RtmAddRoute(RtmLocalHandle,
  206. &RtmRoute,
  207. INFINITE,
  208. &flags,
  209. NULL,
  210. NULL);
  211. SS_ASSERT(rc == NO_ERROR);
  212. return rc;
  213. }
  214. DWORD
  215. DeleteLocalRoute(PICB icbp)
  216. {
  217. DWORD rc;
  218. RTM_IPX_ROUTE RtmRoute;
  219. DWORD RtmFlags;
  220. LocalToRtmRoute(&RtmRoute, icbp);
  221. rc = RtmDeleteRoute(RtmLocalHandle,
  222. &RtmRoute,
  223. &RtmFlags,
  224. NULL);
  225. SS_ASSERT(rc == NO_ERROR);
  226. return rc;
  227. }
  228. VOID
  229. GlobalToRtmRoute(PRTM_IPX_ROUTE RtmRoutep,
  230. PUCHAR Network)
  231. {
  232. RtmRoutep->R_Interface = GLOBAL_INTERFACE_INDEX;
  233. RtmRoutep->R_Protocol = IPX_PROTOCOL_LOCAL;
  234. GETLONG2ULONG(&RtmRoutep->R_Network, Network);
  235. RtmRoutep->R_TickCount = 15; // a good default value -> should be a config param ??? !!!
  236. RtmRoutep->R_HopCount = 1;
  237. memset(RtmRoutep->R_NextHopMacAddress, 0, 6);
  238. RtmRoutep->R_Flags = GLOBAL_WAN_ROUTE;
  239. }
  240. /*++
  241. Function: CreateGlobalRoute
  242. Descr: Creates a route which doesn't have a corresponding interface
  243. but represents a set of interfaces (e.g. all client wan
  244. interfaces).
  245. The interface index for this route is the "global interface"
  246. index.
  247. --*/
  248. DWORD
  249. CreateGlobalRoute(PUCHAR Network)
  250. {
  251. DWORD rc, flags;
  252. RTM_IPX_ROUTE RtmRoute;
  253. Trace(ROUTE_TRACE, "CreateGlobalRoute: Entered for route %.2x%.2x%.2x%.2x\n",
  254. Network[0],
  255. Network[1],
  256. Network[2],
  257. Network[3]);
  258. GlobalToRtmRoute(&RtmRoute, Network);
  259. rc = RtmAddRoute(RtmLocalHandle,
  260. &RtmRoute,
  261. INFINITE,
  262. &flags,
  263. NULL,
  264. NULL);
  265. SS_ASSERT(rc == NO_ERROR);
  266. return rc;
  267. }
  268. DWORD
  269. DeleteGlobalRoute(PUCHAR Network)
  270. {
  271. DWORD rc;
  272. RTM_IPX_ROUTE RtmRoute;
  273. DWORD RtmFlags;
  274. Trace(ROUTE_TRACE, "DeleteGlobalRoute: Entered for route %.2x%.2x%.2x%.2x\n",
  275. Network[0],
  276. Network[1],
  277. Network[2],
  278. Network[3]);
  279. GlobalToRtmRoute(&RtmRoute, Network);
  280. rc = RtmDeleteRoute(RtmLocalHandle,
  281. &RtmRoute,
  282. &RtmFlags,
  283. NULL);
  284. SS_ASSERT(rc == NO_ERROR);
  285. return rc;
  286. }
  287. DWORD
  288. GetRoute(ULONG RoutingTable,
  289. PIPX_ROUTE IpxRoutep)
  290. {
  291. RTM_IPX_ROUTE RtmRoute;
  292. DWORD EnumFlags;
  293. DWORD rc;
  294. switch(RoutingTable) {
  295. case IPX_DEST_TABLE:
  296. EnumFlags = RTM_ONLY_THIS_NETWORK |
  297. RTM_ONLY_BEST_ROUTES | RTM_INCLUDE_DISABLED_ROUTES;
  298. GETLONG2ULONG(&RtmRoute.R_Network, IpxRoutep->Network);
  299. break;
  300. case IPX_STATIC_ROUTE_TABLE:
  301. EnumFlags = RTM_ONLY_THIS_NETWORK |
  302. RTM_ONLY_THIS_INTERFACE |
  303. RTM_ONLY_THIS_PROTOCOL |
  304. RTM_INCLUDE_DISABLED_ROUTES;
  305. RtmRoute.R_Interface = (IpxRoutep->InterfaceIndex);
  306. RtmRoute.R_Protocol = IPX_PROTOCOL_STATIC;
  307. GETLONG2ULONG(&RtmRoute.R_Network, IpxRoutep->Network);
  308. break;
  309. default:
  310. SS_ASSERT(FALSE);
  311. return ERROR_INVALID_PARAMETER;
  312. break;
  313. }
  314. rc = RtmGetFirstRoute(
  315. RTM_PROTOCOL_FAMILY_IPX,
  316. EnumFlags,
  317. &RtmRoute);
  318. RtmToIpxRoute(IpxRoutep, &RtmRoute);
  319. return rc;
  320. }
  321. /*++
  322. Function: IsRoute
  323. Descr: returns TRUE if there is a route to the specified
  324. network
  325. --*/
  326. BOOL
  327. IsRoute(PUCHAR Network)
  328. {
  329. RTM_IPX_ROUTE RtmRoute;
  330. DWORD EnumFlags;
  331. DWORD rc;
  332. EnumFlags = RTM_ONLY_THIS_NETWORK |
  333. RTM_ONLY_BEST_ROUTES |
  334. RTM_INCLUDE_DISABLED_ROUTES;
  335. GETLONG2ULONG(&RtmRoute.R_Network, Network);
  336. rc = RtmGetFirstRoute(
  337. RTM_PROTOCOL_FAMILY_IPX,
  338. EnumFlags,
  339. &RtmRoute);
  340. if(rc == NO_ERROR) {
  341. return TRUE;
  342. }
  343. return FALSE;
  344. }
  345. //********************************************************************************
  346. // *
  347. // Fast Enumeration Functions - Used by the Router Manager for internal purposes *
  348. // *
  349. //********************************************************************************
  350. HANDLE
  351. CreateStaticRoutesEnumHandle(ULONG InterfaceIndex)
  352. {
  353. RTM_IPX_ROUTE EnumCriteriaRoute;
  354. HANDLE EnumHandle;
  355. memset(&EnumCriteriaRoute, 0, sizeof(RTM_IPX_ROUTE));
  356. EnumCriteriaRoute.R_Interface = InterfaceIndex;
  357. EnumCriteriaRoute.R_Protocol = IPX_PROTOCOL_STATIC;
  358. EnumHandle = RtmCreateEnumerationHandle(RTM_PROTOCOL_FAMILY_IPX,
  359. RTM_ONLY_THIS_INTERFACE | RTM_ONLY_THIS_PROTOCOL | RTM_INCLUDE_DISABLED_ROUTES,
  360. &EnumCriteriaRoute);
  361. if((EnumHandle == NULL) && (GetLastError() != ERROR_NO_ROUTES)) {
  362. Trace(ROUTE_TRACE, "CreateStaticRoutesEnumHandle: RtmCreateEnumerationHandle failed with %d\n", GetLastError());
  363. SS_ASSERT(FALSE);
  364. }
  365. return EnumHandle;
  366. }
  367. DWORD
  368. GetNextStaticRoute(HANDLE EnumHandle,
  369. PIPX_STATIC_ROUTE_INFO StaticRtInfop)
  370. {
  371. RTM_IPX_ROUTE RtmRoute;
  372. DWORD rc;
  373. rc = RtmEnumerateGetNextRoute(EnumHandle,
  374. &RtmRoute);
  375. SS_ASSERT((rc == NO_ERROR) || (rc == ERROR_NO_MORE_ROUTES));
  376. RtmToStaticRoute(StaticRtInfop, &RtmRoute);
  377. return rc;
  378. }
  379. VOID
  380. CloseStaticRoutesEnumHandle(HANDLE EnumHandle)
  381. {
  382. if(EnumHandle) {
  383. RtmCloseEnumerationHandle(EnumHandle);
  384. }
  385. }
  386. //********************************************************************************
  387. // *
  388. // Slow Enumeration Functions - Used by the Router Manager for MIB APIs support *
  389. // *
  390. //********************************************************************************
  391. DWORD
  392. GetFirstRoute(ULONG RoutingTable,
  393. PIPX_ROUTE IpxRoutep)
  394. {
  395. RTM_IPX_ROUTE RtmRoute;
  396. DWORD EnumFlags;
  397. DWORD rc;
  398. switch(RoutingTable) {
  399. case IPX_DEST_TABLE:
  400. // get the first route in the best routes table
  401. EnumFlags = RTM_ONLY_BEST_ROUTES | RTM_INCLUDE_DISABLED_ROUTES;
  402. break;
  403. case IPX_STATIC_ROUTE_TABLE:
  404. // get the first route in the static routes table for this
  405. // interface
  406. EnumFlags = RTM_ONLY_THIS_INTERFACE | RTM_ONLY_THIS_PROTOCOL | RTM_INCLUDE_DISABLED_ROUTES;
  407. RtmRoute.R_Interface = IpxRoutep->InterfaceIndex;
  408. RtmRoute.R_Protocol = IPX_PROTOCOL_STATIC;
  409. break;
  410. default:
  411. SS_ASSERT(FALSE);
  412. return ERROR_INVALID_PARAMETER;
  413. break;
  414. }
  415. rc = RtmGetFirstRoute(
  416. RTM_PROTOCOL_FAMILY_IPX,
  417. EnumFlags,
  418. &RtmRoute);
  419. RtmToIpxRoute(IpxRoutep, &RtmRoute);
  420. return rc;
  421. }
  422. DWORD
  423. GetNextRoute(ULONG RoutingTable,
  424. PIPX_ROUTE IpxRoutep)
  425. {
  426. RTM_IPX_ROUTE RtmRoute;
  427. DWORD EnumFlags;
  428. DWORD rc;
  429. ZeroMemory(&RtmRoute, sizeof(RtmRoute));
  430. GETLONG2ULONG(&RtmRoute.R_Network, IpxRoutep->Network);
  431. switch(RoutingTable) {
  432. case IPX_DEST_TABLE:
  433. // get next route in the best routes table
  434. EnumFlags = RTM_ONLY_BEST_ROUTES | RTM_INCLUDE_DISABLED_ROUTES;
  435. break;
  436. case IPX_STATIC_ROUTE_TABLE:
  437. // get next route in the static routes table for this interface
  438. EnumFlags = RTM_ONLY_THIS_INTERFACE | RTM_ONLY_THIS_PROTOCOL | RTM_INCLUDE_DISABLED_ROUTES;
  439. RtmRoute.R_Interface = (IpxRoutep->InterfaceIndex);
  440. RtmRoute.R_Protocol = IPX_PROTOCOL_STATIC;
  441. memcpy(RtmRoute.R_NextHopMacAddress, bcastnode, 6);
  442. break;
  443. default:
  444. SS_ASSERT(FALSE);
  445. return ERROR_INVALID_PARAMETER;
  446. break;
  447. }
  448. rc = RtmGetNextRoute(
  449. RTM_PROTOCOL_FAMILY_IPX,
  450. EnumFlags,
  451. &RtmRoute);
  452. RtmToIpxRoute(IpxRoutep, &RtmRoute);
  453. return rc;
  454. }
  455. //
  456. // Convert routes added by updating routes protocol to static routes
  457. //
  458. /*++
  459. Function: ConvertProtocolRoutesToStatic
  460. Descr:
  461. --*/
  462. VOID
  463. ConvertAllProtocolRoutesToStatic(ULONG InterfaceIndex,
  464. ULONG RoutingProtocolId)
  465. {
  466. RTM_IPX_ROUTE RtmRoute;
  467. DWORD EnumFlags;
  468. DWORD rc;
  469. EnumFlags = RTM_ONLY_THIS_INTERFACE | RTM_ONLY_THIS_PROTOCOL;
  470. memset(&RtmRoute, 0, sizeof(RTM_IPX_ROUTE));
  471. RtmRoute.R_Interface = InterfaceIndex;
  472. RtmRoute.R_Protocol = RoutingProtocolId;
  473. rc = RtmBlockConvertRoutesToStatic(
  474. RtmStaticHandle,
  475. EnumFlags,
  476. &RtmRoute);
  477. return;
  478. }
  479. VOID
  480. DisableStaticRoutes(ULONG InterfaceIndex)
  481. {
  482. RTM_IPX_ROUTE RtmRoute;
  483. DWORD EnumFlags;
  484. DWORD rc;
  485. EnumFlags = RTM_ONLY_THIS_INTERFACE;
  486. memset(&RtmRoute, 0, sizeof(RTM_IPX_ROUTE));
  487. RtmRoute.R_Interface = InterfaceIndex;
  488. RtmRoute.R_Protocol = IPX_PROTOCOL_STATIC;
  489. rc = RtmBlockDisableRoutes(
  490. RtmStaticHandle,
  491. EnumFlags,
  492. &RtmRoute);
  493. return;
  494. }
  495. VOID
  496. DisableStaticRoute(ULONG InterfaceIndex, PUCHAR Network)
  497. {
  498. RTM_IPX_ROUTE RtmRoute;
  499. DWORD EnumFlags;
  500. DWORD rc;
  501. EnumFlags = RTM_ONLY_THIS_INTERFACE|RTM_ONLY_THIS_NETWORK;
  502. memset(&RtmRoute, 0, sizeof(RTM_IPX_ROUTE));
  503. RtmRoute.R_Interface = InterfaceIndex;
  504. RtmRoute.R_Protocol = IPX_PROTOCOL_STATIC;
  505. GETLONG2ULONG(&RtmRoute.R_Network, Network);
  506. rc = RtmBlockDisableRoutes(
  507. RtmStaticHandle,
  508. EnumFlags,
  509. &RtmRoute);
  510. return;
  511. }
  512. VOID
  513. EnableStaticRoutes(ULONG InterfaceIndex)
  514. {
  515. RTM_IPX_ROUTE RtmRoute;
  516. DWORD EnumFlags;
  517. DWORD rc;
  518. EnumFlags = RTM_ONLY_THIS_INTERFACE;
  519. memset(&RtmRoute, 0, sizeof(RTM_IPX_ROUTE));
  520. RtmRoute.R_Interface = InterfaceIndex;
  521. RtmRoute.R_Protocol = IPX_PROTOCOL_STATIC;
  522. rc = RtmBlockReenableRoutes(
  523. RtmStaticHandle,
  524. EnumFlags,
  525. &RtmRoute);
  526. return;
  527. }
  528. /*++
  529. Function: GetStaticRoutesCount
  530. Descr: returns the number of static routes associated with this if
  531. --*/
  532. DWORD
  533. GetStaticRoutesCount(ULONG InterfaceIndex)
  534. {
  535. HANDLE EnumHandle;
  536. DWORD rc, Count = 0;
  537. IPX_STATIC_ROUTE_INFO StaticRtInfo;
  538. EnumHandle = CreateStaticRoutesEnumHandle(InterfaceIndex);
  539. if(EnumHandle != NULL) {
  540. while(GetNextStaticRoute(EnumHandle, &StaticRtInfo) == NO_ERROR) {
  541. Count++;
  542. }
  543. CloseStaticRoutesEnumHandle(EnumHandle);
  544. }
  545. return Count;
  546. }
  547. INT
  548. NetNumCmpFunc(PDWORD Net1,
  549. PDWORD Net2)
  550. {
  551. if(*Net1 > *Net2) {
  552. return 1;
  553. }
  554. else
  555. {
  556. if(*Net1 == *Net2) {
  557. return 0;
  558. }
  559. else
  560. {
  561. return -1;
  562. }
  563. }
  564. }
  565. INT
  566. NextHopAddrCmpFunc(PRTM_IPX_ROUTE Route1p,
  567. PRTM_IPX_ROUTE Route2p)
  568. {
  569. return ( memcmp(Route1p->R_NextHopMacAddress,
  570. Route2p->R_NextHopMacAddress,
  571. 6)
  572. );
  573. }
  574. BOOL
  575. FamSpecDataCmpFunc(PRTM_IPX_ROUTE Route1p,
  576. PRTM_IPX_ROUTE Route2p)
  577. {
  578. if((Route1p->R_Flags == Route2p->R_Flags) &&
  579. (Route1p->R_TickCount == Route2p->R_TickCount) &&
  580. (Route1p->R_HopCount == Route2p->R_HopCount)) {
  581. return TRUE;
  582. }
  583. else
  584. {
  585. return FALSE;
  586. }
  587. }
  588. INT
  589. NetNumHashFunc(PDWORD Net)
  590. {
  591. return (*Net % RoutingTableHashSize);
  592. }
  593. INT
  594. RouteMetricCmpFunc(PRTM_IPX_ROUTE Route1p,
  595. PRTM_IPX_ROUTE Route2p)
  596. {
  597. // if either route has 16 hops, it is the worst, no matter how many ticks
  598. if((Route1p->R_HopCount == 16) && (Route2p->R_HopCount == 16)) {
  599. return 0;
  600. }
  601. if(Route1p->R_HopCount == 16) {
  602. return 1;
  603. }
  604. if(Route2p->R_HopCount == 16) {
  605. return -1;
  606. }
  607. // shortest number of ticks is the best route
  608. if(Route1p->R_TickCount < Route2p->R_TickCount) {
  609. return -1;
  610. }
  611. if(Route1p->R_TickCount > Route2p->R_TickCount) {
  612. return 1;
  613. }
  614. // if two routes exist with equal tick count values, the one with
  615. // the least hops should be used
  616. if(Route1p->R_HopCount < Route2p->R_HopCount) {
  617. return -1;
  618. }
  619. if(Route1p->R_HopCount > Route2p->R_HopCount) {
  620. return 1;
  621. }
  622. return 0;
  623. }
  624. DWORD
  625. RouteValidateFunc(PRTM_IPX_ROUTE Routep)
  626. {
  627. return NO_ERROR;
  628. }
  629. /*++
  630. Function: tickcount
  631. Descr: gets nr of ticks to send a 576 bytes packet over this link
  632. Argument: link speed as a multiple of 100 bps
  633. --*/
  634. USHORT
  635. tickcount(UINT linkspeed)
  636. {
  637. USHORT tc;
  638. if(linkspeed == 0) {
  639. return 1;
  640. }
  641. if(linkspeed >= 10000) {
  642. // link speed >= 1M bps
  643. return 1;
  644. }
  645. else
  646. {
  647. // compute the necessary time to send a 576 bytes packet over this
  648. // line and express it as nr of ticks.
  649. // One tick = 55ms
  650. // time in ms to send 576 bytes (assuming 10 bits/byte for serial line)
  651. tc = 57600 / linkspeed;
  652. // in ticks
  653. tc = tc / 55 + 1;
  654. return tc;
  655. }
  656. }