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.

716 lines
16 KiB

  1. //=============================================================================
  2. // Copyright (c) 1998 Microsoft Corporation
  3. // File Name: main.c
  4. // Abstract:
  5. //
  6. // Author: K.S.Lokesh (lokeshs@) 1-1-98
  7. //=============================================================================
  8. #include "pchdvmrp.h"
  9. #pragma hdrstop
  10. GLOBALS Globals;
  11. GLOBALS1 Globals1;
  12. GLOBAL_CONFIG GlobalConfig;
  13. //----------------------------------------------------------------------------
  14. // _DLLMAIN
  15. //
  16. // Called when the dll is being loaded/unloaded
  17. //----------------------------------------------------------------------------
  18. BOOL
  19. WINAPI
  20. DLLMAIN (
  21. HINSTANCE Module,
  22. DWORD Reason,
  23. LPVOID Reserved
  24. )
  25. {
  26. BOOL NoError;
  27. switch (Reason) {
  28. case DLL_PROCESS_ATTACH:
  29. {
  30. DisableThreadLibraryCalls(Module);
  31. // create and initialize global data
  32. NoError = DllStartup();
  33. break;
  34. }
  35. case DLL_PROCESS_DETACH:
  36. {
  37. // free global data
  38. NoError = DllCleanup();
  39. break;
  40. }
  41. default:
  42. {
  43. NoError = TRUE;
  44. break;
  45. }
  46. }
  47. return NoError;
  48. } //end _DLLMAIN
  49. //----------------------------------------------------------------------------
  50. // _DllStartup
  51. //
  52. // Initializes Globals1 structure
  53. //----------------------------------------------------------------------------
  54. BOOL
  55. DllStartup(
  56. )
  57. {
  58. BEGIN_BREAKOUT_BLOCK1 {
  59. //
  60. // create a private heap for dvmrp
  61. //
  62. Globals1.Heap = HeapCreate(0, 0, 0);
  63. if (Globals1.Heap == NULL) {
  64. GOTO_END_BLOCK1;
  65. }
  66. try {
  67. // initialize the Router Manager event queue
  68. CREATE_LOCKED_LIST(&Globals1.RtmQueue);
  69. // create WorkItem CS
  70. InitializeCriticalSection(&Globals1.WorkItemCS);
  71. }
  72. except (EXCEPTION_EXECUTE_HANDLER) {
  73. GOTO_END_BLOCK1;
  74. }
  75. // if reached here, then return no error.
  76. return TRUE;
  77. } END_BREAKOUT_BLOCK1;
  78. // there was some error. Cleanup before returning error.
  79. DllCleanup();
  80. return FALSE;
  81. }
  82. //----------------------------------------------------------------------------
  83. // _DllCleanup
  84. //
  85. // This function is called when the dll is being unloaded. It frees any global
  86. // structures set in _DllStartup
  87. //----------------------------------------------------------------------------
  88. BOOL
  89. DllCleanup(
  90. )
  91. {
  92. // destroy the router manager event queue
  93. if (LOCKED_LIST_CREATED(&Globals1.RtmQueue)) {
  94. DELETE_LOCKED_LIST(&Globals1.RtmQueue, EVENT_QUEUE_ENTRY, Link);
  95. }
  96. // delete WorkItem CS
  97. DeleteCriticalSection(&Globals1.WorkItemCS);
  98. // destroy private heap
  99. if (Globals1.Heap != NULL) {
  100. HeapDestroy(Globals1.Heap);
  101. }
  102. return TRUE;
  103. }
  104. //----------------------------------------------------------------------------
  105. // _RegisterProtocol
  106. //
  107. // This function is called after the Dll is loaded, and before StartProtocol
  108. // is called. It checks to ensure that the correct version is being configured
  109. //
  110. // No deinitialization is required for this function call.
  111. //----------------------------------------------------------------------------
  112. DWORD
  113. WINAPI
  114. RegisterProtocol(
  115. IN OUT PMPR_ROUTING_CHARACTERISTICS pRoutingChar,
  116. IN OUT PMPR_SERVICE_CHARACTERISTICS pServiceChar
  117. )
  118. {
  119. DWORD Error = NO_ERROR;
  120. //
  121. // initialize tracing and error logging
  122. //
  123. INITIALIZE_TRACING_LOGGING();
  124. Trace0(ENTER, "RegisterProtocol()");
  125. //
  126. // The Router Manager should be calling us to register our protocol.
  127. // The Router Manager must be atleast the version we are compiled with
  128. // The Router Manager must support routing and multicast.
  129. //
  130. #ifdef MS_IP_DVMRP
  131. if(pRoutingChar->dwProtocolId != MS_IP_DVMRP)
  132. return ERROR_NOT_SUPPORTED;
  133. #endif
  134. if(pRoutingChar->dwVersion < MS_ROUTER_VERSION)
  135. return ERROR_NOT_SUPPORTED;
  136. if(!(pRoutingChar->fSupportedFunctionality & RF_ROUTING)
  137. || !(pRoutingChar->fSupportedFunctionality & RF_MULTICAST) )
  138. return ERROR_NOT_SUPPORTED;
  139. //
  140. // We setup our characteristics and function pointers
  141. // All pointers should be set to NULL by the caller.
  142. //
  143. pServiceChar->fSupportedFunctionality = 0;
  144. pRoutingChar->fSupportedFunctionality = RF_MULTICAST | RF_ROUTING;
  145. pRoutingChar->pfnStartProtocol = StartProtocol;
  146. pRoutingChar->pfnStartComplete = StartComplete;
  147. pRoutingChar->pfnStopProtocol = StopProtocol;
  148. pRoutingChar->pfnAddInterface = AddInterface;
  149. pRoutingChar->pfnDeleteInterface = DeleteInterface;
  150. pRoutingChar->pfnInterfaceStatus = InterfaceStatus;
  151. pRoutingChar->pfnGetEventMessage = GetEventMessage;
  152. pRoutingChar->pfnGetInterfaceInfo = GetInterfaceConfigInfo;
  153. pRoutingChar->pfnSetInterfaceInfo = SetInterfaceConfigInfo;
  154. pRoutingChar->pfnGetGlobalInfo = GetGlobalInfo;
  155. pRoutingChar->pfnSetGlobalInfo = SetGlobalInfo;
  156. pRoutingChar->pfnMibCreateEntry = MibCreate;
  157. pRoutingChar->pfnMibDeleteEntry = MibDelete;
  158. pRoutingChar->pfnMibGetEntry = MibGet;
  159. pRoutingChar->pfnMibSetEntry = MibSet;
  160. pRoutingChar->pfnMibGetFirstEntry = MibGetFirst;
  161. pRoutingChar->pfnMibGetNextEntry = MibGetNext;
  162. pRoutingChar->pfnUpdateRoutes = NULL;
  163. pRoutingChar->pfnConnectClient = NULL;
  164. pRoutingChar->pfnDisconnectClient = NULL;
  165. pRoutingChar->pfnGetNeighbors = NULL;
  166. pRoutingChar->pfnGetMfeStatus = NULL;
  167. pRoutingChar->pfnQueryPower = NULL;
  168. pRoutingChar->pfnSetPower = NULL;
  169. Trace0(LEAVE, "Leaving RegisterProtocol():\n");
  170. return NO_ERROR;
  171. } //end _RegisterProtocol
  172. //----------------------------------------------------------------------------
  173. // _StartProtocol
  174. //
  175. // Initializes global structures
  176. //----------------------------------------------------------------------------
  177. DWORD
  178. WINAPI
  179. StartProtocol(
  180. IN HANDLE RtmNotifyEvent, //notify Rtm when dvmrp stopped
  181. IN PSUPPORT_FUNCTIONS pSupportFunctions, //NULL
  182. IN PVOID pDvmrpGlobalConfig,
  183. IN ULONG StructureVersion,
  184. IN ULONG StructureSize,
  185. IN ULONG StructureCount
  186. )
  187. {
  188. DWORD Error=NO_ERROR;
  189. BOOL IsError;
  190. //
  191. // initialize tracing and error logging if StartProtocol called after
  192. // StopProtocol
  193. //
  194. INITIALIZE_TRACING_LOGGING();
  195. //
  196. // acquire global lock
  197. //
  198. ACQUIRE_WORKITEM_LOCK("_StartProtocol");
  199. //
  200. // make certain dvmrp is not already running (StartProtocol might get
  201. // called before StopProtocol completes)
  202. //
  203. if (Globals1.RunningStatus != DVMRP_STATUS_STOPPED) {
  204. Trace0(ERR,
  205. "Error: _StartProtocol called when dvmrp is already running");
  206. Logwarn0(DVMRP_ALREADY_STARTED, NO_ERROR);
  207. RELEASE_WORKITEM_LOCK("_StartProtocol");
  208. return ERROR_CAN_NOT_COMPLETE;
  209. }
  210. IsError = TRUE;
  211. BEGIN_BREAKOUT_BLOCK1 {
  212. // save the Router Manager notification event
  213. Globals.RtmNotifyEvent = RtmNotifyEvent;
  214. //
  215. // set the Global Config (after validating it)
  216. //
  217. if(pDvmrpGlobalConfig == NULL) {
  218. Trace0(ERR, "_StartProtocol: Called with NULL global config");
  219. Error = ERROR_INVALID_PARAMETER;
  220. GOTO_END_BLOCK1;
  221. }
  222. {
  223. PDVMRP_GLOBAL_CONFIG pGlobalConfig;
  224. pGlobalConfig = (PDVMRP_GLOBAL_CONFIG) pDvmrpGlobalConfig;
  225. // Check the global config, and correct if values are not correct.
  226. // Not a fatal error.
  227. if (! ValidateGlobalConfig(pGlobalConfig, StructureSize)) {
  228. Error = ERROR_INVALID_PARAMETER;
  229. GOTO_END_BLOCK1;
  230. }
  231. memcpy(&GlobalConfig, pGlobalConfig, sizeof(GlobalConfig));
  232. }
  233. //
  234. // Initialize Winsock version 2.0
  235. //
  236. {
  237. WSADATA WsaData;
  238. Error = (DWORD)WSAStartup(MAKEWORD(2,0), &WsaData);
  239. if ( (Error!=0) || (LOBYTE(WsaData.wVersion)<2) ) {
  240. Trace1(ERR,
  241. "StartProtocol:Error %d:could not initialize winsock v-2",
  242. Error);
  243. Logerr0(WSASTARTUP_FAILED, Error);
  244. if (LOBYTE(WsaData.wVersion)<2)
  245. WSACleanup();
  246. GOTO_END_BLOCK1;
  247. }
  248. }
  249. //
  250. // Initialise the Dynamic CS and ReadWrite locks main struct
  251. //
  252. Error = InitializeDynamicLocks(&Globals.DynamicCSStore);
  253. if (Error!=NO_ERROR) {
  254. GOTO_END_BLOCK1;
  255. }
  256. Error = InitializeDynamicLocks(&Globals.DynamicRWLStore);
  257. if (Error!=NO_ERROR) {
  258. GOTO_END_BLOCK1;
  259. }
  260. //
  261. // Initialize Interface Table
  262. //
  263. InitializeIfTable();
  264. IsError = FALSE;
  265. } END_BREAKOUT_BLOCK1;
  266. if (IsError) {
  267. Trace1(START, "Dvmrp could not be started: %d", Error);
  268. ProtocolCleanup();
  269. }
  270. else {
  271. Trace0(START, "Dvmrp started successfully");
  272. Loginfo0(DVMRP_STARTED, NO_ERROR);
  273. }
  274. RELEASE_WORKITEM_LOCK("_StartProtocol()");
  275. Trace1(LEAVE, "Leaving StartProtocol():%d\n", Error);
  276. return Error;
  277. } //end _StartProtocol
  278. //----------------------------------------------------------------------------
  279. // _ValidateGlobalConfig
  280. //----------------------------------------------------------------------------
  281. DWORD
  282. ValidateGlobalConfig(
  283. PDVMRP_GLOBAL_CONFIG pGlobalConfig,
  284. DWORD StructureSize
  285. )
  286. {
  287. //
  288. // check structure size
  289. //
  290. if (StructureSize != sizeof(DVMRP_GLOBAL_CONFIG)) {
  291. Trace1(ERR, "Dvmrp global config size too small.\n", StructureSize);
  292. return ERROR_INVALID_DATA;
  293. }
  294. DebugPrintGlobalConfig(pGlobalConfig);
  295. //
  296. // check version
  297. //
  298. if (pGlobalConfig->MajorVersion != 3) {
  299. Trace1(ERR, "Invalid version:%d in global config.",
  300. pGlobalConfig->MajorVersion);
  301. Logerr1(INVALID_VERSION, "%d", pGlobalConfig->MajorVersion,
  302. ERROR_INVALID_DATA);
  303. return ERROR_INVALID_DATA;
  304. }
  305. // check loggingLevel
  306. switch (pGlobalConfig->LoggingLevel) {
  307. case DVMRP_LOGGING_NONE :
  308. case DVMRP_LOGGING_ERROR :
  309. case DVMRP_LOGGING_WARN :
  310. case DVMRP_LOGGING_INFO :
  311. break;
  312. default :
  313. {
  314. Trace1(ERR, "Invalid value:%d for LoggingLevel in global config.",
  315. pGlobalConfig->LoggingLevel);
  316. return ERROR_INVALID_DATA;
  317. }
  318. }
  319. //
  320. // check RouteReportInterval (min 10 sec)
  321. //
  322. if (pGlobalConfig->RouteReportInterval != DVMRP_ROUTE_REPORT_INTERVAL) {
  323. Trace2(CONFIG,
  324. "RouteReportInterval being set to %d. Suggested value:%d",
  325. pGlobalConfig->RouteReportInterval, DVMRP_ROUTE_REPORT_INTERVAL);
  326. }
  327. if (pGlobalConfig->RouteReportInterval < 10000) {
  328. Trace2(ERR,
  329. "RouteReportInterval has very low value:%d, suggested:%d",
  330. pGlobalConfig->RouteReportInterval, DVMRP_ROUTE_REPORT_INTERVAL);
  331. return ERROR_INVALID_DATA;
  332. }
  333. //
  334. // check RouteExpirationInterval (min 40)
  335. //
  336. if (pGlobalConfig->RouteExpirationInterval
  337. != DVMRP_ROUTE_EXPIRATION_INTERVAL
  338. ) {
  339. Trace2(CONFIG,
  340. "RouteExpirationInterval being set to %d. Suggested value:%d",
  341. pGlobalConfig->RouteExpirationInterval,
  342. DVMRP_ROUTE_EXPIRATION_INTERVAL);
  343. }
  344. if (pGlobalConfig->RouteExpirationInterval < (2*10 + 20)) {
  345. Trace2(ERR,
  346. "RouteExpirationInterval has very low value:%d, suggested:%d",
  347. pGlobalConfig->RouteExpirationInterval,
  348. DVMRP_ROUTE_EXPIRATION_INTERVAL);
  349. return ERROR_INVALID_DATA;
  350. }
  351. //
  352. // check RouteHolddownInterval
  353. //
  354. if (pGlobalConfig->RouteHolddownInterval != DVMRP_ROUTE_HOLDDOWN_INTERVAL
  355. ) {
  356. Trace2(CONFIG,
  357. "RouteHolddownInterval being set to %d. Suggested value:%d",
  358. pGlobalConfig->RouteHolddownInterval,
  359. DVMRP_ROUTE_HOLDDOWN_INTERVAL);
  360. }
  361. //
  362. // check PruneLifetimeInterval
  363. //
  364. if (pGlobalConfig->PruneLifetimeInterval != DVMRP_PRUNE_LIFETIME_INTERVAL
  365. ) {
  366. Trace2(CONFIG,
  367. "PruneLifetimeInterval being set to %d. Suggested value:%d\n",
  368. pGlobalConfig->PruneLifetimeInterval,
  369. DVMRP_PRUNE_LIFETIME_INTERVAL);
  370. }
  371. if (pGlobalConfig->PruneLifetimeInterval < 600000) {
  372. Trace2(ERR,
  373. "PruneLifeTime has very low value:%d, suggested:%d",
  374. pGlobalConfig->PruneLifetimeInterval,
  375. DVMRP_PRUNE_LIFETIME_INTERVAL);
  376. return ERROR_INVALID_DATA;
  377. }
  378. return NO_ERROR;
  379. } //end _ValidateGlobalConfig
  380. DWORD
  381. APIENTRY
  382. StartComplete(
  383. VOID
  384. )
  385. {
  386. return NO_ERROR;
  387. }
  388. /*-----------------------------------------------------------------------------
  389. Functions to display the MibTable on the TraceWindow periodically
  390. Locks:
  391. Arguments:
  392. Return Values:
  393. -----------------------------------------------------------------------------*/
  394. DWORD
  395. APIENTRY
  396. StopProtocol(
  397. VOID
  398. )
  399. {
  400. return NO_ERROR;
  401. }
  402. VOID
  403. WF_StopProtocolComplete(
  404. )
  405. {
  406. //
  407. // deregister tracing/error logging if they were
  408. // registered in RegisterProtocol/StartProtocol call
  409. //
  410. DEINITIALIZE_TRACING_LOGGING();
  411. return;
  412. }
  413. VOID
  414. ProtocolCleanup(
  415. )
  416. {
  417. if (Globals.ActivityEvent) {
  418. CloseHandle(Globals.ActivityEvent);
  419. }
  420. ZeroMemory(&Globals, sizeof(Globals));
  421. ZeroMemory(&GlobalConfig, sizeof(GlobalConfig));
  422. }
  423. DWORD
  424. WINAPI
  425. GetGlobalInfo(
  426. IN OUT PVOID pvConfig,
  427. IN OUT PDWORD pdwSize,
  428. IN OUT PULONG pulStructureVersion,
  429. IN OUT PULONG pulStructureSize,
  430. IN OUT PULONG pulStructureCount
  431. )
  432. {
  433. DWORD Error = NO_ERROR;
  434. return Error;
  435. }
  436. DWORD
  437. WINAPI
  438. SetGlobalInfo(
  439. IN PVOID pvConfig,
  440. IN ULONG ulStructureVersion,
  441. IN ULONG ulStructureSize,
  442. IN ULONG ulStructureCount
  443. )
  444. {
  445. DWORD Error = NO_ERROR;
  446. return Error;
  447. }
  448. DWORD
  449. APIENTRY
  450. GetEventMessage(
  451. OUT ROUTING_PROTOCOL_EVENTS *pEvent,
  452. OUT PMESSAGE pResult
  453. )
  454. {
  455. DWORD Error;
  456. //
  457. // Note: _GetEventMessage() does not use the
  458. // EnterIgmpApi()/LeaveIgmpApi() mechanism,
  459. // since it may be called after Igmp has stopped, when the
  460. // Router Manager is retrieving the ROUTER_STOPPED message
  461. //
  462. Trace2(ENTER, "entering _GetEventMessage: pEvent(%08x) pResult(%08x)",
  463. pEvent, pResult);
  464. ACQUIRE_LIST_LOCK(&Globals1.RtmQueue, "RtmQueue", "_GetEventMessage");
  465. Error = DequeueEvent(&Globals1.RtmQueue, pEvent, pResult);
  466. RELEASE_LIST_LOCK(&Globals1.RtmQueue, "RtmQueue", "_GetEventMessage");
  467. Trace1(LEAVE, "leaving _GetEventMessage: %d\n", Error);
  468. return Error;
  469. }
  470. DWORD
  471. DequeueEvent(
  472. PLOCKED_LIST pQueue,
  473. ROUTING_PROTOCOL_EVENTS *pEventType,
  474. PMESSAGE pMsg
  475. )
  476. {
  477. PLIST_ENTRY pHead, pLe;
  478. PEVENT_QUEUE_ENTRY pEqe;
  479. pHead = &pQueue->Link;
  480. if (IsListEmpty(pHead)) {
  481. return ERROR_NO_MORE_ITEMS;
  482. }
  483. pLe = RemoveHeadList(pHead);
  484. pEqe = CONTAINING_RECORD(pLe, EVENT_QUEUE_ENTRY, Link);
  485. *pEventType = pEqe->EventType;
  486. *pMsg = pEqe->Msg;
  487. DVMRP_FREE(pEqe);
  488. return NO_ERROR;
  489. }