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.

641 lines
20 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\ip\rtrmgr\worker.c
  5. Abstract:
  6. IP Router Manager worker thread code
  7. Revision History:
  8. Gurdeep Singh Pall 6/8/95 Created
  9. --*/
  10. #include "allinc.h"
  11. extern SOCKET McMiscSocket;
  12. //
  13. // From iphlpapi.h
  14. //
  15. DWORD
  16. NotifyRouteChangeEx(
  17. PHANDLE pHandle,
  18. LPOVERLAPPED pOverLapped,
  19. BOOL bExQueue
  20. );
  21. DWORD
  22. WINAPI
  23. EnableRouter(
  24. HANDLE* pHandle,
  25. OVERLAPPED* pOverlapped
  26. );
  27. DWORD
  28. WINAPI
  29. UnenableRouter(
  30. OVERLAPPED* pOverlapped,
  31. LPDWORD lpdwEnableCount OPTIONAL
  32. );
  33. DWORD
  34. WorkerThread (
  35. PVOID pGlobalInfo
  36. )
  37. {
  38. DWORD eventindex ; // index of event notified
  39. HANDLE workereventarray [NUMBER_OF_EVENTS] ; // event array
  40. PPROTO_CB protptr ;
  41. DWORD dwTimeOut, dwResult, dwByteCount, dwEnableCount;
  42. OVERLAPPED RouteChangeOverlapped, SetForwardingOverlapped;
  43. HANDLE hTemp;
  44. TraceEnter("WorkerThread");
  45. //
  46. // Prepare list of events that WaitForMultipleObjects will wait on
  47. //
  48. workereventarray[EVENT_DEMANDDIAL] = g_hDemandDialEvent;
  49. #ifdef KSL_IPINIP
  50. workereventarray[EVENT_IPINIP] = g_hIpInIpEvent;
  51. #endif //KSL_IPINIP
  52. workereventarray[EVENT_STOP_ROUTER] = g_hStopRouterEvent;
  53. workereventarray[EVENT_SET_FORWARDING] = g_hSetForwardingEvent;
  54. workereventarray[EVENT_FORWARDING_CHANGE] = g_hForwardingChangeEvent;
  55. workereventarray[EVENT_STACK_CHANGE] = g_hStackChangeEvent;
  56. workereventarray[EVENT_ROUTINGPROTOCOL] = g_hRoutingProtocolEvent ;
  57. workereventarray[EVENT_RTRDISCTIMER] = g_hRtrDiscTimer;
  58. workereventarray[EVENT_RTRDISCSOCKET] = g_hRtrDiscSocketEvent;
  59. workereventarray[EVENT_MCMISCSOCKET] = g_hMcMiscSocketEvent;
  60. workereventarray[EVENT_MZAPTIMER] = g_hMzapTimer;
  61. workereventarray[EVENT_MZAPSOCKET] = g_hMzapSocketEvent;
  62. workereventarray[EVENT_RASADVTIMER] = g_hRasAdvTimer;
  63. workereventarray[EVENT_MHBEAT] = g_hMHbeatSocketEvent;
  64. workereventarray[EVENT_MCAST_0] = g_hMcastEvents[0];
  65. workereventarray[EVENT_MCAST_1] = g_hMcastEvents[1];
  66. workereventarray[EVENT_MCAST_2] = g_hMcastEvents[2];
  67. workereventarray[EVENT_ROUTE_CHANGE_0] = g_hRouteChangeEvents[0];
  68. workereventarray[EVENT_ROUTE_CHANGE_1] = g_hRouteChangeEvents[1];
  69. workereventarray[EVENT_ROUTE_CHANGE_2] = g_hRouteChangeEvents[2];
  70. dwTimeOut = INFINITE;
  71. //
  72. // Do a setsockopt to listen for address changes.
  73. // This must be done in the thread that will wait for the notifications
  74. //
  75. dwResult = WSAIoctl(McMiscSocket,
  76. SIO_ADDRESS_LIST_CHANGE,
  77. NULL,
  78. 0,
  79. NULL,
  80. 0,
  81. &dwByteCount,
  82. NULL,
  83. NULL);
  84. if(dwResult is SOCKET_ERROR)
  85. {
  86. dwResult = WSAGetLastError();
  87. if((dwResult isnot WSAEWOULDBLOCK) and
  88. (dwResult isnot WSA_IO_PENDING) and
  89. (dwResult isnot NO_ERROR))
  90. {
  91. Trace1(ERR,
  92. "WorkerThread: Error %d from SIO_ADDRESS_LIST_CHANGE",
  93. dwResult);
  94. }
  95. }
  96. ZeroMemory(&SetForwardingOverlapped,
  97. sizeof(SetForwardingOverlapped));
  98. #if 1
  99. for (
  100. eventindex = 0;
  101. eventindex < NUM_ROUTE_CHANGE_IRPS;
  102. eventindex++
  103. )
  104. {
  105. PostIoctlForRouteChangeNotification(eventindex);
  106. }
  107. #else
  108. ZeroMemory(&RouteChangeOverlapped,
  109. sizeof(RouteChangeOverlapped));
  110. RouteChangeOverlapped.hEvent = g_hStackChangeEvent;
  111. hTemp = NULL;
  112. dwResult = NotifyRouteChangeEx(&hTemp,
  113. &RouteChangeOverlapped,
  114. TRUE);
  115. if((dwResult isnot NO_ERROR) and
  116. (dwResult isnot ERROR_IO_PENDING))
  117. {
  118. Trace1(ERR,
  119. "WorkerThread: Error %d from NotifyRouteChange",
  120. dwResult);
  121. }
  122. #endif
  123. __try
  124. {
  125. while(TRUE)
  126. {
  127. eventindex = WaitForMultipleObjectsEx(NUMBER_OF_EVENTS,
  128. workereventarray,
  129. FALSE,
  130. dwTimeOut,
  131. TRUE);
  132. switch(eventindex)
  133. {
  134. case WAIT_IO_COMPLETION:
  135. {
  136. continue ; // handle alertable wait case
  137. }
  138. case EVENT_DEMANDDIAL:
  139. {
  140. Trace0(DEMAND,
  141. "WorkerThread: Demand Dial event received");
  142. HandleDemandDialEvent();
  143. break ;
  144. }
  145. #ifdef KSL_IPINIP
  146. case EVENT_IPINIP:
  147. {
  148. Trace0(DEMAND,
  149. "WorkerThread: IpInIp event received");
  150. HandleIpInIpEvent();
  151. break ;
  152. }
  153. #endif //KSL_IPINIP
  154. case EVENT_STOP_ROUTER:
  155. case WAIT_TIMEOUT:
  156. {
  157. Trace0(GLOBAL,
  158. "WorkerThread: Stop router event received");
  159. // *** Exclusion Begin ***
  160. ENTER_READER(ICB_LIST);
  161. // *** Exclusion Begin ***
  162. ENTER_WRITER(PROTOCOL_CB_LIST);
  163. //
  164. // If all interfaces havent been deleted we switch to
  165. // polling mode where we get up every
  166. // INTERFACE_DELETE_POLL_TIME and check
  167. //
  168. if(!IsListEmpty(&ICBList))
  169. {
  170. //
  171. // Now wakeup every two second to check
  172. //
  173. dwTimeOut = INTERFACE_DELETE_POLL_TIME;
  174. EXIT_LOCK(PROTOCOL_CB_LIST);
  175. EXIT_LOCK(ICB_LIST);
  176. break ;
  177. }
  178. else
  179. {
  180. //
  181. // Get out of polling mode
  182. //
  183. dwTimeOut = INFINITE;
  184. }
  185. //
  186. // Since all interfaces are now gone, we can delete the
  187. // internal interface
  188. //
  189. if(g_pInternalInterfaceCb)
  190. {
  191. DeleteInternalInterface();
  192. }
  193. NotifyRoutingProtocolsToStop() ; // tells routing protocols to stop.
  194. //
  195. // Well interfaces have been deleted, so what about
  196. // protocols?
  197. //
  198. WaitForAPIsToExitBeforeStopping() ; // returns when it is safe to stop router
  199. if (AllRoutingProtocolsStopped())
  200. {
  201. //
  202. // This check is done here since all routing protocols
  203. // may have stopped synchronously, in which case
  204. // we can safely stop
  205. //
  206. EXIT_LOCK(PROTOCOL_CB_LIST);
  207. EXIT_LOCK(ICB_LIST);
  208. __leave;
  209. }
  210. //
  211. // All interfaces have been deleted but some protocol is
  212. // still running. We will get a EVENT_ROUTINGPROTOCOL
  213. // notification
  214. //
  215. EXIT_LOCK(PROTOCOL_CB_LIST);
  216. EXIT_LOCK(ICB_LIST);
  217. // make sure mrinfo/mtrace service is stopped
  218. StopMcMisc();
  219. if ( g_bEnableNetbtBcastFrowarding )
  220. {
  221. RestoreNetbtBcastForwardingMode();
  222. g_bEnableNetbtBcastFrowarding = FALSE;
  223. }
  224. break ;
  225. }
  226. case EVENT_SET_FORWARDING:
  227. {
  228. hTemp = NULL;
  229. EnterCriticalSection(&g_csFwdState);
  230. //
  231. // If our current state matches the user's request
  232. // just free the message and move on
  233. //
  234. if(g_bEnableFwdRequest is g_bFwdEnabled)
  235. {
  236. LeaveCriticalSection(&g_csFwdState);
  237. break;
  238. }
  239. SetForwardingOverlapped.hEvent = g_hForwardingChangeEvent;
  240. if(g_bEnableFwdRequest)
  241. {
  242. Trace0(GLOBAL,
  243. "WorkerThread: **--Enabling forwarding--**\n\n");
  244. dwResult = EnableRouter(&hTemp,
  245. &SetForwardingOverlapped);
  246. g_bFwdEnabled = TRUE;
  247. }
  248. else
  249. {
  250. Trace0(GLOBAL,
  251. "WorkerThread: **--Disabling forwarding--**\n\n");
  252. dwResult = UnenableRouter(&SetForwardingOverlapped,
  253. &dwEnableCount);
  254. g_bFwdEnabled = FALSE;
  255. }
  256. if((dwResult isnot NO_ERROR) and
  257. (dwResult isnot ERROR_IO_PENDING))
  258. {
  259. Trace1(ERR,
  260. "WorkerThread: Error %d from call",
  261. dwResult);
  262. }
  263. LeaveCriticalSection(&g_csFwdState);
  264. break;
  265. }
  266. case EVENT_FORWARDING_CHANGE:
  267. {
  268. Trace0(GLOBAL,
  269. "WorkerThread: **--Forwarding change event--**\n\n");
  270. break;
  271. }
  272. case EVENT_STACK_CHANGE:
  273. {
  274. Trace0(GLOBAL,
  275. "WorkerThread: Stack Change event received");
  276. UpdateDefaultRoutes();
  277. dwResult = NotifyRouteChangeEx(&hTemp,
  278. &RouteChangeOverlapped,
  279. TRUE);
  280. if((dwResult isnot NO_ERROR) and
  281. (dwResult isnot ERROR_IO_PENDING))
  282. {
  283. Trace1(ERR,
  284. "WorkerThread: Error %d from NotifyRouteChangeEx",
  285. dwResult);
  286. //
  287. // If there was an error, try again
  288. //
  289. NotifyRouteChangeEx(&hTemp,
  290. &RouteChangeOverlapped,
  291. TRUE);
  292. }
  293. break;
  294. }
  295. case EVENT_ROUTINGPROTOCOL:
  296. {
  297. Trace0(GLOBAL,
  298. "WorkerThread: Routing protocol notification received");
  299. HandleRoutingProtocolNotification() ;
  300. if((RouterState.IRS_State is RTR_STATE_STOPPING) and
  301. IsListEmpty(&ICBList) and
  302. AllRoutingProtocolsStopped())
  303. {
  304. __leave;
  305. }
  306. break ;
  307. }
  308. case EVENT_RASADVTIMER:
  309. {
  310. EnterCriticalSection(&RouterStateLock);
  311. if(RouterState.IRS_State isnot RTR_STATE_RUNNING)
  312. {
  313. Trace0(IF,
  314. "WorkerThread: Router discovery timer fired while shutting down. Ignoring");
  315. LeaveCriticalSection(&RouterStateLock);
  316. break;
  317. }
  318. LeaveCriticalSection(&RouterStateLock);
  319. Trace0(MCAST,
  320. "WorkerThread: RasAdv Timer event received");
  321. HandleRasAdvTimer();
  322. break;
  323. }
  324. case EVENT_RTRDISCTIMER:
  325. {
  326. PLIST_ENTRY pleTimerNode;
  327. PROUTER_DISC_CB pDiscCb;
  328. EnterCriticalSection(&RouterStateLock);
  329. if(RouterState.IRS_State isnot RTR_STATE_RUNNING)
  330. {
  331. Trace0(IF,
  332. "WorkerThread: Router discovery timer fired while shutting down. Ignoring");
  333. LeaveCriticalSection(&RouterStateLock);
  334. break;
  335. }
  336. LeaveCriticalSection(&RouterStateLock);
  337. ENTER_WRITER(ICB_LIST);
  338. Trace0(RTRDISC,
  339. "WorkerThread: Router Discovery Timer event received");
  340. if(IsListEmpty(&g_leTimerQueueHead))
  341. {
  342. //
  343. // Someone removed the timer item from under us
  344. // and happened to empty the timer queue. Since we
  345. // are a non-periodic timer, we will not
  346. // fire again so no problem
  347. //
  348. Trace0(RTRDISC,
  349. "WorkerThread: Router Discovery Timer went off but no timer items");
  350. EXIT_LOCK(ICB_LIST);
  351. break;
  352. }
  353. HandleRtrDiscTimer();
  354. EXIT_LOCK(ICB_LIST);
  355. break;
  356. }
  357. case EVENT_RTRDISCSOCKET:
  358. {
  359. EnterCriticalSection(&RouterStateLock);
  360. if(RouterState.IRS_State isnot RTR_STATE_RUNNING)
  361. {
  362. Trace0(IF,
  363. "WorkerThread: FD_READ while shutting down. Ignoring");
  364. LeaveCriticalSection(&RouterStateLock);
  365. break;
  366. }
  367. LeaveCriticalSection(&RouterStateLock);
  368. ENTER_WRITER(ICB_LIST);
  369. HandleSolicitations();
  370. EXIT_LOCK(ICB_LIST);
  371. break;
  372. }
  373. case EVENT_MCMISCSOCKET:
  374. {
  375. EnterCriticalSection(&RouterStateLock);
  376. if(RouterState.IRS_State isnot RTR_STATE_RUNNING)
  377. {
  378. Trace0(IF,
  379. "WorkerThread: FD_READ while shutting down. Ignoring");
  380. LeaveCriticalSection(&RouterStateLock);
  381. break;
  382. }
  383. LeaveCriticalSection(&RouterStateLock);
  384. HandleMcMiscMessages();
  385. break;
  386. }
  387. case EVENT_MZAPTIMER:
  388. {
  389. EnterCriticalSection(&RouterStateLock);
  390. if(RouterState.IRS_State isnot RTR_STATE_RUNNING)
  391. {
  392. Trace0(IF,
  393. "WorkerThread: Router discovery timer fired while shutting down. Ignoring");
  394. LeaveCriticalSection(&RouterStateLock);
  395. break;
  396. }
  397. LeaveCriticalSection(&RouterStateLock);
  398. HandleMzapTimer();
  399. break;
  400. }
  401. case EVENT_MZAPSOCKET:
  402. {
  403. EnterCriticalSection(&RouterStateLock);
  404. if(RouterState.IRS_State isnot RTR_STATE_RUNNING)
  405. {
  406. Trace0(IF,
  407. "WorkerThread: FD_READ while shutting down. Ignoring");
  408. LeaveCriticalSection(&RouterStateLock);
  409. break;
  410. }
  411. LeaveCriticalSection(&RouterStateLock);
  412. HandleMZAPMessages();
  413. break;
  414. }
  415. case EVENT_MCAST_0:
  416. case EVENT_MCAST_1:
  417. case EVENT_MCAST_2:
  418. {
  419. HandleMcastNotification(eventindex - EVENT_MCAST_0);
  420. break;
  421. }
  422. case EVENT_ROUTE_CHANGE_0:
  423. case EVENT_ROUTE_CHANGE_1:
  424. case EVENT_ROUTE_CHANGE_2:
  425. {
  426. HandleRouteChangeNotification(
  427. eventindex - EVENT_ROUTE_CHANGE_0
  428. );
  429. break;
  430. }
  431. default:
  432. {
  433. Trace1(ERR,
  434. "WorkerThread: Wait failed with following error %d",
  435. GetLastError());
  436. break;
  437. }
  438. }
  439. }
  440. }
  441. __finally
  442. {
  443. Trace0(GLOBAL,
  444. "WorkerThread: Worker thread stopping");
  445. RouterManagerCleanup();
  446. RouterState.IRS_State = RTR_STATE_STOPPED;
  447. (RouterStopped) (PID_IP, 0);
  448. }
  449. FreeLibraryAndExitThread(g_hOwnModule,
  450. NO_ERROR);
  451. return NO_ERROR;
  452. }
  453. VOID
  454. WaitForAPIsToExitBeforeStopping(
  455. VOID
  456. )
  457. {
  458. DWORD sleepcount = 0 ;
  459. TraceEnter("WaitForAPIsToExitBeforeStopping");
  460. //
  461. // Wait for refcount to trickle down to zero: this indicates that no
  462. // threads are in the router now
  463. //
  464. while(RouterState.IRS_RefCount != 0)
  465. {
  466. if (sleepcount++ > 20)
  467. {
  468. Trace0(ERR,
  469. "WaitForAPIsToExitBeforeStopping: RouterState.IRS_Refcount not decreasing");
  470. }
  471. Sleep (200L);
  472. }
  473. TraceLeave("WaitForAPIsToExitBeforeStopping");
  474. }