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.

922 lines
26 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. rtrmgr.c
  5. Abstract:
  6. The major router management functions
  7. Author:
  8. Stefan Solomon 03/22/1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. // *********** Local Variables ***********
  14. HINSTANCE IpxCpModuleInstance;
  15. ULONG WorkerWaitTimeout;
  16. LPVOID RouterGlobalInfop;
  17. ULONG RouterGlobalInfoSize;
  18. TCHAR ModuleName[MAX_PATH+1];
  19. HINSTANCE hModuleReference;
  20. VOID
  21. RoutesUpdateNotification(VOID);
  22. VOID
  23. ServicesUpdateNotification(VOID);
  24. VOID
  25. RouterStopNotification(VOID);
  26. VOID
  27. RoutingProtocolsNotification(VOID);
  28. DWORD
  29. GetRegistryParameters(VOID);
  30. typedef VOID (*EVENTHANDLER)(VOID);
  31. EVENTHANDLER evhdlr[MAX_EVENTS] =
  32. {
  33. AdapterNotification,
  34. ForwarderNotification,
  35. RoutingProtocolsNotification,
  36. RouterStopNotification
  37. };
  38. DWORD
  39. StopRouter(VOID);
  40. DWORD
  41. RouterBootComplete( VOID );
  42. VOID
  43. RouterManagerWorker(VOID);
  44. DWORD
  45. GetGlobalInfo(OUT LPVOID GlobalInfop,
  46. IN OUT LPDWORD GlobalInfoSizep);
  47. // These prototypes allow us to specify when ipxcp will be initialized
  48. DWORD InitializeIpxCp (HINSTANCE hInstDll);
  49. DWORD CleanupIpxCp (HINSTANCE hInstDll);
  50. BOOL WINAPI
  51. IpxRtrMgrDllEntry(HINSTANCE hInstDll,
  52. DWORD fdwReason,
  53. LPVOID pReserved)
  54. {
  55. switch (fdwReason)
  56. {
  57. case DLL_PROCESS_ATTACH:
  58. GetModuleFileName (hInstDll, ModuleName,
  59. sizeof (ModuleName)/sizeof (ModuleName[0]));
  60. SS_DBGINITIALIZE;
  61. StartTracing();
  62. break;
  63. case DLL_PROCESS_DETACH:
  64. StopTracing();
  65. // Close the database mutex
  66. DeleteCriticalSection (&DatabaseLock);
  67. break;
  68. default:
  69. break;
  70. }
  71. return TRUE;
  72. }
  73. const static WCHAR pszIpxStackService[] = L"NwlnkIpx";
  74. //
  75. // Verifies that the ipx stack is started and attempts to start the stack
  76. // if not.
  77. //
  78. DWORD VerifyOrStartIpxStack() {
  79. SC_HANDLE hSC = NULL, hStack = NULL;
  80. SERVICE_STATUS Status;
  81. DWORD dwErr;
  82. Trace(INIT_TRACE, "VerifyOrStartIpxStack: entered.");
  83. __try {
  84. // Get a handle to the service controller
  85. if ((hSC = OpenSCManager (NULL, NULL, GENERIC_READ | GENERIC_EXECUTE)) == NULL)
  86. return GetLastError();
  87. // Get a handle to the ipx stack service
  88. hStack = OpenServiceW (hSC,
  89. pszIpxStackService,
  90. SERVICE_START | SERVICE_QUERY_STATUS);
  91. if (!hStack)
  92. return GetLastError();
  93. // Find out if the service is running
  94. if (QueryServiceStatus (hStack, &Status) == 0)
  95. return GetLastError();
  96. // See if the service is running
  97. if (Status.dwCurrentState != SERVICE_RUNNING) {
  98. // If it's stopped, start it
  99. if (Status.dwCurrentState == SERVICE_STOPPED) {
  100. if (StartService (hStack, 0, NULL) == 0)
  101. return GetLastError();
  102. // Warn that the stack has been started
  103. IF_LOG (EVENTLOG_WARNING_TYPE) {
  104. RouterLogErrorDataW (RMEventLogHdl,
  105. ROUTERLOG_IPX_WRN_STACK_STARTED,
  106. 0, NULL, 0, NULL);
  107. }
  108. Trace(INIT_TRACE, "VerifyOrStartIpxStack: Starting ipx stack...");
  109. // Make sure that the service started. StartService is not supposed
  110. // to return until the driver is started.
  111. if (QueryServiceStatus (hStack, &Status) == 0)
  112. return GetLastError();
  113. if (Status.dwCurrentState != SERVICE_RUNNING)
  114. return ERROR_CAN_NOT_COMPLETE;
  115. }
  116. // If it's not stopped, don't worry about it.
  117. else
  118. return NO_ERROR;
  119. }
  120. }
  121. __finally {
  122. if (hSC)
  123. CloseServiceHandle (hSC);
  124. if (hStack)
  125. CloseServiceHandle (hStack);
  126. }
  127. return NO_ERROR;
  128. }
  129. /*++
  130. Function: StartRouter
  131. Descr: Initializes the router manager database of interfaces and
  132. adapters, starts the other IPX router modules, creates the
  133. IPX router manager worker thread.
  134. --*/
  135. DWORD
  136. StartRouter(PDIM_ROUTER_INTERFACE rifp,
  137. BOOL fLANModeOnly,
  138. LPVOID GlobalInfop)
  139. {
  140. HANDLE threadhandle;
  141. DWORD threadid, rc;
  142. int i;
  143. BOOL ThisMachineOnly, bInternalNetNumOk;
  144. IPXCP_INTERFACE IpxcpInterface;
  145. PIPX_GLOBAL_INFO IpxGlobalInfop;
  146. PIPX_INFO_BLOCK_HEADER globalhp;
  147. // These flags get set to true when their corrosponding components
  148. // get started. They are used to properly clean up.
  149. BOOL bEventsCreated = FALSE;
  150. BOOL bRoutTableCreated = FALSE;
  151. BOOL bRtmStaticObtained = FALSE;
  152. BOOL bRtmLocalObtained = FALSE;
  153. BOOL bFwdStarted = FALSE;
  154. BOOL bAdpManStarted = FALSE;
  155. BOOL bProtsStarted = FALSE;
  156. BOOL bGlobalRouteCreated = FALSE;
  157. BOOL bIpxcpStarted = FALSE;
  158. BOOL bIpxcpInitted = FALSE;
  159. BOOL bWorkerThreadCreated = FALSE;
  160. // Initialize
  161. Trace(INIT_TRACE, "StartRouter: Entered\n");
  162. RouterOperState = OPER_STATE_DOWN;
  163. // [pmay]
  164. // We need to make sure that the stack is started before westart.
  165. if (VerifyOrStartIpxStack() != NO_ERROR) {
  166. IF_LOG (EVENTLOG_ERROR_TYPE) {
  167. RouterLogErrorDataW (RMEventLogHdl,
  168. ROUTERLOG_IPX_STACK_DISABLED,
  169. 0, NULL, 0, NULL);
  170. }
  171. Trace(INIT_TRACE, "StartRouter: Unable to start ipx stack.");
  172. return ERROR_SERVICE_DEPENDENCY_FAIL;
  173. }
  174. // [pmay]
  175. // We use this scheme to automatically select the internal network
  176. // number of the machine we're running on. If the net number is configured
  177. // as zero, this function will automatically select a random net num and
  178. // verify it's uniqueness on the net that this machine is attached to.
  179. if (AutoValidateInternalNetNum(&bInternalNetNumOk, INIT_TRACE) == NO_ERROR) {
  180. if (!bInternalNetNumOk) {
  181. if (PnpAutoSelectInternalNetNumber(INIT_TRACE) != NO_ERROR) {
  182. IF_LOG (EVENTLOG_ERROR_TYPE) {
  183. RouterLogErrorDataW (RMEventLogHdl,
  184. ROUTERLOG_IPX_AUTO_NETNUM_FAILURE,
  185. 0, NULL, 0, NULL);
  186. }
  187. Trace(INIT_TRACE, "StartRouter: Auto selection of net number failed.");
  188. return ERROR_CAN_NOT_COMPLETE;
  189. }
  190. }
  191. }
  192. // This try block will be used to automatically cleanup in the case that
  193. // something doesn't start right
  194. __try {
  195. // Make sure the parameters are ok
  196. if(GlobalInfop == NULL) {
  197. IF_LOG (EVENTLOG_ERROR_TYPE) {
  198. RouterLogErrorDataW (RMEventLogHdl,
  199. ROUTERLOG_IPX_BAD_GLOBAL_CONFIG,
  200. 0, NULL, 0, NULL);
  201. }
  202. Trace(INIT_TRACE, "StartRouter: invalid global info\n");
  203. return ERROR_CAN_NOT_COMPLETE;
  204. }
  205. // Read config from registry
  206. GetRegistryParameters();
  207. globalhp = (PIPX_INFO_BLOCK_HEADER)GlobalInfop;
  208. RouterGlobalInfop = GlobalAlloc(GPTR, globalhp->Size);
  209. RouterGlobalInfoSize = globalhp->Size;
  210. memcpy(RouterGlobalInfop, GlobalInfop, RouterGlobalInfoSize);
  211. IpxGlobalInfop = (PIPX_GLOBAL_INFO)GetInfoEntry((PIPX_INFO_BLOCK_HEADER)GlobalInfop,
  212. IPX_GLOBAL_INFO_TYPE);
  213. // Initialize the hash table size
  214. if(IpxGlobalInfop != NULL) {
  215. switch (IpxGlobalInfop->RoutingTableHashSize) {
  216. case IPX_SMALL_ROUTING_TABLE_HASH_SIZE:
  217. case IPX_MEDIUM_ROUTING_TABLE_HASH_SIZE:
  218. case IPX_LARGE_ROUTING_TABLE_HASH_SIZE:
  219. RoutingTableHashSize = IpxGlobalInfop->RoutingTableHashSize;
  220. Trace(INIT_TRACE, "Setting routing table hash size to %ld\n",
  221. RoutingTableHashSize);
  222. break;
  223. default:
  224. Trace(INIT_TRACE, "Using default routing table hash size of %ld\n",
  225. RoutingTableHashSize);
  226. break;
  227. }
  228. RMEventLogMask = IpxGlobalInfop->EventLogMask;
  229. }
  230. // Create router database mutex
  231. try {
  232. InitializeCriticalSection (&DatabaseLock);
  233. }
  234. except (EXCEPTION_EXECUTE_HANDLER) {
  235. // !!! cannot create database mutex !!!
  236. Trace(INIT_TRACE, "InitializeRouter: cannot initialize database lock.\n");
  237. return(ERROR_CAN_NOT_COMPLETE);
  238. }
  239. // Create the adapter and forwarder notification events
  240. for (i=0; i < MAX_EVENTS; i++) {
  241. g_hEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
  242. if (g_hEvents[i] == NULL) {
  243. // !!! Log a problem with event creation
  244. return (ERROR_CAN_NOT_COMPLETE);
  245. }
  246. }
  247. bEventsCreated = TRUE;
  248. // Initialize the interfaces and adapters databases
  249. InitIfDB();
  250. InitAdptDB();
  251. // create the IPX routing table
  252. if(CreateRouteTable() != NO_ERROR) {
  253. Trace(INIT_TRACE, "InitializeRouter: cannot create route table\n");
  254. return(ERROR_CAN_NOT_COMPLETE);
  255. }
  256. bRoutTableCreated = TRUE;
  257. // Get a handle to use later when calling into rtm for static routes
  258. if((RtmStaticHandle = RtmRegisterClient(RTM_PROTOCOL_FAMILY_IPX,
  259. IPX_PROTOCOL_STATIC,
  260. NULL, // not interested in change notif
  261. 0)) == NULL)
  262. {
  263. Trace(INIT_TRACE, "InitializeRouter: cannot register RTM client\n");
  264. return(ERROR_CAN_NOT_COMPLETE);
  265. }
  266. bRtmStaticObtained = TRUE;
  267. // Get a handle to use when calling into the rtm later for local routes
  268. if((RtmLocalHandle = RtmRegisterClient(RTM_PROTOCOL_FAMILY_IPX,
  269. IPX_PROTOCOL_LOCAL,
  270. NULL, // not interested in change notif
  271. 0)) == NULL)
  272. {
  273. Trace(INIT_TRACE, "InitializeRouter: cannot register RTM client\n");
  274. return(ERROR_CAN_NOT_COMPLETE);
  275. }
  276. bRtmLocalObtained = TRUE;
  277. // tell the IPXCP that router has started so we can accept calls from it
  278. LanOnlyMode = fLANModeOnly;
  279. // Bind with ipxcp if we are a wan router
  280. if(!LanOnlyMode) {
  281. // Load ipxcp
  282. IpxCpModuleInstance = LoadLibrary(IPXCPDLLNAME);
  283. if(IpxCpModuleInstance == NULL) {
  284. IF_LOG (EVENTLOG_ERROR_TYPE)
  285. RouterLogErrorA (RMEventLogHdl, ROUTERLOG_IPX_CANT_LOAD_IPXCP,0, NULL, GetLastError ());
  286. Trace(INIT_TRACE, "StartRouter: cannot load IPXCP DLL\n");
  287. return ERROR_CAN_NOT_COMPLETE;
  288. }
  289. // Initialize it
  290. if ((rc = InitializeIpxCp (IpxCpModuleInstance)) != NO_ERROR) {
  291. Trace(INIT_TRACE, "StartRouter: cannot get IpxcpInit Entry Point");
  292. return rc;
  293. }
  294. bIpxcpInitted = TRUE;
  295. // Bind to it
  296. if(!(IpxcpBind = (PIPXCP_BIND)GetProcAddress(IpxCpModuleInstance, IPXCP_BIND_ENTRY_POINT_STRING))) {
  297. Trace(INIT_TRACE, "StartRouter: cannot get IpxcpBind Entry Point\n");
  298. return ERROR_CAN_NOT_COMPLETE;
  299. }
  300. IpxcpInterface.RmCreateGlobalRoute = RmCreateGlobalRoute;
  301. IpxcpInterface.RmAddLocalWkstaDialoutInterface = RmAddLocalWkstaDialoutInterface;
  302. IpxcpInterface.RmDeleteLocalWkstaDialoutInterface = RmDeleteLocalWkstaDialoutInterface;
  303. IpxcpInterface.RmGetIpxwanInterfaceConfig = RmGetIpxwanInterfaceConfig;
  304. IpxcpInterface.RmIsRoute = RmIsRoute;
  305. IpxcpInterface.RmGetInternalNetNumber = RmGetInternalNetNumber;
  306. IpxcpInterface.RmUpdateIpxcpConfig = RmUpdateIpxcpConfig;
  307. (*IpxcpBind)(&IpxcpInterface);
  308. ThisMachineOnly = IpxcpInterface.Params.ThisMachineOnly;
  309. WanNetDatabaseInitialized = IpxcpInterface.Params.WanNetDatabaseInitialized;
  310. EnableGlobalWanNet = IpxcpInterface.Params.EnableGlobalWanNet;
  311. memcpy(GlobalWanNet, IpxcpInterface.Params.GlobalWanNet, 4);
  312. IpxcpRouterStarted = IpxcpInterface.IpxcpRouterStarted;
  313. IpxcpRouterStopped = IpxcpInterface.IpxcpRouterStopped;
  314. }
  315. // check that the forwarder module exists and is ready to run
  316. if(FwStart(RoutingTableHashSize, ThisMachineOnly)) {
  317. // got a problem initializing the forwarder
  318. IF_LOG (EVENTLOG_ERROR_TYPE) {
  319. RouterLogErrorDataW (RMEventLogHdl, ROUTERLOG_IPX_CANT_LOAD_FORWARDER,0, NULL, 0, NULL);
  320. }
  321. // !!! log an error !!!
  322. Trace(INIT_TRACE, "InitializeRouter: cannot initialize the Forwarder\n");
  323. return(ERROR_CAN_NOT_COMPLETE);
  324. }
  325. bFwdStarted = TRUE;
  326. // start getting the adapter configuration from the IPX stack
  327. // this will start adding adapters to the forwader
  328. if(StartAdapterManager()) {
  329. Trace(INIT_TRACE, "InitializeRouter: cannot get the adapters configuration\n");
  330. return (ERROR_CAN_NOT_COMPLETE);
  331. }
  332. bAdpManStarted = TRUE;
  333. // set the timeout wait for the router worker thread
  334. WorkerWaitTimeout = INFINITE;
  335. // start the routing protocols (rip/sap or nlsp)
  336. if(StartRoutingProtocols(GlobalInfop,g_hEvents[ROUTING_PROTOCOLS_NOTIFICATION_EVENT])) {
  337. Trace(INIT_TRACE, "InitializeRouter: cannot initialize routing protocols\n");
  338. return(ERROR_CAN_NOT_COMPLETE);
  339. }
  340. bProtsStarted = TRUE;
  341. // send an IOCTl to the Forwarder to notify the router manager of connection
  342. // requests
  343. ConnReqOverlapped.hEvent = g_hEvents[FORWARDER_NOTIFICATION_EVENT];
  344. ConnRequest = (PFW_DIAL_REQUEST)GlobalAlloc (GPTR, DIAL_REQUEST_BUFFER_SIZE);
  345. if (ConnRequest==NULL) {
  346. Trace(INIT_TRACE, "InitializeRouter: Cannot allocate Connecttion Request buffer.\n");
  347. return(ERROR_CAN_NOT_COMPLETE);
  348. }
  349. rc = FwNotifyConnectionRequest(ConnRequest,DIAL_REQUEST_BUFFER_SIZE,&ConnReqOverlapped);
  350. if(rc != NO_ERROR) {
  351. Trace(INIT_TRACE, "InitializeRouter: cannot post FwNotifyConnectionRequest IOCtl\n");
  352. return(ERROR_CAN_NOT_COMPLETE);
  353. }
  354. // exchange function table with the DDM
  355. // first, fill in with our entry points
  356. rifp->dwProtocolId = PID_IPX;
  357. rifp->InterfaceConnected = InterfaceConnected;
  358. rifp->StopRouter = StopRouter;
  359. rifp->RouterBootComplete = RouterBootComplete;
  360. rifp->AddInterface = AddInterface;
  361. rifp->DeleteInterface = DeleteInterface;
  362. rifp->GetInterfaceInfo = GetInterfaceInfo;
  363. rifp->SetInterfaceInfo = SetInterfaceInfo;
  364. rifp->InterfaceNotReachable = InterfaceNotReachable;
  365. rifp->InterfaceReachable = InterfaceReachable;
  366. rifp->UpdateRoutes = RequestUpdate;
  367. rifp->GetUpdateRoutesResult = GetDIMUpdateResult;
  368. rifp->SetGlobalInfo = SetGlobalInfo;
  369. rifp->GetGlobalInfo = GetGlobalInfo;
  370. rifp->MIBEntryCreate = MibCreate;
  371. rifp->MIBEntryDelete = MibDelete;
  372. rifp->MIBEntrySet = MibSet;
  373. rifp->MIBEntryGet = MibGet;
  374. rifp->MIBEntryGetFirst = MibGetFirst;
  375. rifp->MIBEntryGetNext = MibGetNext;
  376. // get its entry points
  377. ConnectInterface = rifp->ConnectInterface;
  378. DisconnectInterface = rifp->DisconnectInterface;
  379. SaveInterfaceInfo = rifp->SaveInterfaceInfo;
  380. RestoreInterfaceInfo = rifp->RestoreInterfaceInfo;
  381. RouterStopped = rifp->RouterStopped;
  382. InterfaceEnabled = rifp->InterfaceEnabled;
  383. // Tell ipxcp that we have started if appropriate
  384. if(!LanOnlyMode) {
  385. if(WanNetDatabaseInitialized &&EnableGlobalWanNet) {
  386. CreateGlobalRoute(GlobalWanNet);
  387. bGlobalRouteCreated = TRUE;
  388. }
  389. (*IpxcpRouterStarted)();
  390. bIpxcpStarted = TRUE;
  391. }
  392. // start the Router Manager Worker thread
  393. if ((threadhandle = CreateThread(NULL,
  394. 0,
  395. (LPTHREAD_START_ROUTINE) RouterManagerWorker,
  396. NULL,
  397. 0,
  398. &threadid)) == NULL)
  399. {
  400. // !!! log error cannot create the worker thread !!!
  401. return (ERROR_CAN_NOT_COMPLETE);
  402. }
  403. bWorkerThreadCreated = TRUE;
  404. // all started -> the router is ready to accept interface management
  405. // apis from DDM, SNMP agent and Sysmon.
  406. RouterOperState = OPER_STATE_UP;
  407. }
  408. // Whenever the above try block exists, the code in this finally block will
  409. // be executed. If at that time, the router state is not up, then you know
  410. // an error condition exists. This is the time to cleanup in this case.
  411. __finally {
  412. if (RouterOperState == OPER_STATE_DOWN) {
  413. if (bWorkerThreadCreated)
  414. CloseHandle(threadhandle);
  415. if (bIpxcpStarted)
  416. (*IpxcpRouterStopped)();
  417. if (bIpxcpInitted)
  418. CleanupIpxCp (IpxCpModuleInstance);
  419. if (bGlobalRouteCreated)
  420. DeleteGlobalRoute(GlobalWanNet);
  421. if (bProtsStarted)
  422. StopRoutingProtocols();
  423. if (bAdpManStarted)
  424. StopAdapterManager();
  425. if (bFwdStarted)
  426. FwStop();
  427. if (bRtmLocalObtained)
  428. RtmDeregisterClient (RtmLocalHandle);
  429. if (bRtmStaticObtained)
  430. RtmDeregisterClient (RtmStaticHandle);
  431. if (bRoutTableCreated)
  432. DeleteRouteTable();
  433. if (bEventsCreated) {
  434. for(i=0; i<MAX_EVENTS; i++)
  435. CloseHandle(g_hEvents[i]);
  436. }
  437. }
  438. }
  439. return NO_ERROR;
  440. }
  441. /*++
  442. Function: StopRouter
  443. Descr: The router stops its routing functions and unloads, i.e:
  444. The Forwarder stops forwarding
  445. The Rip module stops and advertises it has stopped
  446. All dynamic routes are deleted and advertised as not available
  447. All local and static routes are advertised as not available
  448. The Sap module stops and advertises it has stopped
  449. All dynamic services are deleted and advertised as not available
  450. All local and static services are advertised as not available
  451. --*/
  452. DWORD
  453. StopRouter(VOID)
  454. {
  455. Trace(INIT_TRACE, "StopRouter: Entered\n");
  456. SetEvent(g_hEvents[STOP_NOTIFICATION_EVENT]);
  457. return PENDING;
  458. }
  459. /*++
  460. Function: RouterBootComplete
  461. Descr: Called by DIM when it has completed adding all the interfaces from
  462. the registry.
  463. --*/
  464. DWORD
  465. RouterBootComplete( VOID )
  466. {
  467. Trace(INIT_TRACE, "RouterBootComplete: Entered\n");
  468. return( NO_ERROR );
  469. }
  470. VOID
  471. RouterStopNotification(VOID)
  472. {
  473. PLIST_ENTRY lep;
  474. PICB icbp;
  475. Trace(INIT_TRACE, "RouterStopNotification: Entered\n");
  476. // We set the RouterOperState to stopping in critical section to make sure
  477. // that no DDM call is executing. All DDM calls require this crit sec for
  478. // starting execution and will check the router state before doing anything
  479. ACQUIRE_DATABASE_LOCK;
  480. RouterOperState = OPER_STATE_STOPPING;
  481. RELEASE_DATABASE_LOCK;
  482. // we have to make sure no SNMP or Sysmon call is active. We use a ref
  483. // counter.
  484. // we also make sure that no work item is pending
  485. for(;;)
  486. {
  487. ACQUIRE_DATABASE_LOCK;
  488. if((MibRefCounter == 0) && (WorkItemsPendingCounter == 0)) {
  489. RELEASE_DATABASE_LOCK;
  490. break;
  491. }
  492. RELEASE_DATABASE_LOCK;
  493. Sleep(1000);
  494. }
  495. // delete all static routes and services and all local routes
  496. ACQUIRE_DATABASE_LOCK;
  497. lep = IndexIfList.Flink;
  498. while(lep != &IndexIfList)
  499. {
  500. icbp = CONTAINING_RECORD(lep, ICB, IndexListLinkage);
  501. DeleteAllStaticRoutes(icbp->InterfaceIndex);
  502. DeleteAllStaticServices(icbp->InterfaceIndex);
  503. // check if oper state UP and admin enabled
  504. if((icbp->AdminState == ADMIN_STATE_ENABLED) &&
  505. (icbp->OperState == OPER_STATE_UP)) {
  506. if(memcmp(icbp->acbp->AdapterInfo.Network, nullnet, 4)) {
  507. DeleteLocalRoute(icbp);
  508. }
  509. }
  510. lep = lep->Flink;
  511. }
  512. RELEASE_DATABASE_LOCK;
  513. // tell ipxcp that the router is stopping so that it will end calling us
  514. if(!LanOnlyMode) {
  515. (*IpxcpRouterStopped)();
  516. if(EnableGlobalWanNet) {
  517. DeleteGlobalRoute(GlobalWanNet);
  518. }
  519. }
  520. // initiate the stopping of the routing protocols
  521. StopRoutingProtocols();
  522. return;
  523. }
  524. /*++
  525. Function: RouterManagerWorker
  526. Descr: the WORKER THREAD
  527. --*/
  528. VOID
  529. RouterManagerWorker(VOID)
  530. {
  531. DWORD rc;
  532. DWORD signaled_event;
  533. hModuleReference = LoadLibrary (ModuleName);
  534. while(TRUE)
  535. {
  536. rc = WaitForMultipleObjectsEx(
  537. MAX_EVENTS,
  538. g_hEvents,
  539. FALSE, // wait any
  540. INFINITE, // timeout
  541. TRUE // wait alertable, so we can run APCs
  542. );
  543. signaled_event = rc - WAIT_OBJECT_0;
  544. if(signaled_event < MAX_EVENTS) {
  545. // invoke the event handler
  546. (*evhdlr[signaled_event])();
  547. }
  548. }
  549. }
  550. VOID
  551. RoutingProtocolsNotification(VOID)
  552. {
  553. PLIST_ENTRY lep;
  554. PRPCB rpcbp;
  555. ROUTING_PROTOCOL_EVENTS RpEvent;
  556. MESSAGE RpMessage;
  557. int i;
  558. DWORD rc;
  559. BOOL RoutingProtocolStopped;
  560. Trace(INIT_TRACE, " RoutingProtocolsNotification: Entered\n");
  561. // for each routing protocol get the events and the messages associated
  562. // with each event
  563. lep = RoutingProtocolCBList.Flink;
  564. while(lep != &RoutingProtocolCBList) {
  565. rpcbp = CONTAINING_RECORD(lep, RPCB, RP_Linkage);
  566. lep = lep->Flink;
  567. RoutingProtocolStopped = FALSE;
  568. while((rc = (*rpcbp->RP_GetEventMessage)(&RpEvent, &RpMessage)) == NO_ERROR)
  569. {
  570. switch(RpEvent) {
  571. case ROUTER_STOPPED:
  572. Trace(INIT_TRACE, "RoutingProtocolNotification: Protocol %x has stopped\n",
  573. rpcbp->RP_ProtocolId);
  574. RoutingProtocolStopped = TRUE;
  575. // remove the routing protocol CB from the list and free it
  576. DestroyRoutingProtocolCB(rpcbp);
  577. // check if there are still routing protocols to wait for
  578. if(IsListEmpty(&RoutingProtocolCBList)) {
  579. //
  580. // All Routing Protocols stopped -> Stop the Router
  581. //
  582. // Close the Forwarder. This will complete the Forwarder pending
  583. // connect request IOCTl.
  584. FwStop();
  585. // set the current state
  586. RouterOperState = OPER_STATE_DOWN;
  587. // Close the IPX stack config port.
  588. StopAdapterManager();
  589. // Clean-up the database
  590. ACQUIRE_DATABASE_LOCK;
  591. // Remove all adapter control blocks
  592. DestroyAllAdapters();
  593. // Remove all interface control blocks
  594. DestroyAllInterfaces();
  595. RELEASE_DATABASE_LOCK;
  596. // Deregister as RTM clients - this will delete all static and
  597. // local routes
  598. RtmDeregisterClient(RtmStaticHandle);
  599. RtmDeregisterClient(RtmLocalHandle);
  600. DeleteRouteTable();
  601. // Close notification events
  602. for(i=0; i<MAX_EVENTS; i++)
  603. {
  604. CloseHandle(g_hEvents[i]);
  605. }
  606. // get rid of global info
  607. GlobalFree(RouterGlobalInfop);
  608. // Call DDM to tell it we have stopped
  609. RouterStopped(PID_IPX, NO_ERROR);
  610. // Free IPXCP if loaded
  611. if (IpxCpModuleInstance!=NULL) {
  612. CleanupIpxCp (IpxCpModuleInstance);
  613. FreeLibrary(IpxCpModuleInstance);
  614. }
  615. FreeLibraryAndExitThread(hModuleReference, 0);
  616. }
  617. break;
  618. case UPDATE_COMPLETE:
  619. Trace(INIT_TRACE, "RoutingProtocolNotification: Protocol %x has completed update\n",
  620. rpcbp->RP_ProtocolId);
  621. UpdateCompleted(&RpMessage.UpdateCompleteMessage);
  622. break;
  623. default:
  624. Trace(INIT_TRACE, "RoutingProtocolNotification: Protocol %x signaled invalid event %d\n",
  625. rpcbp->RP_ProtocolId,
  626. RpEvent);
  627. break;
  628. }
  629. if(RoutingProtocolStopped) {
  630. break;
  631. }
  632. }
  633. }
  634. }
  635. DWORD
  636. SetGlobalInfo(IN LPVOID GlobalInfop)
  637. {
  638. DWORD rc;
  639. PIPX_INFO_BLOCK_HEADER globalhp;
  640. PIPX_GLOBAL_INFO IpxGlobalInfop;
  641. if(GlobalInfop == NULL) {
  642. return ERROR_CAN_NOT_COMPLETE;
  643. }
  644. GlobalFree(RouterGlobalInfop);
  645. globalhp = (PIPX_INFO_BLOCK_HEADER)GlobalInfop;
  646. RouterGlobalInfoSize = globalhp->Size;
  647. RouterGlobalInfop = GlobalAlloc(GPTR, RouterGlobalInfoSize);
  648. if(RouterGlobalInfop == NULL) {
  649. return ERROR_CAN_NOT_COMPLETE;
  650. }
  651. memcpy(RouterGlobalInfop, GlobalInfop, RouterGlobalInfoSize);
  652. IpxGlobalInfop = (PIPX_GLOBAL_INFO)GetInfoEntry((PIPX_INFO_BLOCK_HEADER)GlobalInfop,
  653. IPX_GLOBAL_INFO_TYPE);
  654. if(IpxGlobalInfop != NULL) {
  655. // Can only be set at startup
  656. // RoutingTableHashSize = IpxGlobalInfop->RoutingTableHashSize;
  657. RMEventLogMask = IpxGlobalInfop->EventLogMask;
  658. }
  659. rc = SetRoutingProtocolsGlobalInfo((PIPX_INFO_BLOCK_HEADER)GlobalInfop);
  660. return rc;
  661. }
  662. DWORD
  663. GetGlobalInfo(OUT LPVOID GlobalInfop,
  664. IN OUT LPDWORD GlobalInfoSizep)
  665. {
  666. if((GlobalInfop == NULL) || (*GlobalInfoSizep == 0)) {
  667. *GlobalInfoSizep = RouterGlobalInfoSize;
  668. return ERROR_INSUFFICIENT_BUFFER;
  669. }
  670. if(RouterGlobalInfoSize > *GlobalInfoSizep) {
  671. *GlobalInfoSizep = RouterGlobalInfoSize;
  672. return ERROR_INSUFFICIENT_BUFFER;
  673. }
  674. memcpy(GlobalInfop, RouterGlobalInfop, RouterGlobalInfoSize);
  675. *GlobalInfoSizep = RouterGlobalInfoSize;
  676. return NO_ERROR;
  677. }
  678. //***
  679. //
  680. // Function: GetRegistryParameters
  681. //
  682. // Descr: Reads the parameters from the registry and sets them
  683. //
  684. //***
  685. DWORD
  686. GetRegistryParameters(VOID)
  687. {
  688. NTSTATUS Status;
  689. PWSTR RouterManagerParametersPath = L"RemoteAccess\\RouterManagers\\IPX\\Parameters";
  690. RTL_QUERY_REGISTRY_TABLE paramTable[2]; // table size = nr of params + 1
  691. RtlZeroMemory(&paramTable[0], sizeof(paramTable));
  692. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  693. paramTable[0].Name = L"MaxRoutingTableSize";
  694. paramTable[0].EntryContext = &MaxRoutingTableSize;
  695. paramTable[0].DefaultType = REG_DWORD;
  696. paramTable[0].DefaultData = &MaxRoutingTableSize;
  697. paramTable[0].DefaultLength = sizeof(ULONG);
  698. Status = RtlQueryRegistryValues(
  699. RTL_REGISTRY_SERVICES,
  700. RouterManagerParametersPath,
  701. paramTable,
  702. NULL,
  703. NULL);
  704. return Status;
  705. }