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.

844 lines
22 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. nmpnp.c
  5. Abstract:
  6. Network Plug 'N Play and interface state event handling for
  7. the Node Manager.
  8. Author:
  9. Mike Massa (mikemas)
  10. Revision History:
  11. 2/23/98 Created.
  12. --*/
  13. #include "nmp.h"
  14. //
  15. // Private Types
  16. //
  17. typedef struct {
  18. LIST_ENTRY Linkage;
  19. CLUSNET_EVENT_TYPE Type;
  20. DWORD Context1;
  21. DWORD Context2;
  22. } NM_PNP_EVENT, *PNM_PNP_EVENT;
  23. //
  24. // Private Data
  25. //
  26. PCRITICAL_SECTION NmpPnpLock = NULL;
  27. BOOLEAN NmpPnpEnabled = FALSE;
  28. BOOLEAN NmpPnpChangeOccurred = FALSE;
  29. BOOLEAN NmpPnpInitialized = FALSE;
  30. PCLRTL_BUFFER_POOL NmpPnpEventPool = NULL;
  31. PNM_PNP_EVENT NmpPnpShutdownEvent = NULL;
  32. PCL_QUEUE NmpPnpEventQueue = NULL;
  33. HANDLE NmpPnpWorkerThreadHandle = NULL;
  34. LPWSTR NmpPnpAddressString = NULL;
  35. //
  36. // Private Prototypes
  37. //
  38. DWORD
  39. NmpPnpWorkerThread(
  40. LPVOID Context
  41. );
  42. //
  43. // Routines
  44. //
  45. DWORD
  46. NmpInitializePnp(
  47. VOID
  48. )
  49. {
  50. DWORD status;
  51. HANDLE handle;
  52. DWORD threadId;
  53. DWORD maxAddressStringLength;
  54. //
  55. // Create the PnP lock
  56. //
  57. NmpPnpLock = LocalAlloc(LMEM_FIXED, sizeof(CRITICAL_SECTION));
  58. if (NmpPnpLock == NULL) {
  59. ClRtlLogPrint(LOG_CRITICAL, "[NM] Unable to allocate PnP lock.\n");
  60. return(ERROR_NOT_ENOUGH_MEMORY);
  61. }
  62. InitializeCriticalSection(NmpPnpLock);
  63. NmpPnpInitialized = TRUE;
  64. //
  65. // Allocate a buffer pool for PnP event contexts
  66. //
  67. NmpPnpEventPool = ClRtlCreateBufferPool(
  68. sizeof(NM_PNP_EVENT),
  69. 5,
  70. CLRTL_MAX_POOL_BUFFERS,
  71. NULL,
  72. NULL
  73. );
  74. if (NmpPnpEventPool == NULL) {
  75. status = ERROR_NOT_ENOUGH_MEMORY;
  76. ClRtlLogPrint(LOG_CRITICAL,
  77. "[NM] Failed to allocate PnP event pool.\n"
  78. );
  79. goto error_exit;
  80. }
  81. //
  82. // Pre-allocate the shutdown event
  83. //
  84. NmpPnpShutdownEvent = ClRtlAllocateBuffer(NmpPnpEventPool);
  85. if (NmpPnpShutdownEvent == NULL) {
  86. status = ERROR_NOT_ENOUGH_MEMORY;
  87. ClRtlLogPrint(LOG_CRITICAL,
  88. "[NM] Failed to allocate PnP shutdown event.\n"
  89. );
  90. goto error_exit;
  91. }
  92. NmpPnpShutdownEvent->Type = ClusnetEventNone;
  93. //
  94. // Allocate the PnP event queue
  95. //
  96. NmpPnpEventQueue = LocalAlloc(LMEM_FIXED, sizeof(CL_QUEUE));
  97. if (NmpPnpEventQueue == NULL) {
  98. status = ERROR_NOT_ENOUGH_MEMORY;
  99. ClRtlLogPrint(LOG_CRITICAL,
  100. "[NM] Failed to allocate PnP event queue.\n"
  101. );
  102. goto error_exit;
  103. }
  104. ClRtlInitializeQueue(NmpPnpEventQueue);
  105. ClRtlQueryTcpipInformation(&maxAddressStringLength, NULL, NULL);
  106. NmpPnpAddressString = LocalAlloc(
  107. LMEM_FIXED,
  108. (maxAddressStringLength + 1) * sizeof(WCHAR)
  109. );
  110. if (NmpPnpAddressString == NULL) {
  111. status = ERROR_NOT_ENOUGH_MEMORY;
  112. ClRtlLogPrint(LOG_CRITICAL,
  113. "[NM] Failed to allocate PnP address buffer.\n"
  114. );
  115. goto error_exit;
  116. }
  117. //
  118. // Create PnP worker thread
  119. //
  120. NmpPnpWorkerThreadHandle = CreateThread(
  121. NULL,
  122. 0,
  123. NmpPnpWorkerThread,
  124. NULL,
  125. 0,
  126. &threadId
  127. );
  128. if (NmpPnpWorkerThreadHandle == NULL) {
  129. status = GetLastError();
  130. ClRtlLogPrint(LOG_CRITICAL,
  131. "[NM] Failed to create PnP worker thread, status %1!u!.\n",
  132. status
  133. );
  134. goto error_exit;
  135. }
  136. status = ERROR_SUCCESS;
  137. error_exit:
  138. return(status);
  139. } // NmpInitializePnp
  140. VOID
  141. NmpShutdownPnp(
  142. VOID
  143. )
  144. {
  145. if (!NmpPnpInitialized) {
  146. return;
  147. }
  148. if (NmpPnpWorkerThreadHandle != NULL) {
  149. //
  150. // Post shutdown event to queue
  151. //
  152. ClRtlInsertTailQueue(
  153. NmpPnpEventQueue,
  154. &(NmpPnpShutdownEvent->Linkage)
  155. );
  156. //
  157. // Wait for the worker thread to terminate
  158. //
  159. WaitForSingleObject(NmpPnpWorkerThreadHandle, INFINITE);
  160. CloseHandle(NmpPnpWorkerThreadHandle);
  161. NmpPnpWorkerThreadHandle = NULL;
  162. }
  163. return;
  164. } // NmpShutdownPnp
  165. VOID
  166. NmpCleanupPnp(
  167. VOID
  168. )
  169. {
  170. if (!NmpPnpInitialized) {
  171. return;
  172. }
  173. if (NmpPnpEventQueue != NULL) {
  174. LIST_ENTRY eventList;
  175. PLIST_ENTRY entry;
  176. PNM_PNP_EVENT event;
  177. ClRtlRundownQueue(NmpPnpEventQueue, &eventList);
  178. for ( entry = eventList.Flink;
  179. entry != &eventList;
  180. )
  181. {
  182. event = CONTAINING_RECORD(entry, NM_PNP_EVENT, Linkage);
  183. if (event == NmpPnpShutdownEvent) {
  184. NmpPnpShutdownEvent = NULL;
  185. }
  186. entry = entry->Flink;
  187. ClRtlFreeBuffer(event);
  188. }
  189. LocalFree(NmpPnpEventQueue);
  190. NmpPnpEventQueue = NULL;
  191. }
  192. if (NmpPnpEventPool != NULL) {
  193. if (NmpPnpShutdownEvent != NULL) {
  194. ClRtlFreeBuffer(NmpPnpShutdownEvent);
  195. NmpPnpShutdownEvent = NULL;
  196. }
  197. ClRtlDestroyBufferPool(NmpPnpEventPool);
  198. NmpPnpEventPool = NULL;
  199. }
  200. if (NmpPnpAddressString != NULL) {
  201. LocalFree(NmpPnpAddressString);
  202. NmpPnpAddressString = NULL;
  203. }
  204. DeleteCriticalSection(NmpPnpLock);
  205. NmpPnpLock = NULL;
  206. NmpPnpInitialized = FALSE;
  207. return;
  208. } // NmpCleanupPnp
  209. VOID
  210. NmpWatchForPnpEvents(
  211. VOID
  212. )
  213. {
  214. EnterCriticalSection(NmpPnpLock);
  215. NmpPnpChangeOccurred = FALSE;
  216. LeaveCriticalSection(NmpPnpLock);
  217. return;
  218. } // NmpWatchForPnpEvents
  219. DWORD
  220. NmpEnablePnpEvents(
  221. VOID
  222. )
  223. {
  224. DWORD status;
  225. EnterCriticalSection(NmpPnpLock);
  226. if (NmpPnpChangeOccurred) {
  227. status = ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED;
  228. }
  229. else {
  230. NmpPnpEnabled = TRUE;
  231. status = ERROR_SUCCESS;
  232. }
  233. LeaveCriticalSection(NmpPnpLock);
  234. return(status);
  235. } // NmpEnablePnpEvents
  236. VOID
  237. NmPostPnpEvent(
  238. IN CLUSNET_EVENT_TYPE EventType,
  239. IN DWORD Context1,
  240. IN DWORD Context2
  241. )
  242. {
  243. PNM_PNP_EVENT event;
  244. event = ClRtlAllocateBuffer(NmpPnpEventPool);
  245. if (event != NULL) {
  246. event->Type = EventType;
  247. event->Context1 = Context1;
  248. event->Context2 = Context2;
  249. ClRtlInsertTailQueue(NmpPnpEventQueue, &(event->Linkage));
  250. }
  251. else {
  252. ClRtlLogPrint(LOG_CRITICAL,
  253. "[NM] Failed to allocate PnP event.\n"
  254. );
  255. }
  256. return;
  257. } // NmPostPnpEvent
  258. VOID
  259. NmpProcessPnpAddAddressEvent(
  260. IN LPWSTR Address
  261. )
  262. {
  263. DWORD status;
  264. PNM_NETWORK_ENUM networkEnum;
  265. PNM_INTERFACE_ENUM2 interfaceEnum;
  266. DWORD matchedNetworkCount;
  267. DWORD newNetworkCount;
  268. DWORD retryCount = 0;
  269. //
  270. // We will retry this operation a few times in case multiple nodes
  271. // race to create a network that has just been powered up.
  272. //
  273. do {
  274. networkEnum = NULL;
  275. interfaceEnum = NULL;
  276. matchedNetworkCount = 0;
  277. newNetworkCount = 0;
  278. NmpAcquireLock();
  279. //
  280. // Obtain the network and interface definitions.
  281. //
  282. status = NmpEnumNetworkObjects(&networkEnum);
  283. if (status == ERROR_SUCCESS) {
  284. status = NmpEnumInterfaceObjects(&interfaceEnum);
  285. NmpReleaseLock();
  286. if (status == ERROR_SUCCESS) {
  287. //
  288. // Run the network configuration engine. This will
  289. // update the cluster database.
  290. //
  291. status = NmpConfigureNetworks(
  292. NULL,
  293. NmLocalNodeIdString,
  294. NmLocalNodeName,
  295. &networkEnum,
  296. &interfaceEnum,
  297. NmpClusnetEndpoint,
  298. &matchedNetworkCount,
  299. &newNetworkCount,
  300. TRUE // RenameConnectoids
  301. );
  302. if (status == ERROR_SUCCESS) {
  303. ClRtlLogPrint(LOG_NOISE,
  304. "[NM] Matched %1!u! networks, created %2!u! new "
  305. "networks.\n",
  306. matchedNetworkCount,
  307. newNetworkCount
  308. );
  309. }
  310. else {
  311. ClRtlLogPrint(LOG_CRITICAL,
  312. "[NM] Failed to configure networks & interfaces, "
  313. "attempt #%1!u!, status %2!u!.\n",
  314. (retryCount + 1),
  315. status
  316. );
  317. }
  318. if (interfaceEnum != NULL) {
  319. ClNetFreeInterfaceEnum(interfaceEnum);
  320. }
  321. }
  322. else {
  323. ClRtlLogPrint(
  324. LOG_UNUSUAL,
  325. "[NM] Failed to obtain current interface configuration, "
  326. "status %1!u!\n",
  327. status
  328. );
  329. }
  330. if (networkEnum != NULL) {
  331. ClNetFreeNetworkEnum(networkEnum);
  332. }
  333. }
  334. else {
  335. NmpReleaseLock();
  336. ClRtlLogPrint(
  337. LOG_UNUSUAL,
  338. "[NM] Failed to obtain current network configuration, "
  339. "status %1!u!\n",
  340. status
  341. );
  342. }
  343. } while ((status != ERROR_SUCCESS) && (++retryCount <= 3));
  344. return;
  345. } // NmpProcessPnpAddAddressEvent
  346. VOID
  347. NmpProcessPnpDelAddressEvent(
  348. IN LPWSTR Address
  349. )
  350. {
  351. PLIST_ENTRY entry;
  352. PNM_INTERFACE netInterface;
  353. BOOLEAN networkDeleted;
  354. //
  355. // Check if this address corresponds to an interface for
  356. // the local node.
  357. //
  358. NmpAcquireLock();
  359. for (entry = NmLocalNode->InterfaceList.Flink;
  360. entry != &(NmLocalNode->InterfaceList);
  361. entry = entry->Flink
  362. )
  363. {
  364. netInterface = CONTAINING_RECORD(
  365. entry,
  366. NM_INTERFACE,
  367. NodeLinkage
  368. );
  369. if (lstrcmpW(
  370. Address,
  371. netInterface->Address
  372. ) == 0
  373. )
  374. {
  375. //
  376. // Delete the interface from the cluster.
  377. //
  378. NmpGlobalDeleteInterface(
  379. (LPWSTR) OmObjectId(netInterface),
  380. &networkDeleted
  381. );
  382. break;
  383. }
  384. }
  385. if (entry == &(NmLocalNode->InterfaceList)) {
  386. ClRtlLogPrint(LOG_NOISE,
  387. "[NM] Deleted address does not correspond to a cluster "
  388. "interface.\n"
  389. );
  390. }
  391. NmpReleaseLock();
  392. return;
  393. } // NmpProcessPnpDelAddressEvent
  394. DWORD
  395. NmpPnpWorkerThread(
  396. LPVOID Context
  397. )
  398. {
  399. PLIST_ENTRY entry;
  400. PNM_PNP_EVENT event;
  401. BOOL again = TRUE;
  402. DWORD status;
  403. while (again) {
  404. entry = ClRtlRemoveHeadQueue(NmpPnpEventQueue);
  405. if (entry == NULL) {
  406. //
  407. // Time to exit
  408. //
  409. NmpPnpShutdownEvent = NULL;
  410. break;
  411. }
  412. event = CONTAINING_RECORD(entry, NM_PNP_EVENT, Linkage);
  413. if (event->Type == ClusnetEventNone) {
  414. //
  415. // Time to exit
  416. //
  417. again = FALSE;
  418. NmpPnpShutdownEvent = NULL;
  419. }
  420. else if (event->Type == ClusnetEventNetInterfaceUp) {
  421. NmpReportLocalInterfaceStateEvent(
  422. event->Context1,
  423. event->Context2,
  424. ClusterNetInterfaceUp
  425. );
  426. }
  427. else if (event->Type == ClusnetEventNetInterfaceUnreachable) {
  428. NmpReportLocalInterfaceStateEvent(
  429. event->Context1,
  430. event->Context2,
  431. ClusterNetInterfaceUnreachable
  432. );
  433. }
  434. else if (event->Type == ClusnetEventNetInterfaceFailed) {
  435. NmpReportLocalInterfaceStateEvent(
  436. event->Context1,
  437. event->Context2,
  438. ClusterNetInterfaceFailed
  439. );
  440. }
  441. else if ( (event->Type == ClusnetEventAddAddress) ||
  442. (event->Type == ClusnetEventDelAddress)
  443. )
  444. {
  445. //
  446. // This is a PnP event.
  447. //
  448. EnterCriticalSection(NmpPnpLock);
  449. if (NmpPnpEnabled) {
  450. LeaveCriticalSection(NmpPnpLock);
  451. status = ClRtlTcpipAddressToString(
  452. event->Context1,
  453. &NmpPnpAddressString
  454. );
  455. if (status == ERROR_SUCCESS) {
  456. if (event->Type == ClusnetEventAddAddress) {
  457. ClRtlLogPrint(LOG_NOISE,
  458. "[NM] Processing PnP add event for address "
  459. "%1!ws!.\n",
  460. NmpPnpAddressString
  461. );
  462. NmpProcessPnpAddAddressEvent(NmpPnpAddressString);
  463. }
  464. else {
  465. ClRtlLogPrint(LOG_NOISE,
  466. "[NM] Processing PnP delete event for address "
  467. "%1!ws!.\n",
  468. NmpPnpAddressString
  469. );
  470. NmpProcessPnpDelAddressEvent(NmpPnpAddressString);
  471. }
  472. }
  473. else {
  474. ClRtlLogPrint(LOG_UNUSUAL,
  475. "[NM] Failed to convert PnP address %1!x! to string, "
  476. "status %2!u!.\n",
  477. event->Context1,
  478. status
  479. );
  480. }
  481. }
  482. else {
  483. //
  484. // We are not ready to handle PnP events yet.
  485. // Note that something changed. This will cause the join/form
  486. // process to eventually abort.
  487. //
  488. NmpPnpChangeOccurred = TRUE;
  489. LeaveCriticalSection(NmpPnpLock);
  490. ClRtlLogPrint(
  491. LOG_NOISE,
  492. "[NM] Discarding Pnp notification - handling not "
  493. "enabled.\n"
  494. );
  495. }
  496. }
  497. else {
  498. ClRtlLogPrint(LOG_NOISE,
  499. "[NM] Received unknown PnP event type 0x%1!x!.\n",
  500. event->Type
  501. );
  502. }
  503. ClRtlFreeBuffer(event);
  504. }
  505. ClRtlLogPrint(LOG_NOISE, "[NM] Pnp worker thread terminating.\n");
  506. return(ERROR_SUCCESS);
  507. } // NmpPnpWorkerThread
  508. DWORD
  509. NmpConfigureNetworks(
  510. IN RPC_BINDING_HANDLE JoinSponsorBinding,
  511. IN LPWSTR LocalNodeId,
  512. IN LPWSTR LocalNodeName,
  513. IN PNM_NETWORK_ENUM * NetworkEnum,
  514. IN PNM_INTERFACE_ENUM2 * InterfaceEnum,
  515. IN LPWSTR DefaultEndpoint,
  516. IN OUT LPDWORD MatchedNetworkCount,
  517. IN OUT LPDWORD NewNetworkCount,
  518. IN BOOL RenameConnectoids
  519. )
  520. /*++
  521. Notes:
  522. Must not be called with the NM lock held.
  523. RenameConnectoids is TRUE if connectoid names are to be aligned with
  524. cluster network names. If FALSE, rename the cluster network names to be
  525. like the connectoid names.
  526. --*/
  527. {
  528. DWORD status;
  529. CLNET_CONFIG_LISTS lists;
  530. PLIST_ENTRY listEntry;
  531. PCLNET_CONFIG_ENTRY configEntry;
  532. BOOLEAN networkDeleted;
  533. WCHAR errorString[12];
  534. DWORD eventCode = 0;
  535. DWORD defaultRole = CL_DEFAULT_NETWORK_ROLE;
  536. *MatchedNetworkCount = 0;
  537. *NewNetworkCount = 0;
  538. ClNetInitializeConfigLists(&lists);
  539. //
  540. // Convert the enums to a list
  541. //
  542. status = ClNetConvertEnumsToConfigList(
  543. NetworkEnum,
  544. InterfaceEnum,
  545. LocalNodeId,
  546. &(lists.InputConfigList),
  547. TRUE
  548. );
  549. if (status != ERROR_SUCCESS) {
  550. return(status);
  551. }
  552. //
  553. // Read the default network role from the database.
  554. //
  555. (VOID) DmQueryDword(
  556. DmClusterParametersKey,
  557. CLUSREG_NAME_CLUS_DEFAULT_NETWORK_ROLE,
  558. &defaultRole,
  559. &defaultRole
  560. );
  561. //
  562. // Run the configuration engine. Existing net names take
  563. // precedence over connectoid when joining, otherwise change
  564. // the net name to align with the changed connectoid name.
  565. //
  566. ClRtlLogPrint(LOG_NOISE,
  567. "[NM] Running network configuration engine.\n"
  568. );
  569. status = ClNetConfigureNetworks(
  570. LocalNodeId,
  571. LocalNodeName,
  572. NmpClusnetEndpoint,
  573. defaultRole,
  574. RenameConnectoids,
  575. &lists,
  576. MatchedNetworkCount,
  577. NewNetworkCount
  578. );
  579. if (status != ERROR_SUCCESS) {
  580. goto error_exit;
  581. }
  582. ClRtlLogPrint(LOG_NOISE,
  583. "[NM] Processing network configuration changes.\n"
  584. );
  585. //
  586. // Process the output - The order is important!
  587. //
  588. while (!IsListEmpty(&(lists.DeletedInterfaceList))) {
  589. listEntry = RemoveHeadList(&(lists.DeletedInterfaceList));
  590. configEntry = CONTAINING_RECORD(
  591. listEntry,
  592. CLNET_CONFIG_ENTRY,
  593. Linkage
  594. );
  595. status = NmpDeleteInterface(
  596. JoinSponsorBinding,
  597. configEntry->InterfaceInfo.Id,
  598. configEntry->InterfaceInfo.NetworkId,
  599. &networkDeleted
  600. );
  601. ClNetFreeConfigEntry(configEntry);
  602. if (status != ERROR_SUCCESS) {
  603. goto error_exit;
  604. }
  605. }
  606. while (!IsListEmpty(&(lists.UpdatedInterfaceList))) {
  607. listEntry = RemoveHeadList(&(lists.UpdatedInterfaceList));
  608. configEntry = CONTAINING_RECORD(
  609. listEntry,
  610. CLNET_CONFIG_ENTRY,
  611. Linkage
  612. );
  613. status = NmpSetInterfaceInfo(
  614. JoinSponsorBinding,
  615. &(configEntry->InterfaceInfo)
  616. );
  617. if (status == ERROR_SUCCESS && configEntry->UpdateNetworkName) {
  618. CL_ASSERT(JoinSponsorBinding == NULL);
  619. //
  620. // Note: this function must not be called with the NM lock
  621. // held.
  622. //
  623. status = NmpSetNetworkName(
  624. &(configEntry->NetworkInfo)
  625. );
  626. }
  627. ClNetFreeConfigEntry(configEntry);
  628. if (status != ERROR_SUCCESS) {
  629. goto error_exit;
  630. }
  631. }
  632. while (!IsListEmpty(&(lists.CreatedInterfaceList))) {
  633. listEntry = RemoveHeadList(&(lists.CreatedInterfaceList));
  634. configEntry = CONTAINING_RECORD(
  635. listEntry,
  636. CLNET_CONFIG_ENTRY,
  637. Linkage
  638. );
  639. status = NmpCreateInterface(
  640. JoinSponsorBinding,
  641. &(configEntry->InterfaceInfo)
  642. );
  643. ClNetFreeConfigEntry(configEntry);
  644. if (status != ERROR_SUCCESS) {
  645. goto error_exit;
  646. }
  647. }
  648. while (!IsListEmpty(&(lists.CreatedNetworkList))) {
  649. listEntry = RemoveHeadList(&(lists.CreatedNetworkList));
  650. configEntry = CONTAINING_RECORD(
  651. listEntry,
  652. CLNET_CONFIG_ENTRY,
  653. Linkage
  654. );
  655. status = NmpCreateNetwork(
  656. JoinSponsorBinding,
  657. &(configEntry->NetworkInfo),
  658. &(configEntry->InterfaceInfo)
  659. );
  660. ClNetFreeConfigEntry(configEntry);
  661. if (status != ERROR_SUCCESS) {
  662. goto error_exit;
  663. }
  664. }
  665. error_exit:
  666. if (eventCode != 0) {
  667. wsprintfW(&(errorString[0]), L"%u", status);
  668. CsLogEvent1(LOG_CRITICAL, eventCode, errorString);
  669. }
  670. ClNetFreeConfigLists(&lists);
  671. return(status);
  672. } // NmpConfigureNetworks
  673.